This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]