summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CodeGenFunction.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-02-18 19:59:28 +0000
committerJohn McCall <rjmccall@apple.com>2010-02-18 19:59:28 +0000
commit5c60a6f5970e581fdcb0638d80e1fd0998bcca6c (patch)
tree1fb14bbb5612297b6e606e7a7d2c88fd83cf6fe5 /clang/lib/CodeGen/CodeGenFunction.cpp
parent441eb781ae20447e9d9b9ffc314ab4a9b8d9babc (diff)
downloadbcm5719-llvm-5c60a6f5970e581fdcb0638d80e1fd0998bcca6c.tar.gz
bcm5719-llvm-5c60a6f5970e581fdcb0638d80e1fd0998bcca6c.zip
Make deleting and complete dtor variants defer to other dtor variants by
calling them as subroutines. This triggers whenever the alias optimization doesn't, i.e. when the dtor has linkonce linkage or there are virtual bases or it's the deleting dtor. llvm-svn: 96605
Diffstat (limited to 'clang/lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp54
1 files changed, 42 insertions, 12 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index ddf4e6431d0..98113a700ec 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -248,39 +248,69 @@ void CodeGenFunction::GenerateBody(GlobalDecl GD, llvm::Function *Fn,
Stmt *Body = FD->getBody();
assert((Body || FD->isImplicit()) && "non-implicit function def has no body");
+ bool SkipBody = false; // should get jump-threaded
+
// Emit special ctor/dtor prologues.
- llvm::BasicBlock *DtorEpilogue = 0;
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
+ // Emit the constructor prologue, i.e. the base and member initializers.
EmitCtorPrologue(CD, GD.getCtorType());
+
+ // TODO: for complete, non-varargs variants, we can get away with
+ // just emitting the vbase initializers, then calling the base
+ // constructor.
+
} else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
- DtorEpilogue = createBasicBlock("dtor.epilogue");
+ // In all cases, if there's an exception in the body (or delegate)
+ // we'll still need to run the epilogue.
+ llvm::BasicBlock *DtorEpilogue = createBasicBlock("dtor.epilogue");
PushCleanupBlock(DtorEpilogue);
- InitializeVtablePtrs(DD->getParent());
+ // If this is the deleting variant, invoke the complete variant;
+ // the epilogue will call the appropriate operator delete().
+ if (GD.getDtorType() == Dtor_Deleting) {
+ EmitCXXDestructorCall(DD, Dtor_Complete, LoadCXXThis());
+ SkipBody = true;
+
+ // If this is the complete variant, just invoke the base variant;
+ // the epilogue will destruct the virtual bases.
+ } else if (GD.getDtorType() == Dtor_Complete) {
+ EmitCXXDestructorCall(DD, Dtor_Base, LoadCXXThis());
+ SkipBody = true;
+
+ // Otherwise, we're in the base variant, so we need to ensure the
+ // vtable ptrs are right before emitting the body.
+ } else {
+ InitializeVtablePtrs(DD->getParent());
+ }
}
// Emit the body of the function.
- if (!Body)
+ if (SkipBody) {
+ // skipped
+ } else if (!Body) {
SynthesizeImplicitFunctionBody(GD, Fn, Args);
- else {
+ } else {
if (isa<CXXTryStmt>(Body))
OuterTryBlock = cast<CXXTryStmt>(Body);
-
EmitStmt(Body);
}
- // Emit special ctor/ctor epilogues.
+ // Emit special ctor/dtor epilogues.
if (isa<CXXConstructorDecl>(FD)) {
- // If any of the member initializers are temporaries bound to references
- // make sure to emit their destructors.
+ // Be sure to emit any cleanup blocks associated with the member
+ // or base initializers, which includes (along the exceptional
+ // path) the destructors for those members and bases that were
+ // fully constructed.
EmitCleanupBlocks(0);
+
} else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
+ // Funnel the previously-pushed cleanup block into the epilogue.
CleanupBlockInfo Info = PopCleanupBlock();
- assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!");
+ EmitBlock(Info.CleanupBlock);
- EmitBlock(DtorEpilogue);
EmitDtorEpilogue(DD, GD.getDtorType());
-
+
+ // Go ahead and link in the switch and end blocks.
if (Info.SwitchBlock)
EmitBlock(Info.SwitchBlock);
if (Info.EndBlock)
OpenPOWER on IntegriCloud