]> granicus.if.org Git - clang/commitdiff
Fix a bug with designated initializers where we were stepping out of a
authorDouglas Gregor <dgregor@apple.com>
Thu, 12 Feb 2009 19:00:39 +0000 (19:00 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 12 Feb 2009 19:00:39 +0000 (19:00 +0000)
union subobject initialization before checking whether the next
initiailizer was actually a designated initializer. This led to
spurious "excess elements in union initializer" errors. Thanks to
rdivacky for reporting the bug!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64392 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaInit.cpp
test/Sema/designated-initializers.c

index 27d8d5aa2e55499cd894a2ab56de5d4e58f9d334..b54a8d674b2477f114c5bba56f88af40fa90f15b 100644 (file)
@@ -742,14 +742,13 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
     return;
   }
 
-
-
   // If structDecl is a forward declaration, this loop won't do
   // anything except look at designated initializers; That's okay,
   // because an error should get printed out elsewhere. It might be
   // worthwhile to skip over the rest of the initializer, though.
   RecordDecl *RD = DeclType->getAsRecordType()->getDecl();
   RecordDecl::field_iterator FieldEnd = RD->field_end();
+  bool InitializedSomething = false;
   while (Index < IList->getNumInits()) {
     Expr *Init = IList->getInit(Index);
 
@@ -768,11 +767,7 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
                                      true, TopLevelObject))
         hadError = true;
 
-      // Abort early for unions: the designator handled the
-      // initialization of the appropriate field.
-      if (DeclType->isUnionType())
-        break;
-
+      InitializedSomething = true;
       continue;
     }
 
@@ -781,6 +776,10 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
       break;
     }
 
+    // We've already initialized a member of a union. We're done.
+    if (InitializedSomething && DeclType->isUnionType())
+      break;
+
     // If we've hit the flexible array member at the end, we're done.
     if (Field->getType()->isIncompleteArrayType())
       break;
@@ -793,11 +792,11 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
 
     CheckSubElementType(IList, Field->getType(), Index,
                         StructuredList, StructuredIndex);
+    InitializedSomething = true;
 
     if (DeclType->isUnionType()) {
       // Initialize the first field within the union.
       StructuredList->setInitializedFieldInUnion(*Field);
-      break;
     }
 
     ++Field;
index 9c4429d02da34e66ae981a1604e29f8020462470..7c6ddca8ef2e7d3f9feb9c83363398aae07d4190 100644 (file)
@@ -172,3 +172,17 @@ struct bar saloon = {
   .f.arr[3] = 1,
   .arr = { &f }
 };
+
+typedef unsigned char u_char;
+typedef unsigned short u_short;
+
+union wibble {
+        u_char  arr1[6];
+        u_short arr2[3];
+};
+
+const union wibble wobble = { .arr2[0] = 0xffff,
+                              .arr2[1] = 0xffff,
+                              .arr2[2] = 0xffff };
+
+const union wibble wobble2 = { .arr2 = {4, 5, 6}, 7 }; // expected-error{{excess elements in union initializer}}