More refactoring around constructor/destructor code generation.
Fix some bugs with function-try-blocks and simplify normal try-block
code generation.
This implementation excludes a deleting destructor's call to
operator delete() from the function-try-block, which I believe
is correct but which I can't find straightforward support for at
a moment's glance.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96670 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 98113a7..7337590 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -241,80 +241,16 @@
}
}
-void CodeGenFunction::GenerateBody(GlobalDecl GD, llvm::Function *Fn,
- FunctionArgList &Args) {
- const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
+void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args) {
+ const FunctionDecl *FD = cast<FunctionDecl>(CurGD.getDecl());
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.
- 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)) {
- // 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);
-
- // 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 (SkipBody) {
- // skipped
- } else if (!Body) {
- SynthesizeImplicitFunctionBody(GD, Fn, Args);
- } else {
- if (isa<CXXTryStmt>(Body))
- OuterTryBlock = cast<CXXTryStmt>(Body);
+ if (Body)
EmitStmt(Body);
- }
-
- // Emit special ctor/dtor epilogues.
- if (isa<CXXConstructorDecl>(FD)) {
- // 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();
- EmitBlock(Info.CleanupBlock);
-
- EmitDtorEpilogue(DD, GD.getDtorType());
-
- // Go ahead and link in the switch and end blocks.
- if (Info.SwitchBlock)
- EmitBlock(Info.SwitchBlock);
- if (Info.EndBlock)
- EmitBlock(Info.EndBlock);
+ else {
+ assert(FD->isImplicit() && "non-implicit function def has no body");
+ assert(FD->isCopyAssignment() && "implicit function not copy assignment");
+ SynthesizeCXXCopyAssignment(Args);
}
}
@@ -328,7 +264,6 @@
FunctionArgList Args;
CurGD = GD;
- OuterTryBlock = 0;
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
if (MD->isInstance()) {
// Create the implicit 'this' decl.
@@ -368,7 +303,12 @@
StartFunction(GD, FD->getResultType(), Fn, Args, BodyRange.getBegin());
// Generate the body of the function.
- GenerateBody(GD, Fn, Args);
+ if (isa<CXXDestructorDecl>(FD))
+ EmitDestructorBody(Args);
+ else if (isa<CXXConstructorDecl>(FD))
+ EmitConstructorBody(Args);
+ else
+ EmitFunctionBody(Args);
// Emit the standard function epilogue.
FinishFunction(BodyRange.getEnd());