aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/testsuite/gcc.dg/c99-tag-3.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/testsuite/gcc.dg/c99-tag-3.c')
-rw-r--r--gcc-4.9/gcc/testsuite/gcc.dg/c99-tag-3.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/gcc-4.9/gcc/testsuite/gcc.dg/c99-tag-3.c b/gcc-4.9/gcc/testsuite/gcc.dg/c99-tag-3.c
new file mode 100644
index 000000000..a492037b0
--- /dev/null
+++ b/gcc-4.9/gcc/testsuite/gcc.dg/c99-tag-3.c
@@ -0,0 +1,59 @@
+/* Test for handling of tags. "const struct foo;" and similar does
+ not redeclare an existing tag. */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
+
+/* Plain "struct s;" always declares a tag: the same as one declared
+ in that scope, or shadowing one from an outer scope. */
+struct s0;
+struct s0 { int a; };
+struct s0;
+void f (void) { struct s0; }
+
+/* A declaration with a qualifier or storage class specifier declares
+ the tag if no other declaration of it is visible. */
+const union u0; /* { dg-warning "13:useless type qualifier in empty declaration" } */
+union u0 { long b; };
+
+extern struct s1; /* { dg-warning "15:useless storage class specifier in empty declaration" } */
+
+/* But if a declaration of the tag is visible, whether at the same
+ scope or an outer scope, the declaration specifies the same type as
+ the previous declaration and does not redeclare the tag (C99
+ 6.7.2.3#8). Thus, as it does not declare a declarator, a tag or
+ the members of an enumeration, it is a constraint violation. */
+
+struct s2 { char x; };
+const struct s2; /* { dg-error "14:empty declaration with type qualifier does not redeclare tag" } */
+
+union u1;
+extern union u1; /* { dg-error "14:empty declaration with storage class specifier does not redeclare tag" } */
+
+union u2 { long b; };
+void g(void) { const union u2; } /* { dg-error "28:empty declaration with type qualifier does not redeclare tag" } */
+
+/* And it does not redeclare the tag either if the outer tag is the
+ wrong kind of tag. This also yields an error for the reference to
+ the wrong kind of tag in addition to the pedwarn for the empty
+ declaration. */
+
+union u3 { float v; };
+void h(void) { const struct u3; } /* { dg-error "29:'u3' defined as wrong kind of tag" } */
+/* { dg-error "29:empty declaration with type qualifier does not redeclare tag" "wrong tag empty" { target *-*-* } 42 } */
+
+/* However, such useless specifiers are OK if the contents of the tag
+ are being defined, or shadowed in an inner scope with the contents
+ included in the shadowing. */
+
+struct s3;
+const struct s3 { int a; }; /* { dg-warning "14:useless type qualifier in empty declaration" } */
+
+union u4;
+extern union u4 { int z; }; /* { dg-warning "14:useless storage class specifier in empty declaration" } */
+
+enum e0 { E0 };
+void i(void) { const enum e0 { E1 }; } /* { dg-warning "32:useless type qualifier in empty declaration" } */
+
+union u5 { int p; };
+void j(void) { extern struct u5 { int q; }; } /* { dg-warning "30:useless storage class specifier in empty declaration" } */