diff options
author | Zack Weinberg <zack@gcc.gnu.org> | 2003-07-19 23:32:55 +0000 |
---|---|---|
committer | Zack Weinberg <zack@gcc.gnu.org> | 2003-07-19 23:32:55 +0000 |
commit | 14e33ee85629ee9bfb7185eadb27a9066bb02687 (patch) | |
tree | 39921ed41b276ac3aff0d0ef4a2b474488855a70 /gcc/testsuite/gcc.dg/noncompile/label-1.c | |
parent | 1b339d862abe1a3858536ba5f204218daed6a49a (diff) | |
download | gcc-14e33ee85629ee9bfb7185eadb27a9066bb02687.zip gcc-14e33ee85629ee9bfb7185eadb27a9066bb02687.tar.gz gcc-14e33ee85629ee9bfb7185eadb27a9066bb02687.tar.bz2 |
* 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
Diffstat (limited to 'gcc/testsuite/gcc.dg/noncompile/label-1.c')
-rw-r--r-- | gcc/testsuite/gcc.dg/noncompile/label-1.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/noncompile/label-1.c b/gcc/testsuite/gcc.dg/noncompile/label-1.c new file mode 100644 index 0000000..c646b48 --- /dev/null +++ b/gcc/testsuite/gcc.dg/noncompile/label-1.c @@ -0,0 +1,175 @@ +/* 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(); +} |