Commit b635eb2f by Per Bothner

parse.y (complete_loop_body): Rename to finish_loop_body.

d
	* parse.y (complete_loop_body):  Rename to finish_loop_body.
 	(complete_labeled_statement):  Rename to finish_labeled_statement.
	(complete_for_loop):  Rename to finish_for_loop.
	(complete_method_declaration):  Rename to finish_method_declaration.
	* java-tree.h (continue_identifier_node):  New global node.
	* decl.c:  Define and initialize continue_identifier_node.
	* parse.y (generate_labeled_block):  Remove - no longer needed.
	(build_loop_body):  Use continue_identifier_node for continue block.
	(finish_labeled_statement):  Also do pop_labeled_block actions.
	(java_complete_lhs):  POP_LOOP even if error.
	(build_labeled_block):  Special handling for continue_identifier_node.
	(patch_loop_statement):  Re-organize.
	(patch_bc_statement):  Re-write.

From-SVN: r26015
parent 40b5a77c
...@@ -221,6 +221,7 @@ extern tree void_signature_node; /* "()V" */ ...@@ -221,6 +221,7 @@ extern tree void_signature_node; /* "()V" */
extern tree length_identifier_node; /* "length" */ extern tree length_identifier_node; /* "length" */
extern tree this_identifier_node; /* "this" */ extern tree this_identifier_node; /* "this" */
extern tree super_identifier_node; /* "super" */ extern tree super_identifier_node; /* "super" */
extern tree continue_identifier_node; /* "continue" */
extern tree one_elt_array_domain_type; extern tree one_elt_array_domain_type;
extern tree void_type_node; extern tree void_type_node;
extern tree ptr_type_node; extern tree ptr_type_node;
......
...@@ -186,16 +186,15 @@ static tree add_stmt_to_compound PROTO ((tree, tree, tree)); ...@@ -186,16 +186,15 @@ static tree add_stmt_to_compound PROTO ((tree, tree, tree));
static tree add_stmt_to_block PROTO ((tree, tree, tree)); static tree add_stmt_to_block PROTO ((tree, tree, tree));
static tree patch_exit_expr PROTO ((tree)); static tree patch_exit_expr PROTO ((tree));
static tree build_labeled_block PROTO ((int, tree)); static tree build_labeled_block PROTO ((int, tree));
static tree generate_labeled_block PROTO (()); static tree finish_labeled_statement PROTO ((tree, tree));
static tree complete_labeled_statement PROTO ((tree, tree));
static tree build_bc_statement PROTO ((int, int, tree)); static tree build_bc_statement PROTO ((int, int, tree));
static tree patch_bc_statement PROTO ((tree)); static tree patch_bc_statement PROTO ((tree));
static tree patch_loop_statement PROTO ((tree)); static tree patch_loop_statement PROTO ((tree));
static tree build_new_loop PROTO ((tree)); static tree build_new_loop PROTO ((tree));
static tree build_loop_body PROTO ((int, tree, int)); static tree build_loop_body PROTO ((int, tree, int));
static tree complete_loop_body PROTO ((int, tree, tree, int)); static tree finish_loop_body PROTO ((int, tree, tree, int));
static tree build_debugable_stmt PROTO ((int, tree)); static tree build_debugable_stmt PROTO ((int, tree));
static tree complete_for_loop PROTO ((int, tree, tree, tree)); static tree finish_for_loop PROTO ((int, tree, tree, tree));
static tree patch_switch_statement PROTO ((tree)); static tree patch_switch_statement PROTO ((tree));
static tree string_constant_concatenation PROTO ((tree, tree)); static tree string_constant_concatenation PROTO ((tree, tree));
static tree build_string_concatenation PROTO ((tree, tree)); static tree build_string_concatenation PROTO ((tree, tree));
...@@ -210,7 +209,7 @@ static void check_thrown_exceptions PROTO ((int, tree)); ...@@ -210,7 +209,7 @@ static void check_thrown_exceptions PROTO ((int, tree));
static int check_thrown_exceptions_do PROTO ((tree)); static int check_thrown_exceptions_do PROTO ((tree));
static void purge_unchecked_exceptions PROTO ((tree)); static void purge_unchecked_exceptions PROTO ((tree));
static void check_throws_clauses PROTO ((tree, tree, tree)); static void check_throws_clauses PROTO ((tree, tree, tree));
static void complete_method_declaration PROTO ((tree)); static void finish_method_declaration PROTO ((tree));
static tree build_super_invocation PROTO (()); static tree build_super_invocation PROTO (());
static int verify_constructor_circularity PROTO ((tree, tree)); static int verify_constructor_circularity PROTO ((tree, tree));
static char *constructor_circularity_msg PROTO ((tree, tree)); static char *constructor_circularity_msg PROTO ((tree, tree));
...@@ -825,7 +824,7 @@ method_declaration: ...@@ -825,7 +824,7 @@ method_declaration:
source_start_java_method (current_function_decl); source_start_java_method (current_function_decl);
} }
method_body method_body
{ complete_method_declaration ($3); } { finish_method_declaration ($3); }
| method_header error | method_header error
{YYNOT_TWICE yyerror ("'{' expected"); RECOVER;} {YYNOT_TWICE yyerror ("'{' expected"); RECOVER;}
; ;
...@@ -955,7 +954,7 @@ constructor_declaration: ...@@ -955,7 +954,7 @@ constructor_declaration:
source_start_java_method (current_function_decl); source_start_java_method (current_function_decl);
} }
constructor_body constructor_body
{ complete_method_declaration ($3); } { finish_method_declaration ($3); }
; ;
constructor_header: constructor_header:
...@@ -1236,22 +1235,14 @@ label_decl: ...@@ -1236,22 +1235,14 @@ label_decl:
labeled_statement: labeled_statement:
label_decl statement label_decl statement
{ { $$ = finish_labeled_statement ($1, $2); }
$$ = complete_labeled_statement ($1, $2);
pop_labeled_block ();
POP_LABELED_BLOCK ();
}
| identifier error | identifier error
{yyerror ("':' expected"); RECOVER;} {yyerror ("':' expected"); RECOVER;}
; ;
labeled_statement_nsi: labeled_statement_nsi:
label_decl statement_nsi label_decl statement_nsi
{ { $$ = finish_labeled_statement ($1, $2); }
$$ = complete_labeled_statement ($1, $2);
pop_labeled_block ();
POP_LABELED_BLOCK ();
}
; ;
/* We concentrate here a bunch of error handling rules that we couldn't write /* We concentrate here a bunch of error handling rules that we couldn't write
...@@ -1435,7 +1426,7 @@ while_expression: ...@@ -1435,7 +1426,7 @@ while_expression:
while_statement: while_statement:
while_expression statement while_expression statement
{ $$ = complete_loop_body (0, NULL_TREE, $2, 0); } { $$ = finish_loop_body (0, NULL_TREE, $2, 0); }
| WHILE_TK error | WHILE_TK error
{YYERROR_NOW; yyerror ("'(' expected"); RECOVER;} {YYERROR_NOW; yyerror ("'(' expected"); RECOVER;}
| WHILE_TK OP_TK error | WHILE_TK OP_TK error
...@@ -1446,7 +1437,7 @@ while_statement: ...@@ -1446,7 +1437,7 @@ while_statement:
while_statement_nsi: while_statement_nsi:
while_expression statement_nsi while_expression statement_nsi
{ $$ = complete_loop_body (0, NULL_TREE, $2, 0); } { $$ = finish_loop_body (0, NULL_TREE, $2, 0); }
; ;
do_statement_begin: do_statement_begin:
...@@ -1460,15 +1451,15 @@ do_statement_begin: ...@@ -1460,15 +1451,15 @@ do_statement_begin:
do_statement: do_statement:
do_statement_begin statement WHILE_TK OP_TK expression CP_TK SC_TK do_statement_begin statement WHILE_TK OP_TK expression CP_TK SC_TK
{ $$ = complete_loop_body ($4.location, $5, $2, 1); } { $$ = finish_loop_body ($4.location, $5, $2, 1); }
; ;
for_statement: for_statement:
for_begin SC_TK expression SC_TK for_update CP_TK statement for_begin SC_TK expression SC_TK for_update CP_TK statement
{ $$ = complete_for_loop (EXPR_WFL_LINECOL ($3), $3, $5, $7); } { $$ = finish_for_loop (EXPR_WFL_LINECOL ($3), $3, $5, $7); }
| for_begin SC_TK SC_TK for_update CP_TK statement | for_begin SC_TK SC_TK for_update CP_TK statement
{ {
$$ = complete_for_loop (0, NULL_TREE, $4, $6); $$ = finish_for_loop (0, NULL_TREE, $4, $6);
/* We have not condition, so we get rid of the EXIT_EXPR */ /* We have not condition, so we get rid of the EXIT_EXPR */
LOOP_EXPR_BODY_CONDITION_EXPR (LOOP_EXPR_BODY ($$), 0) = LOOP_EXPR_BODY_CONDITION_EXPR (LOOP_EXPR_BODY ($$), 0) =
empty_stmt_node; empty_stmt_node;
...@@ -1483,10 +1474,10 @@ for_statement: ...@@ -1483,10 +1474,10 @@ for_statement:
for_statement_nsi: for_statement_nsi:
for_begin SC_TK expression SC_TK for_update CP_TK statement_nsi for_begin SC_TK expression SC_TK for_update CP_TK statement_nsi
{ $$ = complete_for_loop (EXPR_WFL_LINECOL ($3), $3, $5, $7);} { $$ = finish_for_loop (EXPR_WFL_LINECOL ($3), $3, $5, $7);}
| for_begin SC_TK SC_TK for_update CP_TK statement_nsi | for_begin SC_TK SC_TK for_update CP_TK statement_nsi
{ {
$$ = complete_for_loop (0, NULL_TREE, $4, $6); $$ = finish_for_loop (0, NULL_TREE, $4, $6);
/* We have not condition, so we get rid of the EXIT_EXPR */ /* We have not condition, so we get rid of the EXIT_EXPR */
LOOP_EXPR_BODY_CONDITION_EXPR (LOOP_EXPR_BODY ($$), 0) = LOOP_EXPR_BODY_CONDITION_EXPR (LOOP_EXPR_BODY ($$), 0) =
empty_stmt_node; empty_stmt_node;
...@@ -3469,7 +3460,7 @@ fix_method_argument_names (orig_arg, meth) ...@@ -3469,7 +3460,7 @@ fix_method_argument_names (orig_arg, meth)
/* Complete the method declaration with METHOD_BODY. */ /* Complete the method declaration with METHOD_BODY. */
static void static void
complete_method_declaration (method_body) finish_method_declaration (method_body)
tree method_body; tree method_body;
{ {
BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (current_function_decl)) = method_body; BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (current_function_decl)) = method_body;
...@@ -7817,15 +7808,18 @@ java_complete_lhs (node) ...@@ -7817,15 +7808,18 @@ java_complete_lhs (node)
node = patch_switch_statement (node); node = patch_switch_statement (node);
if (TREE_OPERAND (node, 0) == error_mark_node) if (TREE_OPERAND (node, 0) == error_mark_node)
return error_mark_node; nn = error_mark_node;
TREE_TYPE (nn) = TREE_TYPE (node) = void_type_node; else
/* If we returned something different, that's because we
inserted a label. Pop the label too. */
if (nn != node)
{ {
if (CAN_COMPLETE_NORMALLY (node)) TREE_TYPE (nn) = TREE_TYPE (node) = void_type_node;
CAN_COMPLETE_NORMALLY (nn) = 1; /* If we returned something different, that's because we
POP_LABELED_BLOCK (); inserted a label. Pop the label too. */
if (nn != node)
{
if (CAN_COMPLETE_NORMALLY (node))
CAN_COMPLETE_NORMALLY (nn) = 1;
POP_LABELED_BLOCK ();
}
} }
POP_LOOP (); POP_LOOP ();
return nn; return nn;
...@@ -10390,30 +10384,35 @@ patch_if_else_statement (node) ...@@ -10390,30 +10384,35 @@ patch_if_else_statement (node)
/* Action taken when a lableled statement is parsed. a new /* Action taken when a lableled statement is parsed. a new
LABELED_BLOCK_EXPR is created. No statement is attached to the LABELED_BLOCK_EXPR is created. No statement is attached to the
label, yet. */ label, yet. LABEL can be NULL_TREE for artificially-generated blocks. */
static tree static tree
build_labeled_block (location, label) build_labeled_block (location, label)
int location; int location;
tree label; tree label;
{ {
tree label_name = merge_qualified_name (label_id, label); tree label_name ;
tree label_decl, node; tree label_decl, node;
if (label == NULL_TREE || label == continue_identifier_node)
/* Issue an error if we try to reuse a label that was previously label_name = label;
declared */ else
if (IDENTIFIER_LOCAL_VALUE (label_name))
{ {
EXPR_WFL_LINECOL (wfl_operator) = location; label_name = merge_qualified_name (label_id, label);
parse_error_context (wfl_operator, "Declaration of `%s' shadows " /* Issue an error if we try to reuse a label that was previously
"a previous label declaration", declared */
IDENTIFIER_POINTER (label)); if (IDENTIFIER_LOCAL_VALUE (label_name))
EXPR_WFL_LINECOL (wfl_operator) = {
EXPR_WFL_LINECOL (IDENTIFIER_LOCAL_VALUE (label_name)); EXPR_WFL_LINECOL (wfl_operator) = location;
parse_error_context (wfl_operator, "This is the location of the " parse_error_context (wfl_operator, "Declaration of `%s' shadows "
"previous declaration of label `%s'", "a previous label declaration",
IDENTIFIER_POINTER (label)); IDENTIFIER_POINTER (label));
java_error_count--; EXPR_WFL_LINECOL (wfl_operator) =
EXPR_WFL_LINECOL (IDENTIFIER_LOCAL_VALUE (label_name));
parse_error_context (wfl_operator, "This is the location of the "
"previous declaration of label `%s'",
IDENTIFIER_POINTER (label));
java_error_count--;
}
} }
label_decl = create_label_decl (label_name); label_decl = create_label_decl (label_name);
...@@ -10423,20 +10422,10 @@ build_labeled_block (location, label) ...@@ -10423,20 +10422,10 @@ build_labeled_block (location, label)
return node; return node;
} }
/* Generate a label crafting a unique name for it. This is used to
implicitely label loops that aren't the body part of labeled
statement. */
static tree
generate_labeled_block ()
{
return build_labeled_block (0, generate_name ());
}
/* A labeled statement LBE is attached a statement. */ /* A labeled statement LBE is attached a statement. */
static tree static tree
complete_labeled_statement (lbe, statement) finish_labeled_statement (lbe, statement)
tree lbe; /* Labeled block expr */ tree lbe; /* Labeled block expr */
tree statement; tree statement;
{ {
...@@ -10449,9 +10438,10 @@ complete_labeled_statement (lbe, statement) ...@@ -10449,9 +10438,10 @@ complete_labeled_statement (lbe, statement)
if (TREE_CODE (statement) == LOOP_EXPR && IS_FOR_LOOP_P (statement)) if (TREE_CODE (statement) == LOOP_EXPR && IS_FOR_LOOP_P (statement))
{ {
java_method_add_stmt (current_function_decl, lbe); java_method_add_stmt (current_function_decl, lbe);
return exit_block (); lbe = exit_block ();
} }
pop_labeled_block ();
POP_LABELED_BLOCK ();
return lbe; return lbe;
} }
...@@ -10503,7 +10493,7 @@ build_loop_body (location, condition, reversed) ...@@ -10503,7 +10493,7 @@ build_loop_body (location, condition, reversed)
condition = build_debugable_stmt (location, condition); condition = build_debugable_stmt (location, condition);
TREE_SIDE_EFFECTS (condition) = 1; TREE_SIDE_EFFECTS (condition) = 1;
body = generate_labeled_block (); body = build_labeled_block (0, continue_identifier_node);
first = (reversed ? body : condition); first = (reversed ? body : condition);
second = (reversed ? condition : body); second = (reversed ? condition : body);
return return
...@@ -10516,7 +10506,7 @@ build_loop_body (location, condition, reversed) ...@@ -10516,7 +10506,7 @@ build_loop_body (location, condition, reversed)
loop list. */ loop list. */
static tree static tree
complete_loop_body (location, condition, body, reversed) finish_loop_body (location, condition, body, reversed)
int location; int location;
tree condition, body; tree condition, body;
int reversed; int reversed;
...@@ -10538,16 +10528,16 @@ complete_loop_body (location, condition, body, reversed) ...@@ -10538,16 +10528,16 @@ complete_loop_body (location, condition, body, reversed)
return to_return; return to_return;
} }
/* Tailored version of complete_loop_body for FOR loops, when FOR /* Tailored version of finish_loop_body for FOR loops, when FOR
loops feature the condition part */ loops feature the condition part */
static tree static tree
complete_for_loop (location, condition, update, body) finish_for_loop (location, condition, update, body)
int location; int location;
tree condition, update, body; tree condition, update, body;
{ {
/* Put the condition and the loop body in place */ /* Put the condition and the loop body in place */
tree loop = complete_loop_body (location, condition, body, 0); tree loop = finish_loop_body (location, condition, body, 0);
/* LOOP is the current loop which has been now popped of the loop /* LOOP is the current loop which has been now popped of the loop
stack. Install the update block */ stack. Install the update block */
LOOP_EXPR_BODY_UPDATE_BLOCK (LOOP_EXPR_BODY (loop)) = update; LOOP_EXPR_BODY_UPDATE_BLOCK (LOOP_EXPR_BODY (loop)) = update;
...@@ -10555,28 +10545,21 @@ complete_for_loop (location, condition, update, body) ...@@ -10555,28 +10545,21 @@ complete_for_loop (location, condition, update, body)
} }
/* If the loop isn't surrounded by a labeled statement, create one and /* If the loop isn't surrounded by a labeled statement, create one and
insert LOOP as it's body. */ insert LOOP as its body. */
static tree static tree
patch_loop_statement (loop) patch_loop_statement (loop)
tree loop; tree loop;
{ {
tree loop_label, to_return_as_loop; if (! LOOP_HAS_LABEL_P (loop))
if (LOOP_HAS_LABEL_P (loop))
{
loop_label = ctxp->current_labeled_block;
to_return_as_loop = loop;
}
else
{ {
loop_label = generate_labeled_block (); tree loop_label = build_labeled_block (0, NULL_TREE);
LABELED_BLOCK_BODY (loop_label) = loop; LABELED_BLOCK_BODY (loop_label) = loop;
PUSH_LABELED_BLOCK (loop_label); PUSH_LABELED_BLOCK (loop_label);
to_return_as_loop = loop_label; loop = loop_label;
} }
TREE_TYPE (to_return_as_loop) = void_type_node; TREE_TYPE (loop) = void_type_node;
return to_return_as_loop; return loop;
} }
/* 14.13, 14.14: break and continue Statements */ /* 14.13, 14.14: break and continue Statements */
...@@ -10620,98 +10603,63 @@ patch_bc_statement (node) ...@@ -10620,98 +10603,63 @@ patch_bc_statement (node)
tree node; tree node;
{ {
tree bc_label = EXIT_BLOCK_LABELED_BLOCK (node), target_stmt; tree bc_label = EXIT_BLOCK_LABELED_BLOCK (node), target_stmt;
int is_unlabeled = 0; tree labeled_block = ctxp->current_labeled_block;
EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node); EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node);
/* Not having a target means that the break/continue statement is
unlabeled. We try to find a decent label for it */
if (!bc_label)
{
is_unlabeled = 1;
/* There should be a loop/switch to branch to */
if (ctxp->current_loop)
{
if (TREE_CODE (ctxp->current_loop) == LOOP_EXPR)
{
/* At that stage, we're in the loop body, which is
encapsulated around a LABELED_BLOCK_EXPR. So searching
the current loop label requires us to consider the
labeled block before the current one. */
if (!LOOP_HAS_LABEL_SKIP_P (ctxp->current_loop))
fatal ("unlabeled loop has no installed label -- "
"patch_bc_statement");
bc_label = TREE_CHAIN (ctxp->current_labeled_block);
}
/* For a SWITCH statement, this is the current one */
else
bc_label = ctxp->current_labeled_block;
}
/* Not having a loop to break/continue to is an error */
else
{
parse_error_context (wfl_operator, "`%s' must be in loop%s",
(IS_BREAK_STMT_P (node) ? "break" : "continue"),
(IS_BREAK_STMT_P (node) ? " or switch" : ""));
return error_mark_node;
}
}
/* Having an identifier here means that the target is unknown. */ /* Having an identifier here means that the target is unknown. */
else if (TREE_CODE (bc_label) == IDENTIFIER_NODE) if (bc_label != NULL_TREE && TREE_CODE (bc_label) == IDENTIFIER_NODE)
{ {
parse_error_context (wfl_operator, "No label definition found for `%s'", parse_error_context (wfl_operator, "No label definition found for `%s'",
IDENTIFIER_POINTER (bc_label)); IDENTIFIER_POINTER (bc_label));
return error_mark_node; return error_mark_node;
} }
if (! IS_BREAK_STMT_P (node))
/* Find the statement we're targeting. */
target_stmt = LABELED_BLOCK_BODY (bc_label);
/* Target loop is slightly burrowed in the case of a for loop, it
appears at the first sight to be a block. */
if (TREE_CODE (target_stmt) == BLOCK)
{
tree sub = BLOCK_SUBBLOCKS (target_stmt);
if (sub && TREE_CODE (sub) == COMPOUND_EXPR && TREE_OPERAND (sub, 1)
&& TREE_CODE (TREE_OPERAND (sub, 1)) == LOOP_EXPR)
target_stmt = TREE_OPERAND (sub, 1);
}
/* 14.13 The break Statement */
if (IS_BREAK_STMT_P (node))
{ {
/* Named break are always fine, as far as they have a target /* It's a continue statement. */
(already verified). Anonymous break need to target for (;; labeled_block = TREE_CHAIN (labeled_block))
while/do/for/switch */
if (is_unlabeled &&
!(TREE_CODE (target_stmt) == LOOP_EXPR /* do/while/for */
|| TREE_CODE (target_stmt) == SWITCH_EXPR)) /* switch */
{ {
parse_error_context (wfl_operator, if (labeled_block == NULL_TREE)
"`break' must be in loop or switch"); {
return error_mark_node; if (bc_label == NULL_TREE)
parse_error_context (wfl_operator,
"`continue' must be in loop");
else
parse_error_context (wfl_operator,
"continue label `%d' does not name a loop",
IDENTIFIER_POINTER (bc_label));
return error_mark_node;
}
if ((DECL_NAME (LABELED_BLOCK_LABEL (labeled_block))
== continue_identifier_node)
&& (bc_label == NULL_TREE
|| TREE_CHAIN (labeled_block) == bc_label))
{
bc_label = labeled_block;
break;
}
} }
/* If previously unlabeled, install the new found label */
if (is_unlabeled)
EXIT_BLOCK_LABELED_BLOCK (node) = bc_label;
} }
/* 14.14 The continue Statement */ else if (!bc_label)
/* The continue statement must always target a loop, unnamed or not. */
else
{ {
if (TREE_CODE (target_stmt) != LOOP_EXPR) /* do/while/for */ for (;; labeled_block = TREE_CHAIN (labeled_block))
{ {
parse_error_context (wfl_operator, "`continue' must be in loop"); if (labeled_block == NULL_TREE)
return error_mark_node; {
parse_error_context (wfl_operator,
"`break' must be in loop or switch");
return error_mark_node;
}
target_stmt = LABELED_BLOCK_BODY (labeled_block);
if (TREE_CODE (target_stmt) == SWITCH_EXPR
|| TREE_CODE (target_stmt) == LOOP_EXPR)
{
bc_label = labeled_block;
break;
}
} }
/* Everything looks good. We can fix the `continue' jump to go
at the place in the loop were the continue is. For unlabeled
continue, the continuation point is the current labeled
block, by construction. */
if (is_unlabeled)
EXIT_BLOCK_LABELED_BLOCK (node) =
bc_label = ctxp->current_labeled_block;
} }
EXIT_BLOCK_LABELED_BLOCK (node) = bc_label;
CAN_COMPLETE_NORMALLY (bc_label) = 1; CAN_COMPLETE_NORMALLY (bc_label) = 1;
/* Our break/continue don't return values. */ /* Our break/continue don't return values. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment