summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2013-02-01 05:11:40 +0000
committerJohn McCall <rjmccall@apple.com>2013-02-01 05:11:40 +0000
commit12cc42aa1b29168020a0d671314b39f7bd8a3d68 (patch)
treecf61d0818fbc612e9b99bb955eafcf6f541806ca /clang/lib/CodeGen
parentbc0e5c0114d68be7d86ca76ae466af56ac96ee4d (diff)
downloadbcm5719-llvm-12cc42aa1b29168020a0d671314b39f7bd8a3d68.tar.gz
bcm5719-llvm-12cc42aa1b29168020a0d671314b39f7bd8a3d68.zip
Destroy arrays and ARC fields when throwing out of ctors.
Previously we were only handling non-array fields of class type. Testcases derived from a patch by WenHan Gu. llvm-svn: 174146
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGClass.cpp36
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp13
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h2
3 files changed, 20 insertions, 31 deletions
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 0611ed7834f..ce32acd0da1 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -532,21 +532,6 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF,
CGF.EmitBlock(AfterFor, true);
}
-namespace {
- struct CallMemberDtor : EHScopeStack::Cleanup {
- llvm::Value *V;
- CXXDestructorDecl *Dtor;
-
- CallMemberDtor(llvm::Value *V, CXXDestructorDecl *Dtor)
- : V(V), Dtor(Dtor) {}
-
- void Emit(CodeGenFunction &CGF, Flags flags) {
- CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
- /*Delegating=*/false, V);
- }
- };
-}
-
static void EmitMemberInitializer(CodeGenFunction &CGF,
const CXXRecordDecl *ClassDecl,
CXXCtorInitializer *MemberInit,
@@ -652,22 +637,13 @@ void CodeGenFunction::EmitInitializerForField(FieldDecl *Field,
EmitAggMemberInitializer(*this, LHS, Init, ArrayIndexVar, FieldType,
ArrayIndexes, 0);
-
- if (!CGM.getLangOpts().Exceptions)
- return;
-
- // FIXME: If we have an array of classes w/ non-trivial destructors,
- // we need to destroy in reverse order of construction along the exception
- // path.
- const RecordType *RT = FieldType->getAs<RecordType>();
- if (!RT)
- return;
-
- CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- if (!RD->hasTrivialDestructor())
- EHStack.pushCleanup<CallMemberDtor>(EHCleanup, LHS.getAddress(),
- RD->getDestructor());
}
+
+ // Ensure that we destroy this object if an exception is thrown
+ // later in the constructor.
+ QualType::DestructionKind dtorKind = FieldType.isDestructedType();
+ if (needsEHCleanup(dtorKind))
+ pushEHDestroy(dtorKind, LHS.getAddress(), FieldType);
}
/// Checks whether the given constructor is a valid subject for the
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index ac45339515b..a43a38360b1 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1242,7 +1242,18 @@ CodeGenFunction::getDestroyer(QualType::DestructionKind kind) {
llvm_unreachable("Unknown DestructionKind");
}
-/// pushDestroy - Push the standard destructor for the given type.
+/// pushEHDestroy - Push the standard destructor for the given type as
+/// an EH-only cleanup.
+void CodeGenFunction::pushEHDestroy(QualType::DestructionKind dtorKind,
+ llvm::Value *addr, QualType type) {
+ assert(dtorKind && "cannot push destructor for trivial type");
+ assert(needsEHCleanup(dtorKind));
+
+ pushDestroy(EHCleanup, addr, type, getDestroyer(dtorKind), true);
+}
+
+/// pushDestroy - Push the standard destructor for the given type as
+/// at least a normal cleanup.
void CodeGenFunction::pushDestroy(QualType::DestructionKind dtorKind,
llvm::Value *addr, QualType type) {
assert(dtorKind && "cannot push destructor for trivial type");
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 99bb8e37f45..15fd10ccc43 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1282,6 +1282,8 @@ public:
void pushDestroy(QualType::DestructionKind dtorKind,
llvm::Value *addr, QualType type);
+ void pushEHDestroy(QualType::DestructionKind dtorKind,
+ llvm::Value *addr, QualType type);
void pushDestroy(CleanupKind kind, llvm::Value *addr, QualType type,
Destroyer *destroyer, bool useEHCleanupForArray);
void emitDestroy(llvm::Value *addr, QualType type, Destroyer *destroyer,
OpenPOWER on IntegriCloud