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]

Fix designated initializers for anonymous structures (PR c/10676)


This patch fixes PR 10676, C designated initializers not being able to
reference the elements of anonymous structures and unions.  This is
part of implementing C1X requirements for anonymous structures and
unions.

Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  Applied
to mainline.

2010-05-09  Joseph Myers  <joseph@codesourcery.com>

	PR c/10676
	* c-typeck.c (lookup_field): Take a type directly.  Update
	recursive calls.
	(build_component_ref): Update call to lookup_field.
	(set_init_label): Use lookup_field to find initialized field.
	Handle returned list of fields like a sequence of designators.

testsuite:
2010-05-09  Joseph Myers  <joseph@codesourcery.com>

	PR c/10676
	* gcc.dg/anon-struct-10.c: New test.

Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 159204)
+++ gcc/c-typeck.c	(working copy)
@@ -1953,7 +1953,7 @@ default_conversion (tree exp)
   return exp;
 }
 
-/* Look up COMPONENT in a structure or union DECL.
+/* Look up COMPONENT in a structure or union TYPE.
 
    If the component name is not found, returns NULL_TREE.  Otherwise,
    the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL
@@ -1963,9 +1963,8 @@ default_conversion (tree exp)
    unions, the list steps down the chain to the component.  */
 
 static tree
-lookup_field (tree decl, tree component)
+lookup_field (tree type, tree component)
 {
-  tree type = TREE_TYPE (decl);
   tree field;
 
   /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
@@ -1995,7 +1994,7 @@ lookup_field (tree decl, tree component)
 		  if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
 		      || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
 		    {
-		      tree anon = lookup_field (field, component);
+		      tree anon = lookup_field (TREE_TYPE (field), component);
 
 		      if (anon)
 			return tree_cons (NULL_TREE, field, anon);
@@ -2031,7 +2030,7 @@ lookup_field (tree decl, tree component)
 	      && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
 		  || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
 	    {
-	      tree anon = lookup_field (field, component);
+	      tree anon = lookup_field (TREE_TYPE (field), component);
 
 	      if (anon)
 		return tree_cons (NULL_TREE, field, anon);
@@ -2074,7 +2073,7 @@ build_component_ref (location_t loc, tre
 	  return error_mark_node;
 	}
 
-      field = lookup_field (datum, component);
+      field = lookup_field (type, component);
 
       if (!field)
 	{
@@ -6983,7 +6982,7 @@ set_init_index (tree first, tree last,
 void
 set_init_label (tree fieldname, struct obstack * braced_init_obstack)
 {
-  tree tail;
+  tree field;
 
   if (set_designator (0, braced_init_obstack))
     return;
@@ -6997,23 +6996,26 @@ set_init_label (tree fieldname, struct o
       return;
     }
 
-  for (tail = TYPE_FIELDS (constructor_type); tail;
-       tail = TREE_CHAIN (tail))
-    {
-      if (DECL_NAME (tail) == fieldname)
-	break;
-    }
+  field = lookup_field (constructor_type, fieldname);
 
-  if (tail == 0)
+  if (field == 0)
     error ("unknown field %qE specified in initializer", fieldname);
   else
-    {
-      constructor_fields = tail;
-      designator_depth++;
-      designator_erroneous = 0;
-      if (constructor_range_stack)
-	push_range_stack (NULL_TREE, braced_init_obstack);
-    }
+    do
+      {
+	constructor_fields = TREE_VALUE (field);
+	designator_depth++;
+	designator_erroneous = 0;
+	if (constructor_range_stack)
+	  push_range_stack (NULL_TREE, braced_init_obstack);
+	field = TREE_CHAIN (field);
+	if (field)
+	  {
+	    if (set_designator (0, braced_init_obstack))
+	      return;
+	  }
+      }
+    while (field != NULL_TREE);
 }
 
 /* Add a new initializer to the tree of pending initializers.  PURPOSE
Index: gcc/testsuite/gcc.dg/anon-struct-10.c
===================================================================
--- gcc/testsuite/gcc.dg/anon-struct-10.c	(revision 0)
+++ gcc/testsuite/gcc.dg/anon-struct-10.c	(revision 0)
@@ -0,0 +1,57 @@
+/* Test for designated initializers for anonymous structures and
+   unions.  PR 10676.  */
+/* { dg-do run } */
+/* { dg-options "" } */
+
+extern void abort (void);
+extern void exit (int);
+
+struct s
+{
+  int a;
+  struct
+  {
+    int b;
+    int c;
+  };
+  union
+  {
+    int d;
+    struct
+    {
+      int e;
+    };
+  };
+  struct
+  {
+    struct
+    {
+      struct
+      {
+	int f;
+      };
+    };
+  };
+};
+
+struct s x =
+  {
+    .e = 5,
+    .b = 4,
+    .a = 3,
+    .f = 7,
+    .c = 9
+  };
+
+int
+main (void)
+{
+  if (x.a != 3
+      || x.b != 4
+      || x.c != 9
+      || x.d != 5
+      || x.e != 5
+      || x.f != 7)
+    abort ();
+  exit (0);
+}

-- 
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]