Commit acef433b by Mark Mitchell Committed by Mark Mitchell

cp-tree.def (LABEL_STMT): New tree node.

	* cp-tree.def (LABEL_STMT): New tree node.
	(LABEL_STMT_LABEL): New macro.
	(shadow_label): Remove.
	(declare_local_label): New function.
	(finish_label_decl): Likewise.
	* decl.c (make_label_decl): New function, split out from
	lookup_label.
	(shadowed_labels): Remove.
	(binding_level): Add shadowed_labels.
	(clear_binding_level): Remove.
	(push_binding_level): Just bzero the new binding level.
	(pushlevel): Fix indentation.
	(pop_label): New function.
	(pop_labels): Likewise, split out from poplevel.
	(poplevel): Pop local labels.  Use pop_labels.
	(maybe_push_to_top_level): Don't clear shadowed_labels.
	(lookup_label): Use make_label_decl.
	(shadow_label): Remove.
	(declare_local_label): New function.
	(define_label): Simplify.
	(start_function): Don't clear shadowed_labels.
	(cp_function): Remove shadowed_labels.
	(push_cp_function_context): Don't save shadowed_labels.
	(pop_cp_function_context): Don't restore it.
	* dump.c (dequeue_and_dump): Handle LABEL_STMT.
	* parse.y (label_decl): Use finish_label_decl.
	* pt.c (tsubst_expr): Handle LABEL_STMTs, and local label
	declarations.
	* semantics.c (finish_label_stmt): Add a LABEL_STMT when
	building_stmt_tree.
	(finish_label_decl): New function.
	(expand_stmt): Handle LABEL_STMTs and local label declarations.

From-SVN: r28943
parent 79101920
1999-08-28 Mark Mitchell <mark@codesourcery.com>
* cp-tree.def (LABEL_STMT): New tree node.
(LABEL_STMT_LABEL): New macro.
(shadow_label): Remove.
(declare_local_label): New function.
(finish_label_decl): Likewise.
* decl.c (make_label_decl): New function, split out from
lookup_label.
(shadowed_labels): Remove.
(binding_level): Add shadowed_labels.
(clear_binding_level): Remove.
(push_binding_level): Just bzero the new binding level.
(pushlevel): Fix indentation.
(pop_label): New function.
(pop_labels): Likewise, split out from poplevel.
(poplevel): Pop local labels. Use pop_labels.
(maybe_push_to_top_level): Don't clear shadowed_labels.
(lookup_label): Use make_label_decl.
(shadow_label): Remove.
(declare_local_label): New function.
(define_label): Simplify.
(start_function): Don't clear shadowed_labels.
(cp_function): Remove shadowed_labels.
(push_cp_function_context): Don't save shadowed_labels.
(pop_cp_function_context): Don't restore it.
* dump.c (dequeue_and_dump): Handle LABEL_STMT.
* parse.y (label_decl): Use finish_label_decl.
* pt.c (tsubst_expr): Handle LABEL_STMTs, and local label
declarations.
* semantics.c (finish_label_stmt): Add a LABEL_STMT when
building_stmt_tree.
(finish_label_decl): New function.
(expand_stmt): Handle LABEL_STMTs and local label declarations.
1999-08-26 Mark Mitchell <mark@codesourcery.com> 1999-08-26 Mark Mitchell <mark@codesourcery.com>
* decl.c (lookup_label): Build labels on the permanent obstack * decl.c (lookup_label): Build labels on the permanent obstack
......
...@@ -228,6 +228,7 @@ DEFTREECODE (BREAK_STMT, "break_stmt", 'e', 0) ...@@ -228,6 +228,7 @@ DEFTREECODE (BREAK_STMT, "break_stmt", 'e', 0)
DEFTREECODE (CONTINUE_STMT, "continue_stmt", 'e', 0) DEFTREECODE (CONTINUE_STMT, "continue_stmt", 'e', 0)
DEFTREECODE (SWITCH_STMT, "switch_stmt", 'e', 2) DEFTREECODE (SWITCH_STMT, "switch_stmt", 'e', 2)
DEFTREECODE (GOTO_STMT, "goto_stmt", 'e', 1) DEFTREECODE (GOTO_STMT, "goto_stmt", 'e', 1)
DEFTREECODE (LABEL_STMT, "label_stmt", 'e', 1)
DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 5) DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 5)
/* A SUBOBJECT statement marks the point at which a sub-object is /* A SUBOBJECT statement marks the point at which a sub-object is
fully constructed. After this point, the SUBOBJECT_CLEANUP must be fully constructed. After this point, the SUBOBJECT_CLEANUP must be
......
...@@ -731,6 +731,13 @@ dequeue_and_dump (di) ...@@ -731,6 +731,13 @@ dequeue_and_dump (di)
dump_next_stmt (di, t); dump_next_stmt (di, t);
break; break;
case LABEL_STMT:
dump_stmt (di, t);
if (dump_children_p)
dump_child ("labl", LABEL_STMT_LABEL (t));
dump_next_stmt (di, t);
break;
case RETURN_STMT: case RETURN_STMT:
dump_stmt (di, t); dump_stmt (di, t);
if (dump_children_p) if (dump_children_p)
......
...@@ -3168,12 +3168,11 @@ label_decls: ...@@ -3168,12 +3168,11 @@ label_decls:
label_decl: label_decl:
LABEL identifiers_or_typenames ';' LABEL identifiers_or_typenames ';'
{ tree link; {
for (link = $2; link; link = TREE_CHAIN (link)) while ($2)
{ {
tree label = shadow_label (TREE_VALUE (link)); finish_label_decl (TREE_VALUE ($2));
C_DECLARED_LABEL_FLAG (label) = 1; $2 = TREE_CHAIN ($2);
declare_nonlocal_label (label);
} }
} }
; ;
......
...@@ -7264,18 +7264,23 @@ tsubst_expr (t, args, complain, in_decl) ...@@ -7264,18 +7264,23 @@ tsubst_expr (t, args, complain, in_decl)
lineno = STMT_LINENO (t); lineno = STMT_LINENO (t);
decl = DECL_STMT_DECL (t); decl = DECL_STMT_DECL (t);
init = DECL_INITIAL (decl); if (TREE_CODE (decl) == LABEL_DECL)
decl = tsubst (decl, args, complain, in_decl); finish_label_decl (DECL_NAME (decl));
init = tsubst_expr (init, args, complain, in_decl); else
DECL_INITIAL (decl) = init; {
/* By marking the declaration as instantiated, we avoid trying init = DECL_INITIAL (decl);
decl = tsubst (decl, args, complain, in_decl);
init = tsubst_expr (init, args, complain, in_decl);
DECL_INITIAL (decl) = init;
/* By marking the declaration as instantiated, we avoid trying
to instantiate it. Since instantiate_decl can't handle to instantiate it. Since instantiate_decl can't handle
local variables, and since we've already done all that local variables, and since we've already done all that
needs to be done, that's the right thing to do. */ needs to be done, that's the right thing to do. */
if (TREE_CODE (decl) == VAR_DECL) if (TREE_CODE (decl) == VAR_DECL)
DECL_TEMPLATE_INSTANTIATED (decl) = 1; DECL_TEMPLATE_INSTANTIATED (decl) = 1;
maybe_push_decl (decl); maybe_push_decl (decl);
add_decl_stmt (decl); add_decl_stmt (decl);
}
resume_momentary (i); resume_momentary (i);
return decl; return decl;
} }
...@@ -7392,10 +7397,9 @@ tsubst_expr (t, args, complain, in_decl) ...@@ -7392,10 +7397,9 @@ tsubst_expr (t, args, complain, in_decl)
tsubst_expr (CASE_HIGH (t), args, complain, in_decl)); tsubst_expr (CASE_HIGH (t), args, complain, in_decl));
break; break;
case LABEL_DECL: case LABEL_STMT:
lineno = DECL_SOURCE_LINE (t); lineno = STMT_LINENO (t);
input_filename = DECL_SOURCE_FILE (t); finish_label_stmt (DECL_NAME (LABEL_STMT_LABEL (t)));
finish_label_stmt (DECL_NAME (t));
break; break;
case GOTO_STMT: case GOTO_STMT:
......
...@@ -919,11 +919,24 @@ finish_label_stmt (name) ...@@ -919,11 +919,24 @@ finish_label_stmt (name)
tree decl = define_label (input_filename, lineno, name); tree decl = define_label (input_filename, lineno, name);
if (building_stmt_tree ()) if (building_stmt_tree ())
add_tree (decl); add_tree (build_min_nt (LABEL_STMT, decl));
else if (decl) else if (decl)
expand_label (decl); expand_label (decl);
} }
/* Finish a series of declarations for local labels. G++ allows users
to declare "local" labels, i.e., labels with scope. This extension
is useful when writing code involving statement-expressions. */
void
finish_label_decl (name)
tree name;
{
tree decl = declare_local_label (name);
if (building_stmt_tree ())
add_decl_stmt (decl);
}
/* Create a declaration statement for the declaration given by the /* Create a declaration statement for the declaration given by the
DECL. */ DECL. */
...@@ -2019,17 +2032,22 @@ expand_stmt (t) ...@@ -2019,17 +2032,22 @@ expand_stmt (t)
lineno = STMT_LINENO (t); lineno = STMT_LINENO (t);
emit_line_note (input_filename, lineno); emit_line_note (input_filename, lineno);
decl = DECL_STMT_DECL (t); decl = DECL_STMT_DECL (t);
/* We need to clear DECL_CONTEXT so that maybe_push_decl if (TREE_CODE (decl) == LABEL_DECL)
will push it into the current scope. */ finish_label_decl (DECL_NAME (decl));
if (DECL_CONTEXT (decl) == current_function_decl) else
DECL_CONTEXT (decl) = NULL_TREE; {
/* If we marked this variable as dead when we processed it /* We need to clear DECL_CONTEXT so that maybe_push_decl
before, we must undo that now. The variable has been will push it into the current scope. */
resuscitated. */ if (DECL_CONTEXT (decl) == current_function_decl)
if (TREE_CODE (decl) == VAR_DECL) DECL_CONTEXT (decl) = NULL_TREE;
DECL_DEAD_FOR_LOCAL (decl) = 0; /* If we marked this variable as dead when we processed it
maybe_push_decl (decl); before, we must undo that now. The variable has been
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0); resuscitated. */
if (TREE_CODE (decl) == VAR_DECL)
DECL_DEAD_FOR_LOCAL (decl) = 0;
maybe_push_decl (decl);
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
}
resume_momentary (i); resume_momentary (i);
} }
break; break;
...@@ -2119,15 +2137,17 @@ expand_stmt (t) ...@@ -2119,15 +2137,17 @@ expand_stmt (t)
finish_case_label (CASE_LOW (t), CASE_HIGH (t)); finish_case_label (CASE_LOW (t), CASE_HIGH (t));
break; break;
case LABEL_DECL: case LABEL_STMT:
input_filename = DECL_SOURCE_FILE (t); lineno = STMT_LINENO (t);
lineno = DECL_SOURCE_LINE (t); finish_label_stmt (DECL_NAME (LABEL_STMT_LABEL (t)));
finish_label_stmt (DECL_NAME (t));
break; break;
case GOTO_STMT: case GOTO_STMT:
lineno = STMT_LINENO (t); lineno = STMT_LINENO (t);
finish_goto_stmt (GOTO_DESTINATION (t)); if (TREE_CODE (GOTO_DESTINATION (t)) == LABEL_DECL)
finish_goto_stmt (DECL_NAME (GOTO_DESTINATION (t)));
else
finish_goto_stmt (GOTO_DESTINATION (t));
break; break;
case ASM_STMT: case ASM_STMT:
......
// Origin: Mark Mitchell <mark@codesourcery.com>
// Special g++ Options:
int main ()
{
int i = 0;
int j = 0;
int k = 0;
l:
if (j)
return 0;
({
__label__ l;
k = 0;
l:
if (++k <= 2)
goto l;
++i;});
if (i > 1 || k != 3)
return 1;
else
{
j = 1;
goto l;
}
}
// Origin: Mark Mitchell <mark@codesourcery.com>
// Special g++ Options:
template <class T>
int f ()
{
int i = 0;
int j = 0;
int k = 0;
l:
if (j)
return 0;
({
__label__ l;
k = 0;
l:
if (++k <= 2)
goto l;
++i;});
if (i > 1 || k != 3)
return 1;
else
{
j = 1;
goto l;
}
}
int main ()
{
return f<double>();
}
// Build don't link:
// Origin: Mark Mitchell <mark@codesourcery.com>
int i = 1;
template <class T> void test()
{
goto lab;
lab:
--i;
}
int main ()
{
test<int>();
return i;
}
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