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

Improve efficiency by only keeping track of seen fields, and only when
designators have been used.


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
@@ -1728,6 +1728,9 @@
   // 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.
+  unsigned FieldIdx = 0;
+  std::vector<unsigned> SeenFields;
+  RecordDecl::field_iterator FieldStart = Field;
   RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
   RecordDecl::field_iterator FieldEnd = RD->field_end();
   bool InitializedSomething = false;
@@ -1750,6 +1753,20 @@
                                      true, TopLevelObject))
         hadError = true;
 
+      if (CheckForMissingFields)
+        for (unsigned i = 0; i < FieldIdx; ++i)
+          SeenFields.push_back(i);
+      unsigned idx = 0;
+      for (RecordDecl::field_iterator f = FieldStart;
+           f != FieldEnd; ++idx, ++f) {
+        auto Next = f;
+        if (++Next == Field) {
+          FieldIdx = idx;
+          break;
+        }
+      }
+      SeenFields.push_back(FieldIdx);
+      ++FieldIdx;
       InitializedSomething = true;
 
       // Disable check for missing fields when designators are used.
@@ -1773,6 +1790,9 @@
 
     if (Field->isUnnamedBitfield()) {
       // Don't initialize unnamed bitfields, e.g. "int : 20;"
+      if (!CheckForMissingFields)
+        SeenFields.push_back(FieldIdx);
+      ++FieldIdx;
       ++Field;
       continue;
     }
@@ -1785,6 +1805,9 @@
       InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field,
                                           IList->getInit(Index)->getLocStart());
     if (InvalidUse) {
+      if (!CheckForMissingFields)
+        SeenFields.push_back(FieldIdx);
+      ++FieldIdx;
       ++Index;
       ++Field;
       hadError = true;
@@ -1802,6 +1825,9 @@
       StructuredList->setInitializedFieldInUnion(*Field);
     }
 
+    if (!CheckForMissingFields)
+      SeenFields.push_back(FieldIdx);
+    ++FieldIdx;
     ++Field;
   }
 
@@ -1821,12 +1847,33 @@
     }
   }
 
+  if (!CheckForMissingFields) {
+    std::sort(SeenFields.begin(), SeenFields.end());
+    SeenFields.erase(std::unique(SeenFields.begin(), SeenFields.end()), SeenFields.end());
+  } else
+    FieldStart = Field;
+  SmallVector<RecordDecl::field_iterator, 10> MissingFields;
+  unsigned Idx = 0;
+  for (auto i : SeenFields) {
+    while (Idx < i) {
+      MissingFields.push_back(FieldStart);
+      ++FieldStart;
+      ++Idx;
+    }
+    ++FieldStart;
+    ++Idx;
+  }
+  while (FieldStart != FieldEnd)
+    MissingFields.push_back(FieldStart++);
+
   // 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())
+  if (VerifyOnly && MissingFields.size() && !DeclType->isUnionType()) {
+    for (auto MissedField : MissingFields) {
+      Field = MissedField;
+      if (hadError)
+        break;
+      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