This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Anonymous structs/unions for C1X
- From: "Joseph S. Myers" <joseph at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 15 May 2010 19:08:12 +0000 (UTC)
- Subject: Anonymous structs/unions for C1X
This patch enables the appropriate subset of anonymous structures and
unions for C1X.
The subset includes the use of a typedef name for a structure or union
with no tag when defining an anonymous structure or union. In
accordance with the usual practice of allowing extensions from later
standard versions by default in gnu89 and gnu99 modes, this case is
now accepted by default rather than just with -std=c1x or
-fms-extensions (which previously enabled this along with other
cases). (flag_iso conditionals, such as that removed here, are
generally inappropriate when an extension does not affect the
interpretation of any valid ISO C program.)
My interpretation of the wording in C1X is that a structure with only
anonymous structs/unions and a flexible array member should be
allowed. This patch makes this allowed. I've queried this (and the
typedefs issue) on the WG14 reflector as the wording isn't entirely
clear.
Bootstrapped with no regressions on x86_64-unknown-linux-gnu. Applied
to mainline.
2010-05-15 Joseph Myers <joseph@codesourcery.com>
* 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:
2010-05-15 Joseph Myers <joseph@codesourcery.com>
* 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.
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi (revision 159430)
+++ gcc/doc/extend.texi (working copy)
@@ -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 const
@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
Index: gcc/testsuite/gcc.dg/c1x-anon-struct-2.c
===================================================================
--- gcc/testsuite/gcc.dg/c1x-anon-struct-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/c1x-anon-struct-2.c (revision 0)
@@ -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" } */
+}
Index: gcc/testsuite/gcc.dg/20080820.c
===================================================================
--- gcc/testsuite/gcc.dg/20080820.c (revision 159430)
+++ gcc/testsuite/gcc.dg/20080820.c (working copy)
@@ -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" } */
Index: gcc/testsuite/gcc.dg/c1x-anon-struct-1.c
===================================================================
--- gcc/testsuite/gcc.dg/c1x-anon-struct-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/c1x-anon-struct-1.c (revision 0)
@@ -0,0 +1,73 @@
+/* Test for anonymous structures and unions in C1X. */
+/* { dg-do compile } */
+/* { dg-options "-std=c1x -pedantic-errors" } */
+
+#include <stddef.h>
+
+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;
+}
Index: gcc/testsuite/gcc.dg/c90-anon-struct-1.c
===================================================================
--- gcc/testsuite/gcc.dg/c90-anon-struct-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/c90-anon-struct-1.c (revision 0)
@@ -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" } */
+};
Index: gcc/testsuite/gcc.dg/c99-anon-struct-1.c
===================================================================
--- gcc/testsuite/gcc.dg/c99-anon-struct-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/c99-anon-struct-1.c (revision 0)
@@ -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" } */
+};
Index: gcc/testsuite/gcc.dg/anon-struct-1.c
===================================================================
--- gcc/testsuite/gcc.dg/anon-struct-1.c (revision 159430)
+++ gcc/testsuite/gcc.dg/anon-struct-1.c (working copy)
@@ -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(st
/* 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 * sizeo
/* 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];
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c (revision 159430)
+++ gcc/c-decl.c (working copy)
@@ -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, t
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, t
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;
}
--
Joseph S. Myers
joseph@codesourcery.com