aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaInit.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-12-16 18:50:27 +0000
committerDouglas Gregor <dgregor@apple.com>2009-12-16 18:50:27 +0000
commit16006c901315fa12a108b4e571f187f4b676e426 (patch)
tree0a429cf4eeeadf701786ee980d6f47d55bccb0ac /lib/Sema/SemaInit.cpp
parent79433b59915859126a774fcd09fa32d7d5a1a3ef (diff)
When value-initializing a class with no user-defined constructors but
with a non-trivial default constructor, zero-initialize the storage and then call the default constructor. Fixes PR5800. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91548 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r--lib/Sema/SemaInit.cpp44
1 files changed, 34 insertions, 10 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 20008a7c1c..629ab9adb3 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -444,6 +444,9 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
if (Field->isUnnamedBitfield())
continue;
+ if (hadError)
+ return;
+
InitializedEntity MemberEntity
= InitializedEntity::InitializeMember(*Field, &Entity);
if (Init >= NumInits || !ILE->getInit(Init)) {
@@ -477,7 +480,7 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
= InitSeq.Perform(SemaRef, MemberEntity, Kind,
Sema::MultiExprArg(SemaRef, 0, 0));
if (MemberInit.isInvalid()) {
- hadError = 0;
+ hadError = true;
return;
}
@@ -529,6 +532,9 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
for (unsigned Init = 0; Init != NumElements; ++Init) {
+ if (hadError)
+ return;
+
if (ElementEntity.getKind() == InitializedEntity::EK_ArrayOrVectorElement)
ElementEntity.setElementIndex(Init);
@@ -546,7 +552,7 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
= InitSeq.Perform(SemaRef, ElementEntity, Kind,
Sema::MultiExprArg(SemaRef, 0, 0));
if (ElementInit.isInvalid()) {
- hadError = 0;
+ hadError = true;
return;
}
@@ -585,7 +591,7 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
if (!hadError) {
bool RequiresSecondPass = false;
FillInValueInitializations(Entity, FullyStructuredList, RequiresSecondPass);
- if (RequiresSecondPass)
+ if (RequiresSecondPass && !hadError)
FillInValueInitializations(Entity, FullyStructuredList,
RequiresSecondPass);
}
@@ -2619,8 +2625,16 @@ static void TryValueInitialization(Sema &S,
if (ClassDecl->hasUserDeclaredConstructor())
return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);
- // FIXME: non-union class type w/ non-trivial default constructor gets
- // zero-initialized, then constructor gets called.
+ // -- if T is a (possibly cv-qualified) non-union class type
+ // without a user-provided constructor, then the object is
+ // zero-initialized and, if T’s implicitly-declared default
+ // constructor is non-trivial, that constructor is called.
+ if ((ClassDecl->getTagKind() == TagDecl::TK_class ||
+ ClassDecl->getTagKind() == TagDecl::TK_struct) &&
+ !ClassDecl->hasTrivialConstructor()) {
+ Sequence.AddZeroInitializationStep(Entity.getType().getType());
+ return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);
+ }
}
}
@@ -3050,6 +3064,7 @@ InitializationSequence::Perform(Sema &S,
// Walk through the computed steps for the initialization sequence,
// performing the specified conversions along the way.
+ bool ConstructorInitRequiresZeroInit = false;
for (step_iterator Step = step_begin(), StepEnd = step_end();
Step != StepEnd; ++Step) {
if (CurInit.isInvalid())
@@ -3216,7 +3231,8 @@ InitializationSequence::Perform(Sema &S,
// Build the an expression that constructs a temporary.
CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor,
- move_arg(ConstructorArgs));
+ move_arg(ConstructorArgs),
+ ConstructorInitRequiresZeroInit);
if (CurInit.isInvalid())
return S.ExprError();
@@ -3224,14 +3240,22 @@ InitializationSequence::Perform(Sema &S,
}
case SK_ZeroInitialization: {
- if (Kind.getKind() == InitializationKind::IK_Value &&
- S.getLangOptions().CPlusPlus &&
- !Kind.isImplicitValueInit())
+ step_iterator NextStep = Step;
+ ++NextStep;
+ if (NextStep != StepEnd &&
+ NextStep->Kind == SK_ConstructorInitialization) {
+ // The need for zero-initialization is recorded directly into
+ // the call to the object's constructor within the next step.
+ ConstructorInitRequiresZeroInit = true;
+ } else if (Kind.getKind() == InitializationKind::IK_Value &&
+ S.getLangOptions().CPlusPlus &&
+ !Kind.isImplicitValueInit()) {
CurInit = S.Owned(new (S.Context) CXXZeroInitValueExpr(Step->Type,
Kind.getRange().getBegin(),
Kind.getRange().getEnd()));
- else
+ } else {
CurInit = S.Owned(new (S.Context) ImplicitValueInitExpr(Step->Type));
+ }
break;
}
}