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))
{ {
tree label = shadow_label (TREE_VALUE (link)); while ($2)
C_DECLARED_LABEL_FLAG (label) = 1; {
declare_nonlocal_label (label); finish_label_decl (TREE_VALUE ($2));
$2 = TREE_CHAIN ($2);
} }
} }
; ;
......
...@@ -7264,6 +7264,10 @@ tsubst_expr (t, args, complain, in_decl) ...@@ -7264,6 +7264,10 @@ 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);
if (TREE_CODE (decl) == LABEL_DECL)
finish_label_decl (DECL_NAME (decl));
else
{
init = DECL_INITIAL (decl); init = DECL_INITIAL (decl);
decl = tsubst (decl, args, complain, in_decl); decl = tsubst (decl, args, complain, in_decl);
init = tsubst_expr (init, args, complain, in_decl); init = tsubst_expr (init, args, complain, in_decl);
...@@ -7276,6 +7280,7 @@ tsubst_expr (t, args, complain, in_decl) ...@@ -7276,6 +7280,7 @@ tsubst_expr (t, args, complain, in_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,6 +2032,10 @@ expand_stmt (t) ...@@ -2019,6 +2032,10 @@ 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);
if (TREE_CODE (decl) == LABEL_DECL)
finish_label_decl (DECL_NAME (decl));
else
{
/* We need to clear DECL_CONTEXT so that maybe_push_decl /* We need to clear DECL_CONTEXT so that maybe_push_decl
will push it into the current scope. */ will push it into the current scope. */
if (DECL_CONTEXT (decl) == current_function_decl) if (DECL_CONTEXT (decl) == current_function_decl)
...@@ -2030,6 +2047,7 @@ expand_stmt (t) ...@@ -2030,6 +2047,7 @@ expand_stmt (t)
DECL_DEAD_FOR_LOCAL (decl) = 0; DECL_DEAD_FOR_LOCAL (decl) = 0;
maybe_push_decl (decl); maybe_push_decl (decl);
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0); cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
}
resume_momentary (i); resume_momentary (i);
} }
break; break;
...@@ -2119,14 +2137,16 @@ expand_stmt (t) ...@@ -2119,14 +2137,16 @@ 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);
if (TREE_CODE (GOTO_DESTINATION (t)) == LABEL_DECL)
finish_goto_stmt (DECL_NAME (GOTO_DESTINATION (t)));
else
finish_goto_stmt (GOTO_DESTINATION (t)); finish_goto_stmt (GOTO_DESTINATION (t));
break; break;
......
// 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