Index: lib/Sema/SemaInit.cpp =================================================================== --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -1730,6 +1730,11 @@ // worthwhile to skip over the rest of the initializer, though. RecordDecl *RD = DeclType->getAs()->getDecl(); RecordDecl::field_iterator FieldEnd = RD->field_end(); + SmallVector RemainingFields; + for (auto f = Field; f != FieldEnd; ++f) { + RemainingFields.push_back(f); + } + RemainingFields.push_back(FieldEnd); bool InitializedSomething = false; bool CheckForMissingFields = true; while (Index < IList->getNumInits()) { @@ -1750,6 +1755,12 @@ true, TopLevelObject)) hadError = true; + RemainingFields.erase( + std::remove_if(RemainingFields.begin(), RemainingFields.end(), + [&Field, &FieldEnd](RecordDecl::field_iterator f) { + return (f != FieldEnd && ++f == Field); + }), + RemainingFields.end()); InitializedSomething = true; // Disable check for missing fields when designators are used. @@ -1773,6 +1784,11 @@ if (Field->isUnnamedBitfield()) { // Don't initialize unnamed bitfields, e.g. "int : 20;" + RemainingFields.erase( + std::remove_if( + RemainingFields.begin(), RemainingFields.end(), + [&Field](RecordDecl::field_iterator f) { return (f == Field); }), + RemainingFields.end()); ++Field; continue; } @@ -1786,6 +1802,11 @@ IList->getInit(Index)->getLocStart()); if (InvalidUse) { ++Index; + RemainingFields.erase( + std::remove_if( + RemainingFields.begin(), RemainingFields.end(), + [&Field](RecordDecl::field_iterator f) { return (f == Field); }), + RemainingFields.end()); ++Field; hadError = true; continue; @@ -1802,6 +1823,11 @@ StructuredList->setInitializedFieldInUnion(*Field); } + RemainingFields.erase( + std::remove_if( + RemainingFields.begin(), RemainingFields.end(), + [&Field](RecordDecl::field_iterator f) { return (f == Field); }), + RemainingFields.end()); ++Field; } @@ -1824,8 +1850,9 @@ // 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) { + for (auto Field : RemainingFields) { + if (Field == FieldEnd || hadError) + break; if (!Field->isUnnamedBitfield() && !Field->hasInClassInitializer()) CheckEmptyInitializable( InitializedEntity::InitializeMember(*Field, &Entity), 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'}} +}