From: Joseph Myers Date: Wed, 31 Jan 2001 10:24:40 +0000 (+0000) Subject: c-parse.in (structsp): Pedwarn when "enum foo" refers to an incomplete type. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0aca1a4fd3d3f5fbfbbbfcc8e29a3f1cbb45d56a;p=gcc.git c-parse.in (structsp): Pedwarn when "enum foo" refers to an incomplete type. * c-parse.in (structsp): Pedwarn when "enum foo" refers to an incomplete type. (typename): Call pending_xref_error after parsing typed_typespecs. * c-decl.c (lookup_tag): Give error immediately rather than leaving it pending if the tag of the wrong type is in the same binding level. (xref_tag): Don't pedwarn for forward declarations of enum types here. * gcc.texi (Actual Bugs): Remove entry for misuse of struct, union and enum tags. testsuite: * gcc.dg/c99-tag-1.c: New test. From-SVN: r39372 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a8dc0b2c495..eb1d068063c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2001-01-31 Joseph S. Myers + + * c-parse.in (structsp): Pedwarn when "enum foo" refers to an + incomplete type. + (typename): Call pending_xref_error after parsing typed_typespecs. + * c-decl.c (lookup_tag): Give error immediately rather than + leaving it pending if the tag of the wrong type is in the same + binding level. + (xref_tag): Don't pedwarn for forward declarations of enum types + here. + * gcc.texi (Actual Bugs): Remove entry for misuse of struct, union + and enum tags. + 2001-01-31 Alexandre Oliva * config/float-sparc.h (LDBL_MAX) [sparc32]: Fix typo. diff --git a/gcc/c-decl.c b/gcc/c-decl.c index edbe9cea503..b49f786b4c0 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -2815,6 +2815,7 @@ lookup_tag (code, name, binding_level, thislevel_only) int thislevel_only; { register struct binding_level *level; + int thislevel = 1; for (level = binding_level; level; level = level->level_chain) { @@ -2829,12 +2830,22 @@ lookup_tag (code, name, binding_level, thislevel_only) pending_invalid_xref = name; pending_invalid_xref_file = input_filename; pending_invalid_xref_line = lineno; + /* If in the same binding level as a declaration as a tag + of a different type, this must not be allowed to + shadow that tag, so give the error immediately. + (For example, "struct foo; union foo;" is invalid.) */ + if (thislevel) + pending_xref_error (); } return TREE_VALUE (tail); } } - if (thislevel_only && ! level->tag_transparent) - return NULL_TREE; + if (! level->tag_transparent) + { + if (thislevel_only) + return NULL_TREE; + thislevel = 0; + } } return NULL_TREE; } @@ -5112,9 +5123,6 @@ xref_tag (code, name) ref = make_node (code); if (code == ENUMERAL_TYPE) { - /* (In ANSI, Enums can be referred to only if already defined.) */ - if (pedantic) - pedwarn ("ISO C forbids forward references to `enum' types"); /* Give the type a default layout like unsigned int to avoid crashing if it does not get defined. */ TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node); diff --git a/gcc/c-parse.in b/gcc/c-parse.in index 5b32768866c..a51161c85a8 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -1397,7 +1397,11 @@ structsp: { $$ = finish_enum ($3, nreverse ($4), chainon ($1, $7)); } | enum_head identifier - { $$ = xref_tag (ENUMERAL_TYPE, $2); } + { $$ = xref_tag (ENUMERAL_TYPE, $2); + /* In ISO C, enumerated types can be referred to + only if already defined. */ + if (pedantic && !COMPLETE_TYPE_P ($$)) + pedwarn ("ISO C forbids forward references to `enum' types"); } ; maybecomma: @@ -1534,8 +1538,10 @@ enumerator: ; typename: - typed_typespecs absdcl - { $$ = build_tree_list ($1, $2); } + typed_typespecs + { pending_xref_error (); } + absdcl + { $$ = build_tree_list ($1, $3); } | nonempty_type_quals absdcl { $$ = build_tree_list ($1, $2); } ; diff --git a/gcc/gcc.texi b/gcc/gcc.texi index 177c2ee08c8..99f2433f89f 100644 --- a/gcc/gcc.texi +++ b/gcc/gcc.texi @@ -536,10 +536,6 @@ The @code{fixproto} script will sometimes add prototypes for the edit the offending file and place the typedef in front of the prototypes. -@item -There are several obscure case of mis-using struct, union, and -enum tags that are not detected as errors by the compiler. - @item When @samp{-pedantic-errors} is specified, GCC will incorrectly give an error message when a function name is specified in an expression diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3cb1be4d249..755db77284d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2001-01-31 Joseph S. Myers + + * gcc.dg/c99-tag-1.c: New test. + 2001-01-31 Neil Booth * gcc.dg/cpp/tr-warn1.c: Add tests. diff --git a/gcc/testsuite/gcc.dg/c99-tag-1.c b/gcc/testsuite/gcc.dg/c99-tag-1.c new file mode 100644 index 00000000000..293636154ad --- /dev/null +++ b/gcc/testsuite/gcc.dg/c99-tag-1.c @@ -0,0 +1,136 @@ +/* Test for handling of tags (6.7.2.3). */ +/* Origin: Joseph Myers */ +/* { dg-do compile } */ +/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */ + +void +foo (void) +{ + /* Forward declarations of structs and unions are OK; those of enums are + not. */ + { + struct s0; + struct s1 *x0; + union u0; + union u1 *x1; + enum e0; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "forward" "enum forward 1" { target *-*-* } 16 } */ + enum e1 *x2; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "forward" "enum forward 2" { target *-*-* } 18 } */ + /* GCC used to fail to diagnose a use of an enum inside its definition. */ + enum e2 { E2A = sizeof (enum e2 *) }; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "forward" "enum forward 3" { target *-*-* } 21 } */ + } + /* A specific type shall have its content defined at most once. But we + may redeclare the tag in different scopes. */ + { + struct s0 { int i; }; + { + struct s0 { long l; }; + } + { + union s0 { long l; }; + } + struct s0 { int i; }; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "rede" "struct redef" { target *-*-* } 34 } */ + union u0 { int i; }; + { + union u0 { long l; }; + } + { + struct u0 { long l; }; + } + union u0 { int i; }; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "rede" "union redef" { target *-*-* } 43 } */ + enum e0 { E0A }; + { + enum e0 { E0B }; + } + { + struct e0 { long l; }; + } + enum e0 { E0B }; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "rede" "enum redef" { target *-*-* } 52 } */ + } + /* Structure, union and enumerated types have a single namespace of tags. */ + { + struct s0; + struct s1; + struct s2 { int i; }; + struct s2; + struct s3 { int i; }; + struct s2 sv; + union u0; + union u2 { int i; }; + union u2; + union u2 uv; + enum e0 { E0A }; + enum e1 { E1A }; + /* None of the following are allowed; some were not detected by GCC. */ + union s0; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "wrong" "wrong tag type" { target *-*-* } 70 } */ + union s1 { int i; }; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "wrong" "wrong tag type" { target *-*-* } 72 } */ + union s2; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "wrong" "wrong tag type" { target *-*-* } 74 } */ + union s3 { int i; }; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "wrong" "wrong tag type" { target *-*-* } 76 } */ + enum u0 { U0A }; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "wrong" "wrong tag type" { target *-*-* } 78 } */ + enum u2 { U2A }; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "wrong" "wrong tag type" { target *-*-* } 80 } */ + struct e0; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "wrong" "wrong tag type" { target *-*-* } 82 } */ + struct e1 { int i; }; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "wrong" "wrong tag type" { target *-*-* } 84 } */ + } + /* Explicit shadowing in inner scopes is OK, but references to the tag + that don't explicitly shadow it must (whether in declarations or + expressions) use the correct one of struct/union/enum. */ + { + struct s0; + struct s1; + struct s2 { int i; }; + struct s2; + struct s3 { int i; }; + struct s2 sv; + union u0; + union u2 { int i; }; + union u2; + union u2 uv; + enum e0 { E0A }; + enum e1 { E1A }; + { + union s0; + union s1; + union s2; + union s3; + struct u0; + struct u2; + struct e0; + union e1; + } + { + union s0 *x0; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "wrong" "wrong tag type" { target *-*-* } 114 } */ + int x1[sizeof (union s1 *)]; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "wrong" "wrong tag type" { target *-*-* } 116 } */ + struct t; + union s2 *x2; + /* { dg-error "wrong" "wrong tag type" { target *-*-* } 119 } */ + int x3[sizeof (union s3 *)]; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "wrong" "wrong tag type" { target *-*-* } 121 } */ + struct u; + enum u0 *y0; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "wrong|forward" "wrong tag type" { target *-*-* } 124 } */ + int y1[sizeof (enum u2 *)]; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "wrong" "wrong tag type" { target *-*-* } 126 } */ + struct v; + struct e0 *z0; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "wrong" "wrong tag type" { target *-*-* } 129 } */ + int z1[sizeof (struct e1 *)]; /* { dg-bogus "warning" "warning in place of error" } */ + /* { dg-error "wrong" "wrong tag type" { target *-*-* } 131 } */ + struct w; + } + } +}