diff options
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 19 | ||||
-rw-r--r-- | test/SemaCXX/default-constructor-initializers.cpp | 8 |
3 files changed, 26 insertions, 7 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 36a1e4e277..6a62a1a12d 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 6d7d3a9b10..7fc23d610e 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 757332df0b..9da85567be 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 } }; +} |