From: jsm28 Date: Sat, 15 May 2010 19:07:01 +0000 (+0000) Subject: * c-decl.c (grokfield): Allow typedefs for anonymous structs and X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=afb3d3c49fad6249e0b85722105326e9031d9475;hp=a107223431e030ac4b0e41c1f956ae43a63a5aa5;ds=sidebyside * c-decl.c (grokfield): Allow typedefs for anonymous structs and unions by default if those structs and unions have no tags. Do not condition anonymous struct and unions handling on flag_iso. Allow anonymous structs and unions for C1X. (finish_struct): Do not diagnose lack of named fields when anonymous structs and unions present for C1X. Accept flexible array members in structure with anonymous structs or unions but no directly named fields. * doc/extend.texi (Unnamed Fields): Update. testsuite: * gcc.dg/c1x-anon-struct-1.c, gcc.dg/c1x-anon-struct-2.c, gcc.dg/c90-anon-struct-1.c, gcc.dg/c99-anon-struct-1.c: New tests. * gcc.dg/20080820.c, gcc.dg/anon-struct-1.c: Update expected diagnostics and type sizes. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@159439 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 61d08427dca..db8e0050792 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2010-05-15 Joseph Myers + + * c-decl.c (grokfield): Allow typedefs for anonymous structs and + unions by default if those structs and unions have no tags. Do + not condition anonymous struct and unions handling on flag_iso. + Allow anonymous structs and unions for C1X. + (finish_struct): Do not diagnose lack of named fields when + anonymous structs and unions present for C1X. Accept flexible + array members in structure with anonymous structs or unions but no + directly named fields. + * doc/extend.texi (Unnamed Fields): Update. + 2010-05-15 Eric Botcazou * gimple.h (compare_field_offset): Rename into... diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 03211d674d7..4bec97f1989 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -6567,6 +6567,8 @@ grokfield (location_t loc, Otherwise this is a forward declaration of a structure tag. If this is something of the form "foo;" and foo is a TYPE_DECL, then + If foo names a structure or union without a tag, then this + is an anonymous struct (this is permitted by C1X). If MS extensions are enabled and foo names a structure, then again this is an anonymous struct. Otherwise this is an error. @@ -6580,14 +6582,11 @@ grokfield (location_t loc, || TREE_CODE (type) == UNION_TYPE); bool ok = false; - if (type_ok - && (flag_ms_extensions || !declspecs->typedef_p)) + if (type_ok) { if (flag_ms_extensions) ok = true; - else if (flag_iso) - ok = false; - else if (TYPE_NAME (type) == NULL) + else if (TYPE_NAME (TYPE_MAIN_VARIANT (type)) == NULL) ok = true; else ok = false; @@ -6597,7 +6596,15 @@ grokfield (location_t loc, pedwarn (loc, 0, "declaration does not declare anything"); return NULL_TREE; } - pedwarn (loc, OPT_pedantic, "ISO C doesn%'t support unnamed structs/unions"); + if (!flag_isoc1x) + { + if (flag_isoc99) + pedwarn (loc, OPT_pedantic, + "ISO C99 doesn%'t support unnamed structs/unions"); + else + pedwarn (loc, OPT_pedantic, + "ISO C90 doesn%'t support unnamed structs/unions"); + } } value = grokdeclarator (declarator, declspecs, FIELD, false, @@ -6789,8 +6796,14 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, if (pedantic) { for (x = fieldlist; x; x = TREE_CHAIN (x)) - if (DECL_NAME (x) != 0) - break; + { + if (DECL_NAME (x) != 0) + break; + if (flag_isoc1x + && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)) + break; + } if (x == 0) { @@ -6893,7 +6906,9 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, pedwarn (DECL_SOURCE_LOCATION (x), OPT_pedantic, "invalid use of structure with flexible array member"); - if (DECL_NAME (x)) + if (DECL_NAME (x) + || TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE) saw_named_field = 1; } diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 7a495ebfd64..d141b14f575 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -12727,7 +12727,8 @@ versions earlier than 4.4. @cindex struct @cindex union -For compatibility with other compilers, GCC allows you to define +As permitted by ISO C1X and for compatibility with other compilers, +GCC allows you to define a structure or union that contains, as fields, structures and unions without names. For example: @@ -12765,11 +12766,12 @@ The compiler gives errors for such constructs. @opindex fms-extensions Unless @option{-fms-extensions} is used, the unnamed field must be a structure or union definition without a tag (for example, @samp{struct -@{ int a; @};}). If @option{-fms-extensions} is used, the field may +@{ int a; @};}), or a @code{typedef} name for such a structure or +union. If @option{-fms-extensions} is used, the field may also be a definition with a tag such as @samp{struct foo @{ int a; @};}, a reference to a previously defined structure or union such as @samp{struct foo;}, or a reference to a @code{typedef} name for a -previously defined structure or union type. +previously defined structure or union type with a tag. @node Thread-Local @section Thread-Local Storage diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1ce44f0c05c..2ee5942ebd2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2010-05-15 Joseph Myers + + * gcc.dg/c1x-anon-struct-1.c, gcc.dg/c1x-anon-struct-2.c, + gcc.dg/c90-anon-struct-1.c, gcc.dg/c99-anon-struct-1.c: New tests. + * gcc.dg/20080820.c, gcc.dg/anon-struct-1.c: Update expected + diagnostics and type sizes. + 2010-05-15 Eric Botcazou * gnat.dg/lto9.adb: New test. diff --git a/gcc/testsuite/gcc.dg/20080820.c b/gcc/testsuite/gcc.dg/20080820.c index b9dd8a7c897..002edb1ddf9 100644 --- a/gcc/testsuite/gcc.dg/20080820.c +++ b/gcc/testsuite/gcc.dg/20080820.c @@ -1,4 +1,4 @@ /* { dg-do compile } */ /* { dg-options "-fshow-column -fms-extensions -pedantic" } */ -struct { struct a { int x; }; int bar; } hot; /* { dg-warning "29:ISO C doesn't support unnamed" } */ +struct { struct a { int x; }; int bar; } hot; /* { dg-warning "29:ISO C90 doesn't support unnamed" } */ diff --git a/gcc/testsuite/gcc.dg/anon-struct-1.c b/gcc/testsuite/gcc.dg/anon-struct-1.c index 587d59d7220..c599fa5669b 100644 --- a/gcc/testsuite/gcc.dg/anon-struct-1.c +++ b/gcc/testsuite/gcc.dg/anon-struct-1.c @@ -1,4 +1,4 @@ -/* { dg-options "-std=iso9899:1990" } */ +/* { dg-options "-std=iso9899:1990 -pedantic" } */ /* In strict ISO C mode, we don't recognize the anonymous struct/union extension or any Microsoft extensions. */ @@ -21,10 +21,10 @@ char testD[sizeof(struct D) == sizeof(struct A) ? 1 : -1]; /* GNU extension. */ struct E { - struct { char z; }; /* { dg-warning "does not declare anything" } */ + struct { char z; }; /* { dg-warning "unnamed structs" } */ char e; }; -char testE[sizeof(struct E) == sizeof(struct A) ? 1 : -1]; + /* MS extension. */ typedef struct A typedef_A; @@ -49,8 +49,8 @@ char testH[sizeof(struct H) == 2 * sizeof(struct A) ? 1 : -1]; /* Make sure __extension__ gets turned back off. */ struct I { - struct { char z; }; /* { dg-warning "does not declare anything" } */ + struct { char z; }; /* { dg-warning "unnamed structs" } */ char i; }; -char testI[sizeof(struct I) == sizeof(struct A) ? 1 : -1]; +char testI[sizeof(struct I) == sizeof(struct E) ? 1 : -1]; diff --git a/gcc/testsuite/gcc.dg/c1x-anon-struct-1.c b/gcc/testsuite/gcc.dg/c1x-anon-struct-1.c new file mode 100644 index 00000000000..711fe65df3d --- /dev/null +++ b/gcc/testsuite/gcc.dg/c1x-anon-struct-1.c @@ -0,0 +1,73 @@ +/* Test for anonymous structures and unions in C1X. */ +/* { dg-do compile } */ +/* { dg-options "-std=c1x -pedantic-errors" } */ + +#include + +typedef struct +{ + int i; +} s0; + +typedef union +{ + int i; +} u0; + +struct s1 +{ + int a; + u0; + struct + { + int b; + }; +}; + +union u1 +{ + int b; + s0; + union + { + int c; + }; +}; + +struct s2 +{ + struct + { + int a; + }; +}; + +struct s3 +{ + u0; +}; + +struct s4 +{ + struct + { + int i; + }; + int a[]; +}; + +struct s1 x = + { + .b = 1, + .i = 2, + .a = 3 + }; + +int o = offsetof (struct s1, i); + +void +f (void) +{ + x.i = 3; + (&x)->i = 4; +} diff --git a/gcc/testsuite/gcc.dg/c1x-anon-struct-2.c b/gcc/testsuite/gcc.dg/c1x-anon-struct-2.c new file mode 100644 index 00000000000..cb8043117d5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c1x-anon-struct-2.c @@ -0,0 +1,57 @@ +/* Test for anonymous structures and unions in C1X. Test for invalid + cases. */ +/* { dg-do compile } */ +/* { dg-options "-std=c1x -pedantic-errors" } */ + +typedef struct s0 +{ + int i; +} s0; + +struct s1 +{ + int a; + struct s0; /* { dg-error "declaration does not declare anything" } */ +}; + +struct s2 +{ + int a; + s0; /* { dg-error "declaration does not declare anything" } */ +}; + +struct s3 +{ + struct + { + int i; + }; + struct + { + int i; /* { dg-error "duplicate member" } */ + }; +}; + +struct s4 +{ + int a; + struct s + { + int i; + }; /* { dg-error "declaration does not declare anything" } */ +}; + +struct s5 +{ + struct + { + int i; + } a; + int b; +} x; + +void +f (void) +{ + x.i = 0; /* { dg-error "has no member" } */ +} diff --git a/gcc/testsuite/gcc.dg/c90-anon-struct-1.c b/gcc/testsuite/gcc.dg/c90-anon-struct-1.c new file mode 100644 index 00000000000..a3eb7f7e392 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c90-anon-struct-1.c @@ -0,0 +1,12 @@ +/* Test for anonymous structures and unions not permitted in C90. */ +/* { dg-do compile } */ +/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */ + +struct s +{ + int a; + struct + { + int b; + }; /* { dg-error "unnamed structs" } */ +}; diff --git a/gcc/testsuite/gcc.dg/c99-anon-struct-1.c b/gcc/testsuite/gcc.dg/c99-anon-struct-1.c new file mode 100644 index 00000000000..87d4c3438eb --- /dev/null +++ b/gcc/testsuite/gcc.dg/c99-anon-struct-1.c @@ -0,0 +1,12 @@ +/* Test for anonymous structures and unions not permitted in C99. */ +/* { dg-do compile } */ +/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */ + +struct s +{ + int a; + struct + { + int b; + }; /* { dg-error "unnamed structs" } */ +};