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>
* decl.c (lookup_label): Build labels on the permanent obstack
......
......@@ -228,6 +228,7 @@ DEFTREECODE (BREAK_STMT, "break_stmt", 'e', 0)
DEFTREECODE (CONTINUE_STMT, "continue_stmt", 'e', 0)
DEFTREECODE (SWITCH_STMT, "switch_stmt", 'e', 2)
DEFTREECODE (GOTO_STMT, "goto_stmt", 'e', 1)
DEFTREECODE (LABEL_STMT, "label_stmt", 'e', 1)
DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 5)
/* A SUBOBJECT statement marks the point at which a sub-object is
fully constructed. After this point, the SUBOBJECT_CLEANUP must be
......
......@@ -731,6 +731,13 @@ dequeue_and_dump (di)
dump_next_stmt (di, t);
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:
dump_stmt (di, t);
if (dump_children_p)
......
......@@ -3168,12 +3168,11 @@ label_decls:
label_decl:
LABEL identifiers_or_typenames ';'
{ tree link;
for (link = $2; link; link = TREE_CHAIN (link))
{
while ($2)
{
tree label = shadow_label (TREE_VALUE (link));
C_DECLARED_LABEL_FLAG (label) = 1;
declare_nonlocal_label (label);
finish_label_decl (TREE_VALUE ($2));
$2 = TREE_CHAIN ($2);
}
}
;
......
......@@ -7264,18 +7264,23 @@ tsubst_expr (t, args, complain, in_decl)
lineno = STMT_LINENO (t);
decl = DECL_STMT_DECL (t);
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
if (TREE_CODE (decl) == LABEL_DECL)
finish_label_decl (DECL_NAME (decl));
else
{
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
local variables, and since we've already done all that
needs to be done, that's the right thing to do. */
if (TREE_CODE (decl) == VAR_DECL)
DECL_TEMPLATE_INSTANTIATED (decl) = 1;
maybe_push_decl (decl);
add_decl_stmt (decl);
if (TREE_CODE (decl) == VAR_DECL)
DECL_TEMPLATE_INSTANTIATED (decl) = 1;
maybe_push_decl (decl);
add_decl_stmt (decl);
}
resume_momentary (i);
return decl;
}
......@@ -7392,10 +7397,9 @@ tsubst_expr (t, args, complain, in_decl)
tsubst_expr (CASE_HIGH (t), args, complain, in_decl));
break;
case LABEL_DECL:
lineno = DECL_SOURCE_LINE (t);
input_filename = DECL_SOURCE_FILE (t);
finish_label_stmt (DECL_NAME (t));
case LABEL_STMT:
lineno = STMT_LINENO (t);
finish_label_stmt (DECL_NAME (LABEL_STMT_LABEL (t)));
break;
case GOTO_STMT:
......
......@@ -919,11 +919,24 @@ finish_label_stmt (name)
tree decl = define_label (input_filename, lineno, name);
if (building_stmt_tree ())
add_tree (decl);
add_tree (build_min_nt (LABEL_STMT, decl));
else if (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
DECL. */
......@@ -2019,17 +2032,22 @@ expand_stmt (t)
lineno = STMT_LINENO (t);
emit_line_note (input_filename, lineno);
decl = DECL_STMT_DECL (t);
/* We need to clear DECL_CONTEXT so that maybe_push_decl
will push it into the current scope. */
if (DECL_CONTEXT (decl) == current_function_decl)
DECL_CONTEXT (decl) = NULL_TREE;
/* If we marked this variable as dead when we processed it
before, we must undo that now. The variable has been
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);
if (TREE_CODE (decl) == LABEL_DECL)
finish_label_decl (DECL_NAME (decl));
else
{
/* We need to clear DECL_CONTEXT so that maybe_push_decl
will push it into the current scope. */
if (DECL_CONTEXT (decl) == current_function_decl)
DECL_CONTEXT (decl) = NULL_TREE;
/* If we marked this variable as dead when we processed it
before, we must undo that now. The variable has been
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);
}
break;
......@@ -2119,15 +2137,17 @@ expand_stmt (t)
finish_case_label (CASE_LOW (t), CASE_HIGH (t));
break;
case LABEL_DECL:
input_filename = DECL_SOURCE_FILE (t);
lineno = DECL_SOURCE_LINE (t);
finish_label_stmt (DECL_NAME (t));
case LABEL_STMT:
lineno = STMT_LINENO (t);
finish_label_stmt (DECL_NAME (LABEL_STMT_LABEL (t)));
break;
case GOTO_STMT:
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;
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