176 lines
3.6 KiB
C
176 lines
3.6 KiB
C
/* 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-message "note: previous definition" "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-message "note: previous definition" "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-message "note: previous declaration" "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();
|
|
}
|