1 |
298 |
jeremybenn |
/* Test for handling of tags. "const struct foo;" and similar does
|
2 |
|
|
not redeclare an existing tag. */
|
3 |
|
|
/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
|
4 |
|
|
/* { dg-do compile } */
|
5 |
|
|
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
|
6 |
|
|
|
7 |
|
|
/* Plain "struct s;" always declares a tag: the same as one declared
|
8 |
|
|
in that scope, or shadowing one from an outer scope. */
|
9 |
|
|
struct s0;
|
10 |
|
|
struct s0 { int a; };
|
11 |
|
|
struct s0;
|
12 |
|
|
void f (void) { struct s0; }
|
13 |
|
|
|
14 |
|
|
/* A declaration with a qualifier or storage class specifier declares
|
15 |
|
|
the tag if no other declaration of it is visible. */
|
16 |
|
|
const union u0; /* { dg-warning "13:useless type qualifier in empty declaration" } */
|
17 |
|
|
union u0 { long b; };
|
18 |
|
|
|
19 |
|
|
extern struct s1; /* { dg-warning "15:useless storage class specifier in empty declaration" } */
|
20 |
|
|
|
21 |
|
|
/* But if a declaration of the tag is visible, whether at the same
|
22 |
|
|
scope or an outer scope, the declaration specifies the same type as
|
23 |
|
|
the previous declaration and does not redeclare the tag (C99
|
24 |
|
|
6.7.2.3#8). Thus, as it does not declare a declarator, a tag or
|
25 |
|
|
the members of an enumeration, it is a constraint violation. */
|
26 |
|
|
|
27 |
|
|
struct s2 { char x; };
|
28 |
|
|
const struct s2; /* { dg-error "14:empty declaration with type qualifier does not redeclare tag" } */
|
29 |
|
|
|
30 |
|
|
union u1;
|
31 |
|
|
extern union u1; /* { dg-error "14:empty declaration with storage class specifier does not redeclare tag" } */
|
32 |
|
|
|
33 |
|
|
union u2 { long b; };
|
34 |
|
|
void g(void) { const union u2; } /* { dg-error "28:empty declaration with type qualifier does not redeclare tag" } */
|
35 |
|
|
|
36 |
|
|
/* And it does not redeclare the tag either if the outer tag is the
|
37 |
|
|
wrong kind of tag. This also yields an error for the reference to
|
38 |
|
|
the wrong kind of tag in addition to the pedwarn for the empty
|
39 |
|
|
declaration. */
|
40 |
|
|
|
41 |
|
|
union u3 { float v; };
|
42 |
|
|
void h(void) { const struct u3; } /* { dg-error "29:'u3' defined as wrong kind of tag" } */
|
43 |
|
|
/* { dg-error "29:empty declaration with type qualifier does not redeclare tag" "wrong tag empty" { target *-*-* } 42 } */
|
44 |
|
|
|
45 |
|
|
/* However, such useless specifiers are OK if the contents of the tag
|
46 |
|
|
are being defined, or shadowed in an inner scope with the contents
|
47 |
|
|
included in the shadowing. */
|
48 |
|
|
|
49 |
|
|
struct s3;
|
50 |
|
|
const struct s3 { int a; }; /* { dg-warning "14:useless type qualifier in empty declaration" } */
|
51 |
|
|
|
52 |
|
|
union u4;
|
53 |
|
|
extern union u4 { int z; }; /* { dg-warning "14:useless storage class specifier in empty declaration" } */
|
54 |
|
|
|
55 |
|
|
enum e0 { E0 };
|
56 |
|
|
void i(void) { const enum e0 { E1 }; } /* { dg-warning "32:useless type qualifier in empty declaration" } */
|
57 |
|
|
|
58 |
|
|
union u5 { int p; };
|
59 |
|
|
void j(void) { extern struct u5 { int q; }; } /* { dg-warning "30:useless storage class specifier in empty declaration" } */
|