Commit 14e33ee8 by Zack Weinberg

* c-decl.c (named_labels, shadowed_labels, label_level_chain)

	(push_label_level, pop_label_level): Kill.
	(struct binding_level): Rename level_chain to outer.
	Add outer_function field.  Change parm_flag, function_body,
	keep, keep_if_subblocks to 1-bit bitfields of type bool.
	(current_function_level): New variable.
	(keep_next_level_flag, keep_next_if_subblocks): Change type to bool.
	(keep_next_level, declare_parm_level, warn_if_shadowing):
	Update to match.
	(struct language_function): Kill named_labels, shadowed_labels fields.
	(c_init_decl_processing, start_function, c_push__function_context)
	(c_pop_function_context): No need to muck with named_labels nor
	shadowed_labels.

	(make_binding_level): No need to clear the structure here.
	(pop_binding_level): Always operate on current_binding_level.
	Update current_function_level if necessary.
	(pushlevel): Don't clear named_labels.  Update current_function_level
	if necessary.  Use "true" and "false" where appropriate.
	(poplevel): Diagnose labels defined but not used, or vice
	versa, and clear out label-meanings leaving scope, while
	walking down the decls list, for all binding levels.
	Handle LABEL_DECLs appearing in the shadowed list.
	pop_binding_level takes no arguments.
	(pushdecl_function_level): Use current_function_level.

	(make_label, bind_label): New static functions.
	(declare_label): New exported function.
	(lookup_label, define_label): Rewritten for new data structure.
	(shadow_label): Kill.

	* c-tree.h: Prototype declare_label; don't prototype
	push_label_level, pop_label_level, nor shadow_label.
	* c-parse.in: Remove all calls to push_label_level and
	pop_label_level.  Use declare_label for __label__ decls.

	* doc/extend.texi: Clarify that __label__ can be used to
	declare labels with local scope in any nested block, not
	just statement expressions.  Cross-reference nested functions
	section from local labels section.

testsuite:
	* gcc.dg/noncompile/label-1.c: New comprehensive test case for
	diagnostics of ill-formed constructs involving labels.
	* gcc.dg/noncompile/label-lineno-1.c: Add error regexp for
	the new 'previously defined here' message.

From-SVN: r69597
parent 1b339d86
2003-07-19 Zack Weinberg <zack@codesourcery.com>
* c-decl.c (named_labels, shadowed_labels, label_level_chain)
(push_label_level, pop_label_level): Kill.
(struct binding_level): Rename level_chain to outer.
Add outer_function field. Change parm_flag, function_body,
keep, keep_if_subblocks to 1-bit bitfields of type bool.
(current_function_level): New variable.
(keep_next_level_flag, keep_next_if_subblocks): Change type to bool.
(keep_next_level, declare_parm_level, warn_if_shadowing):
Update to match.
(struct language_function): Kill named_labels, shadowed_labels fields.
(c_init_decl_processing, start_function, c_push__function_context)
(c_pop_function_context): No need to muck with named_labels nor
shadowed_labels.
(make_binding_level): No need to clear the structure here.
(pop_binding_level): Always operate on current_binding_level.
Update current_function_level if necessary.
(pushlevel): Don't clear named_labels. Update current_function_level
if necessary. Use "true" and "false" where appropriate.
(poplevel): Diagnose labels defined but not used, or vice
versa, and clear out label-meanings leaving scope, while
walking down the decls list, for all binding levels.
Handle LABEL_DECLs appearing in the shadowed list.
pop_binding_level takes no arguments.
(pushdecl_function_level): Use current_function_level.
(make_label, bind_label): New static functions.
(declare_label): New exported function.
(lookup_label, define_label): Rewritten for new data structure.
(shadow_label): Kill.
* c-tree.h: Prototype declare_label; don't prototype
push_label_level, pop_label_level, nor shadow_label.
* c-parse.in: Remove all calls to push_label_level and
pop_label_level. Use declare_label for __label__ decls.
* doc/extend.texi: Clarify that __label__ can be used to
declare labels with local scope in any nested block, not
just statement expressions. Cross-reference nested functions
section from local labels section.
2003-07-19 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz> 2003-07-19 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* sched-rgn.c (find_rgns): Initialize current_edge correctly. * sched-rgn.c (find_rgns): Initialize current_edge correctly.
...@@ -13,7 +56,7 @@ ...@@ -13,7 +56,7 @@
2003-07-19 Ulrich Weigand <uweigand@de.ibm.com> 2003-07-19 Ulrich Weigand <uweigand@de.ibm.com>
* config/s390/s390.c (legitimize_pic_address): Access local symbols * config/s390/s390.c (legitimize_pic_address): Access local symbols
relative to the GOT instead of relative to the literal pool base. relative to the GOT instead of relative to the literal pool base.
(s390_output_symbolic_const): Handle new GOT-relative accesses. (s390_output_symbolic_const): Handle new GOT-relative accesses.
* config/s390/s390.md ("call"): Access local functions and PLT stubs * config/s390/s390.md ("call"): Access local functions and PLT stubs
...@@ -21,7 +64,7 @@ ...@@ -21,7 +64,7 @@
("call_value"): Likewise. ("call_value"): Likewise.
("call_value_tls"): Likewise. ("call_value_tls"): Likewise.
* config/s390/s390.c (s390_chunkify_start): Remove pool anchor * config/s390/s390.c (s390_chunkify_start): Remove pool anchor
reloading. Support LTREL_BASE / LTREL_OFFSET construct. reloading. Support LTREL_BASE / LTREL_OFFSET construct.
(s390_chunkify_finish): Likewise. (s390_chunkify_finish): Likewise.
(s390_chunkify_cancel): Likewise. (s390_chunkify_cancel): Likewise.
...@@ -40,12 +83,12 @@ ...@@ -40,12 +83,12 @@
* config/s390/s390.c (s390_split_branches): Use LTREL_BASE/OFFSET. * config/s390/s390.c (s390_split_branches): Use LTREL_BASE/OFFSET.
(s390_load_got): New function. Use LTREL_BASE/OFFSET. (s390_load_got): New function. Use LTREL_BASE/OFFSET.
(s390_emit_prologue): Use it. (s390_emit_prologue): Use it.
* config/s390/s390.md ("builtin_longjmp", "builtin_setjmp_setup", * config/s390/s390.md ("builtin_longjmp", "builtin_setjmp_setup",
"builtin_setjmp_receiver"): Cleanup. Use s390_load_got. Do not "builtin_setjmp_receiver"): Cleanup. Use s390_load_got. Do not
hard-code register 14. hard-code register 14.
* config/s390/s390-protos.h (s390_load_got): Declare. * config/s390/s390-protos.h (s390_load_got): Declare.
* config/s390/s390.c (NR_C_MODES, constant_modes, gen_consttable): * config/s390/s390.c (NR_C_MODES, constant_modes, gen_consttable):
Support TImode constants. Support TImode constants.
* config/s390/s390.md ("consttable_ti"): New. * config/s390/s390.md ("consttable_ti"): New.
("consttable_si", "consttable_di"): Handle TLS symbols correctly. ("consttable_si", "consttable_di"): Handle TLS symbols correctly.
...@@ -61,7 +104,7 @@ ...@@ -61,7 +104,7 @@
"pool_start_64", "pool_end_64", "reload_base_31", "reload_base_64", "pool_start_64", "pool_end_64", "reload_base_31", "reload_base_64",
"pool", "literal_pool_31", "literal_pool_64"): Cleanup. Use "pool", "literal_pool_31", "literal_pool_64"): Cleanup. Use
symbolic UNSPEC values. symbolic UNSPEC values.
* config/s390/s390.c (larl_operand, s390_short_displacement, * config/s390/s390.c (larl_operand, s390_short_displacement,
bras_sym_operand, s390_cannot_force_const_mem, bras_sym_operand, s390_cannot_force_const_mem,
s390_delegitimize_address, s390_decompose_address, s390_delegitimize_address, s390_decompose_address,
legitimize_pic_address, s390_output_symbolic_const, legitimize_pic_address, s390_output_symbolic_const,
...@@ -163,7 +206,7 @@ ...@@ -163,7 +206,7 @@
2003-07-18 Kazu Hirata <kazu@cs.umass.edu> 2003-07-18 Kazu Hirata <kazu@cs.umass.edu>
* combine.c (simplify_comparison): Don't share rtx when converting * combine.c (simplify_comparison): Don't share rtx when converting
(ne (and (not X) 1) 0) to (eq (and X 1) 0). (ne (and (not X) 1) 0) to (eq (and X 1) 0).
2003-07-18 David Edelsohn <edelsohn@gnu.org> 2003-07-18 David Edelsohn <edelsohn@gnu.org>
......
...@@ -664,8 +664,6 @@ primary: ...@@ -664,8 +664,6 @@ primary:
if (pedantic) if (pedantic)
pedwarn ("ISO C forbids braced-groups within expressions"); pedwarn ("ISO C forbids braced-groups within expressions");
pop_label_level ();
saved_last_tree = COMPOUND_BODY ($1); saved_last_tree = COMPOUND_BODY ($1);
RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
last_tree = saved_last_tree; last_tree = saved_last_tree;
...@@ -677,7 +675,6 @@ primary: ...@@ -677,7 +675,6 @@ primary:
} }
| compstmt_primary_start error ')' | compstmt_primary_start error ')'
{ {
pop_label_level ();
last_tree = COMPOUND_BODY ($1); last_tree = COMPOUND_BODY ($1);
TREE_CHAIN (last_tree) = NULL_TREE; TREE_CHAIN (last_tree) = NULL_TREE;
$$ = error_mark_node; $$ = error_mark_node;
...@@ -2113,7 +2110,7 @@ label_decl: ...@@ -2113,7 +2110,7 @@ label_decl:
{ tree link; { tree link;
for (link = $2; link; link = TREE_CHAIN (link)) for (link = $2; link; link = TREE_CHAIN (link))
{ {
tree label = shadow_label (TREE_VALUE (link)); tree label = declare_label (TREE_VALUE (link));
C_DECLARED_LABEL_FLAG (label) = 1; C_DECLARED_LABEL_FLAG (label) = 1;
add_decl_stmt (label); add_decl_stmt (label);
} }
...@@ -2158,7 +2155,6 @@ compstmt_primary_start: ...@@ -2158,7 +2155,6 @@ compstmt_primary_start:
there is a way to turn off the entire subtree of blocks there is a way to turn off the entire subtree of blocks
that are contained in it. */ that are contained in it. */
keep_next_level (); keep_next_level ();
push_label_level ();
compstmt_count++; compstmt_count++;
$$ = add_stmt (build_stmt (COMPOUND_STMT, last_tree)); $$ = add_stmt (build_stmt (COMPOUND_STMT, last_tree));
} }
......
...@@ -197,6 +197,7 @@ extern void clear_parm_order (void); ...@@ -197,6 +197,7 @@ extern void clear_parm_order (void);
extern int complete_array_type (tree, tree, int); extern int complete_array_type (tree, tree, int);
extern void declare_parm_level (void); extern void declare_parm_level (void);
extern void undeclared_variable (tree); extern void undeclared_variable (tree);
extern tree declare_label (tree);
extern tree define_label (location_t, tree); extern tree define_label (location_t, tree);
extern void finish_decl (tree, tree, tree); extern void finish_decl (tree, tree, tree);
extern tree finish_enum (tree, tree, tree); extern tree finish_enum (tree, tree, tree);
...@@ -214,13 +215,10 @@ extern void parmlist_tags_warning (void); ...@@ -214,13 +215,10 @@ extern void parmlist_tags_warning (void);
extern void pending_xref_error (void); extern void pending_xref_error (void);
extern void c_push_function_context (struct function *); extern void c_push_function_context (struct function *);
extern void c_pop_function_context (struct function *); extern void c_pop_function_context (struct function *);
extern void pop_label_level (void);
extern void push_label_level (void);
extern void push_parm_decl (tree); extern void push_parm_decl (tree);
extern tree pushdecl_top_level (tree); extern tree pushdecl_top_level (tree);
extern void pushtag (tree, tree); extern void pushtag (tree, tree);
extern tree set_array_declarator_type (tree, tree, int); extern tree set_array_declarator_type (tree, tree, int);
extern tree shadow_label (tree);
extern void shadow_tag (tree); extern void shadow_tag (tree);
extern void shadow_tag_warned (tree, int); extern void shadow_tag_warned (tree, int);
extern tree start_enum (tree); extern tree start_enum (tree);
......
...@@ -424,7 +424,7 @@ extensions, accepted by GCC in C89 mode and in C++. ...@@ -424,7 +424,7 @@ extensions, accepted by GCC in C89 mode and in C++.
@menu @menu
* Statement Exprs:: Putting statements and declarations inside expressions. * Statement Exprs:: Putting statements and declarations inside expressions.
* Local Labels:: Labels local to a statement-expression. * Local Labels:: Labels local to a block.
* Labels as Values:: Getting pointers to labels, and computed gotos. * Labels as Values:: Getting pointers to labels, and computed gotos.
* Nested Functions:: As in Algol and Pascal, lexical scoping of functions. * Nested Functions:: As in Algol and Pascal, lexical scoping of functions.
* Constructing Calls:: Dispatching a call to another function. * Constructing Calls:: Dispatching a call to another function.
...@@ -577,10 +577,10 @@ bug.) ...@@ -577,10 +577,10 @@ bug.)
@cindex local labels @cindex local labels
@cindex macros, local labels @cindex macros, local labels
Each statement expression is a scope in which @dfn{local labels} can be GCC allows you to declare @dfn{local labels} in any nested block
declared. A local label is simply an identifier; you can jump to it scope. A local label is just like an ordinary label, but you can
with an ordinary @code{goto} statement, but only from within the only reference it (with a @code{goto} statement, or by taking its
statement expression it belongs to. address) within the block in which it was declared.
A local label declaration looks like this: A local label declaration looks like this:
...@@ -595,21 +595,38 @@ or ...@@ -595,21 +595,38 @@ or
__label__ @var{label1}, @var{label2}, /* @r{@dots{}} */; __label__ @var{label1}, @var{label2}, /* @r{@dots{}} */;
@end example @end example
Local label declarations must come at the beginning of the statement Local label declarations must come at the beginning of the block,
expression, right after the @samp{(@{}, before any ordinary before any ordinary declarations or statements.
declarations.
The label declaration defines the label @emph{name}, but does not define The label declaration defines the label @emph{name}, but does not define
the label itself. You must do this in the usual way, with the label itself. You must do this in the usual way, with
@code{@var{label}:}, within the statements of the statement expression. @code{@var{label}:}, within the statements of the statement expression.
The local label feature is useful because statement expressions are The local label feature is useful for complex macros. If a macro
often used in macros. If the macro contains nested loops, a @code{goto} contains nested loops, a @code{goto} can be useful for breaking out of
can be useful for breaking out of them. However, an ordinary label them. However, an ordinary label whose scope is the whole function
whose scope is the whole function cannot be used: if the macro can be cannot be used: if the macro can be expanded several times in one
expanded several times in one function, the label will be multiply function, the label will be multiply defined in that function. A
defined in that function. A local label avoids this problem. For local label avoids this problem. For example:
example:
@example
#define SEARCH(value, array, target) \
do @{ \
__label__ found; \
typeof (target) _SEARCH_target = (target); \
typeof (*(array)) *_SEARCH_array = (array); \
int i, j; \
int value; \
for (i = 0; i < max; i++) \
for (j = 0; j < max; j++) \
if (_SEARCH_array[i][j] == _SEARCH_target) \
@{ (value) = i; goto found; @} \
(value) = -1; \
found:; \
@} while (0)
@end example
This could also be written using a statement-expression:
@example @example
#define SEARCH(array, target) \ #define SEARCH(array, target) \
...@@ -629,6 +646,9 @@ example: ...@@ -629,6 +646,9 @@ example:
@}) @})
@end example @end example
Local label declarations also make the labels they declare visible to
nested functions, if there are any. @xref{Nested Functions}, for details.
@node Labels as Values @node Labels as Values
@section Labels as Values @section Labels as Values
@cindex labels as values @cindex labels as values
......
2003-07-19 Zack Weinberg <zack@codesourcery.com>
* gcc.dg/noncompile/label-1.c: New comprehensive test case for
diagnostics of ill-formed constructs involving labels.
* gcc.dg/noncompile/label-lineno-1.c: Add error regexp for
the new 'previously defined here' message.
2003-07-18 Nathan Sidwell <nathan@codesourcery.com> 2003-07-18 Nathan Sidwell <nathan@codesourcery.com>
* g++.dg/parse/non-dependent2.C: New test. * g++.dg/parse/non-dependent2.C: New test.
2003-07-18 Andrew Pinski <pinskia@physics.uc.edu> 2003-07-18 Andrew Pinski <pinskia@physics.uc.edu>
* g++.dg/init/init-ref4.C: xfail on targets without * g++.dg/init/init-ref4.C: xfail on targets without
weak symbols. weak symbols.
2003-07-17 Jakub Jelinek <jakub@redhat.com> 2003-07-17 Jakub Jelinek <jakub@redhat.com>
...@@ -278,7 +285,7 @@ ...@@ -278,7 +285,7 @@
* g++.dg/opt/emptyunion.C: New testcase. * g++.dg/opt/emptyunion.C: New testcase.
2003-07-07 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> 2003-07-07 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
Eric Botcazou <ebotcazou@libertysurf.fr> Eric Botcazou <ebotcazou@libertysurf.fr>
* g++.dg/opt/stack1.C: New test. * g++.dg/opt/stack1.C: New test.
...@@ -286,7 +293,7 @@ ...@@ -286,7 +293,7 @@
* g++.old-deja/g++.jason/typeid1.C: Make it a compile test, not a * g++.old-deja/g++.jason/typeid1.C: Make it a compile test, not a
run test. run test.
PR c++/11431 PR c++/11431
* g++.dg/expr/static_cast3.C: New test. * g++.dg/expr/static_cast3.C: New test.
......
/* Test various diagnostics of ill-formed constructs involving labels. */
/* { dg-do compile } */
/* { dg-options "-Wunused" } */
extern void dummy(void);
/* labels must be defined */
void a(void)
{
goto l; /* { dg-error "used but not defined" "no label" } */
}
/* warnings for labels defined but not used, or declared but not defined */
void b(void)
{
__label__ l;
l: /* { dg-warning "defined but not used" "no goto 1" } */
m: /* { dg-warning "defined but not used" "no goto 2" } */
dummy();
}
void c(void)
{
__label__ l; /* { dg-warning "declared but not defined" "only __label__" } */
dummy();
}
/* can't have two labels with the same name in the same function */
void d(void)
{
l: dummy(); /* { dg-error "previously defined" "prev def same scope" } */
l: dummy(); /* { dg-error "duplicate label" "dup label same scope" } */
goto l;
}
/* even at different scopes */
void e(void)
{
l: dummy(); /* { dg-error "previously defined" "prev def diff scope" } */
{
l: dummy(); /* { dg-error "duplicate label" "dup label diff scope" } */
}
goto l;
}
/* but, with __label__, you can */
void f(void)
{
l: dummy();
{
__label__ l;
l: dummy(); /* { dg-warning "defined but not used" "unused shadow 1" } */
};
goto l; /* this reaches the outer l */
}
/* a __label__ is not visible outside its scope */
void g(void)
{
dummy();
{
__label__ l;
l: dummy();
goto l;
}
goto l; /* { dg-error "used but not defined" "label ref out of scope" } */
}
/* __label__ can appear at top level of a function, too...
... but doesn't provide a definition of the label */
void h(void)
{
__label__ l;
dummy ();
goto l; /* { dg-error "used but not defined" "used, only __label__" } */
}
/* A nested function may not goto a label outside itself */
void i(void)
{
auto void nest(void);
l: nest();
void nest(void)
{
goto l; /* { dg-error "used but not defined" "nest use outer label" } */
}
goto l; /* reaches the outer l */
}
/* which means that a nested function may have its own label with the
same name as the outer function */
void j(void)
{
auto void nest(void);
l: nest();
void nest(void)
{
l: dummy(); /* { dg-warning "defined but not used" "nest label same name" } */
}
goto l; /* reaches the outer l */
}
/* and, turnabout, an outer function may not goto a label in a nested
function */
void k(void)
{
void nest(void)
{
l: dummy(); /* { dg-warning "defined but not used" "outer use nest label" } */
}
goto l; /* { dg-error "used but not defined" "outer use nest label" } */
nest();
}
/* not even with __label__ */
void l(void)
{
void nest(void)
{
__label__ l;
l: dummy(); /* { dg-warning "defined but not used" "outer use nest __label__" } */
}
goto l; /* { dg-error "used but not defined" "outer use nest __label__" } */
nest();
}
/* but if the outer label is declared with __label__, then a nested
function can goto that label (accomplishing a longjmp) */
void m(void)
{
__label__ l;
void nest(void) { goto l; }
nest();
dummy();
l:;
}
/* and that means the nested function cannot have its own label with
the same name as an outer label declared with __label__ */
void n(void)
{
__label__ l; /* { dg-error "previously declared" "outer label decl" } */
void nest(void)
{
l: goto l; /* { dg-error "duplicate label" "inner label defn" } */
}
l:
nest();
}
/* unless the nested function uses __label__ too! */
void o(void)
{
__label__ l;
void nest(void)
{
__label__ l;
l: goto l;
}
l: goto l;
nest();
}
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
void void
foo(int i) foo(int i)
{ {
my_label: my_label: /* { dg-error "previously defined" "prev label" } */
i++; 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