diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2000,6 +2000,9 @@ !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()); bool HasDesignatedInit = false; + unsigned FieldSize = std::distance(RD->field_begin(), RD->field_end()); + llvm::BitVector SeenFields(FieldSize); + while (Index < IList->getNumInits()) { Expr *Init = IList->getInit(Index); SourceLocation InitLoc = Init->getBeginLoc(); @@ -2032,6 +2035,10 @@ } } + if (!hadError) + SeenFields.set(Field == FieldEnd ? FieldSize - 1 + : Field->getFieldIndex() - 1); + InitializedSomething = true; // Disable check for missing fields when designators are used. @@ -2045,6 +2052,8 @@ break; } + SeenFields.set(Field->getFieldIndex()); + // We've already initialized a member of a union. We're done. if (InitializedSomething && DeclType->isUnionType()) break; @@ -2111,12 +2120,15 @@ } } - // 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 unseen fields can be value-initialized. + if (VerifyOnly && TopLevelObject && !DeclType->isUnionType() && + (Field != FieldEnd || HasDesignatedInit)) { + Field = RD->field_begin(); + for (unsigned i = 0; i < FieldSize && !hadError; ++i, ++Field) { + if (SeenFields[i]) + continue; + if(!Field->isUnnamedBitfield() && !Field->hasInClassInitializer() && + !Field->getType()->isIncompleteArrayType()) CheckEmptyInitializable( InitializedEntity::InitializeMember(*Field, &Entity), IList->getEndLoc()); diff --git a/clang/test/SemaCXX/cxx0x-initializer-constructor.cpp b/clang/test/SemaCXX/cxx0x-initializer-constructor.cpp --- a/clang/test/SemaCXX/cxx0x-initializer-constructor.cpp +++ b/clang/test/SemaCXX/cxx0x-initializer-constructor.cpp @@ -409,3 +409,21 @@ [0] = 1, [2] = 3 }; // expected-error {{ambiguous}} expected-note {{in implicit initialization of array element 1}} } + +namespace PR23514 { +struct Q { // expected-note-re 4{{candidate constructor (the implicit {{(copy|move)}} constructor) not viable: requires 1 argument, but 0 were provided}} + Q(int) {} // expected-note 2{{candidate constructor not viable: requires 1 argument, but 0 were provided}} +}; +struct A { + Q x, y; // expected-note 2{{in implicit initialization of field 'x' with omitted initializer}} +}; +struct B { + int i; + A a; + int k; +}; +B w = {.a.y = 0, 0, .a.x = 10}; +B x = {.a.y = 0, 0}; // expected-error {{no matching constructor for initialization of 'PR23514::Q'}} +B y = {.a = {.y = 0, .x = 0}, 0}; +B z = {.a = {.y = 0}, 0}; // expected-error {{no matching constructor for initialization of 'PR23514::Q'}} +} // namespace PR23514