hintonda updated this revision to Diff 51114.
hintonda added a comment.

Address additional comments.

Always maintain SeenFields, not just when designators are seen which
simplies the logic.  Note that there is no getNumFields() method, so
we still need to determine the total FieldSize to initialize the
BitVector and loop through it.


http://reviews.llvm.org/D17407

Files:
  lib/Sema/SemaInit.cpp
  test/SemaCXX/cxx0x-initializer-constructor.cpp

Index: test/SemaCXX/cxx0x-initializer-constructor.cpp
===================================================================
--- test/SemaCXX/cxx0x-initializer-constructor.cpp
+++ test/SemaCXX/cxx0x-initializer-constructor.cpp
@@ -407,3 +407,34 @@
     [0] = 1, [2] = 3
   }; // expected-error {{ambiguous}} expected-note {{in implicit 
initialization of array element 1}}
 }
+
+namespace PR23514 {
+struct Test {
+  int& a;
+  int& b;
+};
+
+int d = 0;
+auto a = Test { .b = d, .a = d, };
+
+struct S { // expected-note-re 2{{candidate constructor (the implicit {{.*}} 
constructor) not viable: requires 1 argument, but 0 were provided}}
+  S(int a) {} // expected-note {{candidate constructor not viable: requires 
single argument 'a', but no arguments were provided}}
+};
+
+struct P {
+  char i1;
+  char i2;
+  S s;
+};
+
+P p1 { .s = 2, .i1 = 1, 1, };
+P p2 { .s = 2, .i1 = 1, };
+
+struct PP {
+  char i1;
+  S s1;
+  S s2; // expected-note {{in implicit initialization of field 's2' with 
omitted initializer}}
+};
+
+PP pp { .s1 = 2, .i1 = 1, }; // expected-error {{no matching constructor for 
initialization of 'PR23514::S'}}
+}
Index: lib/Sema/SemaInit.cpp
===================================================================
--- lib/Sema/SemaInit.cpp
+++ lib/Sema/SemaInit.cpp
@@ -1814,6 +1814,14 @@
   // worthwhile to skip over the rest of the initializer, though.
   RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
   RecordDecl::field_iterator FieldEnd = RD->field_end();
+  RecordDecl::field_iterator FieldStart = Field;
+  unsigned FieldSize = [FieldStart, FieldEnd]() mutable -> unsigned {
+    unsigned i = 0;
+    for (; FieldStart != FieldEnd; ++FieldStart, ++i)
+      /*empty*/;
+    return i;
+  }();
+  llvm::BitVector SeenFields(FieldSize);
   bool CheckForMissingFields = true;
   while (Index < IList->getNumInits()) {
     Expr *Init = IList->getInit(Index);
@@ -1833,6 +1841,10 @@
                                      true, TopLevelObject))
         hadError = true;
 
+      if (!hadError)
+        SeenFields.set(Field == FieldEnd ? FieldSize - 1
+                                         : Field->getFieldIndex() - 1);
+
       InitializedSomething = true;
 
       // Disable check for missing fields when designators are used.
@@ -1885,6 +1897,7 @@
       StructuredList->setInitializedFieldInUnion(*Field);
     }
 
+    SeenFields.set(Field->getFieldIndex());
     ++Field;
   }
 
@@ -1904,12 +1917,16 @@
     }
   }
 
-  // Check that any remaining fields can be value-initialized.
-  if (VerifyOnly && Field != FieldEnd && !DeclType->isUnionType() &&
-      !Field->getType()->isIncompleteArrayType()) {
-    // FIXME: Should check for holes left by designated initializers too.
-    for (; Field != FieldEnd && !hadError; ++Field) {
-      if (!Field->isUnnamedBitfield() && !Field->hasInClassInitializer())
+  // Check that any missing fields can be value-initialized.
+  if (VerifyOnly && !DeclType->isUnionType() &&
+      (Field != FieldEnd || !CheckForMissingFields)) {
+    Field = FieldStart;
+    for (unsigned i = 0; i < FieldSize && !hadError; ++i, ++Field) {
+      assert(Field != FieldEnd);
+      if (SeenFields[i])
+        continue;
+      if (!Field->isUnnamedBitfield() && !Field->hasInClassInitializer() &&
+          !Field->getType()->isIncompleteArrayType())
         CheckEmptyInitializable(
             InitializedEntity::InitializeMember(*Field, &Entity),
             IList->getLocEnd());


Index: test/SemaCXX/cxx0x-initializer-constructor.cpp
===================================================================
--- test/SemaCXX/cxx0x-initializer-constructor.cpp
+++ test/SemaCXX/cxx0x-initializer-constructor.cpp
@@ -407,3 +407,34 @@
     [0] = 1, [2] = 3
   }; // expected-error {{ambiguous}} expected-note {{in implicit initialization of array element 1}}
 }
+
+namespace PR23514 {
+struct Test {
+  int& a;
+  int& b;
+};
+
+int d = 0;
+auto a = Test { .b = d, .a = d, };
+
+struct S { // expected-note-re 2{{candidate constructor (the implicit {{.*}} constructor) not viable: requires 1 argument, but 0 were provided}}
+  S(int a) {} // expected-note {{candidate constructor not viable: requires single argument 'a', but no arguments were provided}}
+};
+
+struct P {
+  char i1;
+  char i2;
+  S s;
+};
+
+P p1 { .s = 2, .i1 = 1, 1, };
+P p2 { .s = 2, .i1 = 1, };
+
+struct PP {
+  char i1;
+  S s1;
+  S s2; // expected-note {{in implicit initialization of field 's2' with omitted initializer}}
+};
+
+PP pp { .s1 = 2, .i1 = 1, }; // expected-error {{no matching constructor for initialization of 'PR23514::S'}}
+}
Index: lib/Sema/SemaInit.cpp
===================================================================
--- lib/Sema/SemaInit.cpp
+++ lib/Sema/SemaInit.cpp
@@ -1814,6 +1814,14 @@
   // worthwhile to skip over the rest of the initializer, though.
   RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
   RecordDecl::field_iterator FieldEnd = RD->field_end();
+  RecordDecl::field_iterator FieldStart = Field;
+  unsigned FieldSize = [FieldStart, FieldEnd]() mutable -> unsigned {
+    unsigned i = 0;
+    for (; FieldStart != FieldEnd; ++FieldStart, ++i)
+      /*empty*/;
+    return i;
+  }();
+  llvm::BitVector SeenFields(FieldSize);
   bool CheckForMissingFields = true;
   while (Index < IList->getNumInits()) {
     Expr *Init = IList->getInit(Index);
@@ -1833,6 +1841,10 @@
                                      true, TopLevelObject))
         hadError = true;
 
+      if (!hadError)
+        SeenFields.set(Field == FieldEnd ? FieldSize - 1
+                                         : Field->getFieldIndex() - 1);
+
       InitializedSomething = true;
 
       // Disable check for missing fields when designators are used.
@@ -1885,6 +1897,7 @@
       StructuredList->setInitializedFieldInUnion(*Field);
     }
 
+    SeenFields.set(Field->getFieldIndex());
     ++Field;
   }
 
@@ -1904,12 +1917,16 @@
     }
   }
 
-  // Check that any remaining fields can be value-initialized.
-  if (VerifyOnly && Field != FieldEnd && !DeclType->isUnionType() &&
-      !Field->getType()->isIncompleteArrayType()) {
-    // FIXME: Should check for holes left by designated initializers too.
-    for (; Field != FieldEnd && !hadError; ++Field) {
-      if (!Field->isUnnamedBitfield() && !Field->hasInClassInitializer())
+  // Check that any missing fields can be value-initialized.
+  if (VerifyOnly && !DeclType->isUnionType() &&
+      (Field != FieldEnd || !CheckForMissingFields)) {
+    Field = FieldStart;
+    for (unsigned i = 0; i < FieldSize && !hadError; ++i, ++Field) {
+      assert(Field != FieldEnd);
+      if (SeenFields[i])
+        continue;
+      if (!Field->isUnnamedBitfield() && !Field->hasInClassInitializer() &&
+          !Field->getType()->isIncompleteArrayType())
         CheckEmptyInitializable(
             InitializedEntity::InitializeMember(*Field, &Entity),
             IList->getLocEnd());
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to