From 4bdd0a60b27aa25d23cc19e4ab23163edf1a363b Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Sat, 15 May 2010 20:07:01 +0100 Subject: c-decl.c (grokfield): Allow typedefs for anonymous structs and unions by default if... * 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. From-SVN: r159439 --- gcc/ChangeLog | 12 ++++++ gcc/c-decl.c | 33 +++++++++++---- gcc/doc/extend.texi | 8 ++-- gcc/testsuite/ChangeLog | 7 +++ gcc/testsuite/gcc.dg/20080820.c | 2 +- gcc/testsuite/gcc.dg/anon-struct-1.c | 10 ++--- gcc/testsuite/gcc.dg/c1x-anon-struct-1.c | 73 ++++++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/c1x-anon-struct-2.c | 57 +++++++++++++++++++++++++ gcc/testsuite/gcc.dg/c90-anon-struct-1.c | 12 ++++++ gcc/testsuite/gcc.dg/c99-anon-struct-1.c | 12 ++++++ 10 files changed, 208 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/c1x-anon-struct-1.c create mode 100644 gcc/testsuite/gcc.dg/c1x-anon-struct-2.c create mode 100644 gcc/testsuite/gcc.dg/c90-anon-struct-1.c create mode 100644 gcc/testsuite/gcc.dg/c99-anon-struct-1.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 61d0842..db8e005 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 03211d6..4bec97f 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 7a495eb..d141b14 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 1ce44f0..2ee5942 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 b9dd8a7..002edb1 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 587d59d..c599fa5 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 0000000..711fe65 --- /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 0000000..cb804311 --- /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 0000000..a3eb7f7 --- /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 0000000..87d4c34 --- /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" } */ +}; -- cgit v1.1