aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CodeGenFunction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp54
1 files changed, 42 insertions, 12 deletions
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index ddf4e6431d..98113a700e 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/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)