Index: lib/Sema/SemaInit.cpp =================================================================== --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -1812,6 +1812,10 @@ // 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; + unsigned MaxFieldIdx = 0; + llvm::BitVector SeenFields; + RecordDecl::field_iterator FieldStart = Field; RecordDecl *RD = DeclType->getAs()->getDecl(); RecordDecl::field_iterator FieldEnd = RD->field_end(); bool CheckForMissingFields = true; @@ -1833,6 +1837,26 @@ true, TopLevelObject)) hadError = true; + if (!hadError) { + if (CheckForMissingFields) { + unsigned FieldSize{0}; + for (RecordDecl::field_iterator f = FieldStart; f != FieldEnd; ++f) { + FieldSize++; + } + MaxFieldIdx = FieldSize - 1; + SeenFields.resize(FieldSize); + for (unsigned i = 0; i < FieldIdx; ++i) + SeenFields.set(i); + } + if (Field == FieldEnd) { + FieldIdx = MaxFieldIdx; + } else { + FieldIdx = Field->getFieldIndex() - 1; + } + SeenFields.set(FieldIdx); + ++FieldIdx; + } + InitializedSomething = true; // Disable check for missing fields when designators are used. @@ -1856,6 +1880,7 @@ if (Field->isUnnamedBitfield()) { // Don't initialize unnamed bitfields, e.g. "int : 20;" + ++FieldIdx; ++Field; continue; } @@ -1885,6 +1910,9 @@ StructuredList->setInitializedFieldInUnion(*Field); } + if (!CheckForMissingFields && !hadError) + SeenFields.set(FieldIdx); + ++FieldIdx; ++Field; } @@ -1904,15 +1932,37 @@ } } - // 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()) - CheckEmptyInitializable( - InitializedEntity::InitializeMember(*Field, &Entity), - IList->getLocEnd()); + if (!hadError) { + SmallVector MissingFields; + if (CheckForMissingFields) { + FieldStart = Field; + } else { + for (int Idx = 0, SeenIdx = SeenFields.find_first(); SeenIdx != -1; + SeenIdx = SeenFields.find_next(SeenIdx)) { + while (Idx < SeenIdx) { + MissingFields.push_back(FieldStart); + ++FieldStart; + ++Idx; + } + ++FieldStart; + ++Idx; + } + } + while (FieldStart != FieldEnd) { + MissingFields.push_back(FieldStart); + ++FieldStart; + } + + // Check that any remaining fields can be value-initialized. + if (VerifyOnly && MissingFields.size() && !DeclType->isUnionType()) { + for (auto MissedField : MissingFields) { + Field = MissedField; + 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'}} +}