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,7 +7808,9 @@ java_complete_lhs (node) ...@@ -7817,7 +7808,9 @@ 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;
else
{
TREE_TYPE (nn) = TREE_TYPE (node) = void_type_node; TREE_TYPE (nn) = TREE_TYPE (node) = void_type_node;
/* If we returned something different, that's because we /* If we returned something different, that's because we
inserted a label. Pop the label too. */ inserted a label. Pop the label too. */
...@@ -7827,6 +7820,7 @@ java_complete_lhs (node) ...@@ -7827,6 +7820,7 @@ java_complete_lhs (node)
CAN_COMPLETE_NORMALLY (nn) = 1; CAN_COMPLETE_NORMALLY (nn) = 1;
POP_LABELED_BLOCK (); POP_LABELED_BLOCK ();
} }
}
POP_LOOP (); POP_LOOP ();
return nn; return nn;
...@@ -10390,16 +10384,20 @@ patch_if_else_statement (node) ...@@ -10390,16 +10384,20 @@ 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)
label_name = label;
else
{
label_name = merge_qualified_name (label_id, label);
/* Issue an error if we try to reuse a label that was previously /* Issue an error if we try to reuse a label that was previously
declared */ declared */
if (IDENTIFIER_LOCAL_VALUE (label_name)) if (IDENTIFIER_LOCAL_VALUE (label_name))
...@@ -10415,6 +10413,7 @@ build_labeled_block (location, label) ...@@ -10415,6 +10413,7 @@ build_labeled_block (location, label)
IDENTIFIER_POINTER (label)); IDENTIFIER_POINTER (label));
java_error_count--; java_error_count--;
} }
}
label_decl = create_label_decl (label_name); label_decl = create_label_decl (label_name);
node = build (LABELED_BLOCK_EXPR, NULL_TREE, label_decl, NULL_TREE); node = build (LABELED_BLOCK_EXPR, NULL_TREE, label_decl, NULL_TREE);
...@@ -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; tree loop_label = build_labeled_block (0, NULL_TREE);
to_return_as_loop = loop;
}
else
{
loop_label = generate_labeled_block ();
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 /* Having an identifier here means that the target is unknown. */
unlabeled. We try to find a decent label for it */ if (bc_label != NULL_TREE && TREE_CODE (bc_label) == IDENTIFIER_NODE)
if (!bc_label)
{ {
is_unlabeled = 1; parse_error_context (wfl_operator, "No label definition found for `%s'",
/* There should be a loop/switch to branch to */ IDENTIFIER_POINTER (bc_label));
if (ctxp->current_loop) return error_mark_node;
}
if (! IS_BREAK_STMT_P (node))
{ {
if (TREE_CODE (ctxp->current_loop) == LOOP_EXPR) /* It's a continue statement. */
for (;; labeled_block = TREE_CHAIN (labeled_block))
{ {
/* At that stage, we're in the loop body, which is if (labeled_block == NULL_TREE)
encapsulated around a LABELED_BLOCK_EXPR. So searching {
the current loop label requires us to consider the if (bc_label == NULL_TREE)
labeled block before the current one. */ parse_error_context (wfl_operator,
if (!LOOP_HAS_LABEL_SKIP_P (ctxp->current_loop)) "`continue' must be in 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 else
bc_label = ctxp->current_labeled_block; parse_error_context (wfl_operator,
"continue label `%d' does not name a loop",
IDENTIFIER_POINTER (bc_label));
return error_mark_node;
} }
/* Not having a loop to break/continue to is an error */ if ((DECL_NAME (LABELED_BLOCK_LABEL (labeled_block))
else == continue_identifier_node)
&& (bc_label == NULL_TREE
|| TREE_CHAIN (labeled_block) == bc_label))
{ {
parse_error_context (wfl_operator, "`%s' must be in loop%s", bc_label = labeled_block;
(IS_BREAK_STMT_P (node) ? "break" : "continue"), break;
(IS_BREAK_STMT_P (node) ? " or switch" : ""));
return error_mark_node;
} }
} }
/* Having an identifier here means that the target is unknown. */
else if (TREE_CODE (bc_label) == IDENTIFIER_NODE)
{
parse_error_context (wfl_operator, "No label definition found for `%s'",
IDENTIFIER_POINTER (bc_label));
return error_mark_node;
} }
else if (!bc_label)
/* 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); for (;; labeled_block = TREE_CHAIN (labeled_block))
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 if (labeled_block == NULL_TREE)
(already verified). Anonymous break need to target
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, parse_error_context (wfl_operator,
"`break' must be in loop or switch"); "`break' must be in loop or switch");
return error_mark_node; return error_mark_node;
} }
/* If previously unlabeled, install the new found label */ target_stmt = LABELED_BLOCK_BODY (labeled_block);
if (is_unlabeled) if (TREE_CODE (target_stmt) == SWITCH_EXPR
EXIT_BLOCK_LABELED_BLOCK (node) = bc_label; || TREE_CODE (target_stmt) == LOOP_EXPR)
}
/* 14.14 The continue Statement */
/* The continue statement must always target a loop, unnamed or not. */
else
{ {
if (TREE_CODE (target_stmt) != LOOP_EXPR) /* do/while/for */ bc_label = labeled_block;
{ break;
parse_error_context (wfl_operator, "`continue' must be in loop"); }
return error_mark_node;
} }
/* 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