diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2010-08-23 07:55:51 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2010-08-23 07:55:51 +0000 |
commit | 4e6fbce4277fbc7c574fb2393c7dfe06f014c21a (patch) | |
tree | e7e3bb89dec1144843980740fb7feca37e3f0d3c /lib/Sema/SemaInit.cpp | |
parent | 2b5289b6fd7e3d9899868410a498c081c9595662 (diff) |
Relax the construction of a definition for implicit, trivial default
constructors. We perform semantic checking when creating the definition, and
this isn't needed in certain contexts (value initialization) but is in others
(default initialization). This fixes PR7948.
We add explicit code to the default initialization path to ensure the
definition is both present and valid.
Doug, please review. I think this follows your latest suggestion, and it ended
up remarkably cleaner than I anticipated. Also let me know if similar logic
should be followed for destructors and copy-constructors.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111802 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r-- | lib/Sema/SemaInit.cpp | 19 |
1 files changed, 15 insertions, 4 deletions
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 || |