diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 36a1e4e2778f58c378bfe249913802d9ed11192b..6a62a1a12dfdc466b3e2142384692c5ce64bf0d5 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -7654,8 +7654,10 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { unsigned TypeQuals; if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) { - if (!Constructor->isUsed(false)) - DefineImplicitDefaultConstructor(Loc, Constructor); + if (Constructor->getParent()->hasTrivialConstructor()) + return; + if (!Constructor->isUsed(false)) + DefineImplicitDefaultConstructor(Loc, Constructor); } else if (Constructor->isImplicit() && Constructor->isCopyConstructor(TypeQuals)) { if (!Constructor->isUsed(false)) diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 6d7d3a9b107c9422f0c05fbe8e673a330b8153f7..7fc23d610ecd8faa50e29ad4464aadf535ebf76c 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -2862,8 +2862,8 @@ static void TryDefaultInitialization(Sema &S, // constructor for T is called (and the initialization is ill-formed if // T has no accessible default constructor); if (DestType->isRecordType() && S.getLangOptions().CPlusPlus) { - return TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType, - Sequence); + TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType, Sequence); + return; } // - otherwise, no initialization is performed. @@ -3838,14 +3838,25 @@ InitializationSequence::Perform(Sema &S, SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid()) ? Kind.getEqualLoc() : Kind.getLocation(); - + + if (Kind.getKind() == InitializationKind::IK_Default) { + // Force even a trivial, implicit default constructor to be + // semantically checked. We do this explicitly because we don't build + // the definition for completely trivial constructors. + CXXRecordDecl *ClassDecl = Constructor->getParent(); + assert(ClassDecl && "No parent class for constructor."); + if (Constructor->isImplicit() && Constructor->isDefaultConstructor() && + ClassDecl->hasTrivialConstructor() && !Constructor->isUsed(false)) + S.DefineImplicitDefaultConstructor(Loc, Constructor); + } + // Determine the arguments required to actually perform the constructor // call. if (S.CompleteConstructorCall(Constructor, move(Args), Loc, ConstructorArgs)) return S.ExprError(); - // Build the expression that constructs a temporary. + if (Entity.getKind() == InitializedEntity::EK_Temporary && NumArgs != 1 && // FIXME: Hack to work around cast weirdness (Kind.getKind() == InitializationKind::IK_Direct || diff --git a/test/SemaCXX/default-constructor-initializers.cpp b/test/SemaCXX/default-constructor-initializers.cpp index 757332df0b058056bcf663c506faa49422b50cd9..9da85567beda64f9ead56d1ea8ad858299493b06 100644 --- a/test/SemaCXX/default-constructor-initializers.cpp +++ b/test/SemaCXX/default-constructor-initializers.cpp @@ -43,7 +43,6 @@ Y4 y4; // More tests - struct Z1 { // expected-error {{must explicitly initialize the reference member 'z'}} \ // expected-error {{must explicitly initialize the const member 'c1'}} int& z; // expected-note {{declared here}} @@ -51,5 +50,12 @@ struct Z1 { // expected-error {{must explicitly initialize the reference member volatile int v1; }; +// Test default initialization which *requires* a constructor call for non-POD. Z1 z1; // expected-note {{first required here}} +// Ensure that value initialization doesn't use trivial implicit constructors. +namespace PR7948 { + // Note that this is also non-POD to ensure we don't just special case PODs. + struct S { const int x; ~S(); }; + const S arr[2] = { { 42 } }; +}