diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index d9051675ba01..863b09c86a99 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -590,17 +590,44 @@ void CodeGenFunction::EmitClassCopyAssignment( Callee, ReturnValueSlot(), CallArgs, MD); } -/// SynthesizeDefaultConstructor - synthesize a default constructor -void -CodeGenFunction::SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor, - CXXCtorType Type, - llvm::Function *Fn, - const FunctionArgList &Args) { - assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor"); - StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args, - SourceLocation()); - EmitCtorPrologue(Ctor, Type); - FinishFunction(); +/// Synthesizes an implicit function body. Since these only arise in +/// C++, we only do them in C++. +void CodeGenFunction::SynthesizeImplicitFunctionBody(GlobalDecl GD, + llvm::Function *Fn, + const FunctionArgList &Args) { + const FunctionDecl *FD = cast(GD.getDecl()); + + // FIXME: this should become isImplicitlyDefined() once we properly + // support that for C++0x. + assert(FD->isImplicit() && "Cannot synthesize a non-implicit function"); + + if (const CXXConstructorDecl *CD = dyn_cast(FD)) { + assert(!CD->isTrivial() && "shouldn't need to synthesize a trivial ctor"); + + if (CD->isDefaultConstructor()) { + // Sema generates base and member initializers as for this, so + // the ctor prologue is good enough here. + return; + } else { + assert(CD->isCopyConstructor()); + return SynthesizeCXXCopyConstructor(CD, GD.getCtorType(), Fn, Args); + } + } + + if (isa(FD)) { + // The dtor epilogue does everything we'd need to do here. + return; + } + + const CXXMethodDecl *MD = cast(FD); + + // FIXME: in C++0x we might have user-declared copy assignment operators + // coexisting with implicitly-defined ones. + assert(MD->isCopyAssignment() && + !MD->getParent()->hasUserDeclaredCopyAssignment() && + "Cannot synthesize a method that is not an implicitly-defined " + "copy constructor"); + SynthesizeCXXCopyAssignment(MD, Fn, Args); } /// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a @@ -627,8 +654,6 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor, assert(!ClassDecl->hasUserDeclaredCopyConstructor() && "SynthesizeCXXCopyConstructor - copy constructor has definition already"); assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor"); - StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args, - SourceLocation()); FunctionArgList::const_iterator i = Args.begin(); const VarDecl *ThisArg = i->first; @@ -698,7 +723,6 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor, } InitializeVtablePtrs(ClassDecl); - FinishFunction(); } /// SynthesizeCXXCopyAssignment - Implicitly define copy assignment operator. @@ -728,7 +752,6 @@ void CodeGenFunction::SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD, const CXXRecordDecl *ClassDecl = cast(CD->getDeclContext()); assert(!ClassDecl->hasUserDeclaredCopyAssignment() && "SynthesizeCXXCopyAssignment - copy assignment has user declaration"); - StartFunction(CD, CD->getResultType(), Fn, Args, SourceLocation()); FunctionArgList::const_iterator i = Args.begin(); const VarDecl *ThisArg = i->first; @@ -796,8 +819,6 @@ void CodeGenFunction::SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD, // return *this; Builder.CreateStore(LoadOfThis, ReturnValue); - - FinishFunction(); } static void EmitBaseInitializer(CodeGenFunction &CGF, @@ -1054,20 +1075,6 @@ void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD, } } -void CodeGenFunction::SynthesizeDefaultDestructor(const CXXDestructorDecl *Dtor, - CXXDtorType DtorType, - llvm::Function *Fn, - const FunctionArgList &Args) { - assert(!Dtor->getParent()->hasUserDeclaredDestructor() && - "SynthesizeDefaultDestructor - destructor has user declaration"); - - StartFunction(GlobalDecl(Dtor, DtorType), Dtor->getResultType(), Fn, Args, - SourceLocation()); - InitializeVtablePtrs(Dtor->getParent()); - EmitDtorEpilogue(Dtor, DtorType); - FinishFunction(); -} - /// EmitCXXAggrConstructorCall - This routine essentially creates a (nested) /// for-loop to call the default constructor on individual members of the /// array. diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index d803a05aa95e..ddf4e6431d02 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -241,6 +241,53 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, } } +void CodeGenFunction::GenerateBody(GlobalDecl GD, llvm::Function *Fn, + FunctionArgList &Args) { + const FunctionDecl *FD = cast(GD.getDecl()); + + Stmt *Body = FD->getBody(); + assert((Body || FD->isImplicit()) && "non-implicit function def has no body"); + + // Emit special ctor/dtor prologues. + llvm::BasicBlock *DtorEpilogue = 0; + if (const CXXConstructorDecl *CD = dyn_cast(FD)) { + EmitCtorPrologue(CD, GD.getCtorType()); + } else if (const CXXDestructorDecl *DD = dyn_cast(FD)) { + DtorEpilogue = createBasicBlock("dtor.epilogue"); + PushCleanupBlock(DtorEpilogue); + + InitializeVtablePtrs(DD->getParent()); + } + + // Emit the body of the function. + if (!Body) + SynthesizeImplicitFunctionBody(GD, Fn, Args); + else { + if (isa(Body)) + OuterTryBlock = cast(Body); + + EmitStmt(Body); + } + + // Emit special ctor/ctor epilogues. + if (isa(FD)) { + // If any of the member initializers are temporaries bound to references + // make sure to emit their destructors. + EmitCleanupBlocks(0); + } else if (const CXXDestructorDecl *DD = dyn_cast(FD)) { + CleanupBlockInfo Info = PopCleanupBlock(); + assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!"); + + EmitBlock(DtorEpilogue); + EmitDtorEpilogue(DD, GD.getDtorType()); + + if (Info.SwitchBlock) + EmitBlock(Info.SwitchBlock); + if (Info.EndBlock) + EmitBlock(Info.EndBlock); + } +} + void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) { const FunctionDecl *FD = cast(GD.getDecl()); @@ -284,80 +331,17 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) { FProto->getArgType(i))); } - if (const CompoundStmt *S = FD->getCompoundBody()) { - StartFunction(GD, FD->getResultType(), Fn, Args, S->getLBracLoc()); + SourceRange BodyRange; + if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange(); - if (const CXXConstructorDecl *CD = dyn_cast(FD)) { - EmitCtorPrologue(CD, GD.getCtorType()); - EmitStmt(S); - - // If any of the member initializers are temporaries bound to references - // make sure to emit their destructors. - EmitCleanupBlocks(0); - - } else if (const CXXDestructorDecl *DD = dyn_cast(FD)) { - llvm::BasicBlock *DtorEpilogue = createBasicBlock("dtor.epilogue"); - PushCleanupBlock(DtorEpilogue); + // Emit the standard function prologue. + StartFunction(GD, FD->getResultType(), Fn, Args, BodyRange.getBegin()); - InitializeVtablePtrs(DD->getParent()); + // Generate the body of the function. + GenerateBody(GD, Fn, Args); - EmitStmt(S); - - CleanupBlockInfo Info = PopCleanupBlock(); - - assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!"); - EmitBlock(DtorEpilogue); - EmitDtorEpilogue(DD, GD.getDtorType()); - - if (Info.SwitchBlock) - EmitBlock(Info.SwitchBlock); - if (Info.EndBlock) - EmitBlock(Info.EndBlock); - } else { - // Just a regular function, emit its body. - EmitStmt(S); - } - - FinishFunction(S->getRBracLoc()); - } else if (FD->isImplicit()) { - const CXXRecordDecl *ClassDecl = - cast(FD->getDeclContext()); - (void) ClassDecl; - if (const CXXConstructorDecl *CD = dyn_cast(FD)) { - // FIXME: For C++0x, we want to look for implicit *definitions* of - // these special member functions, rather than implicit *declarations*. - if (CD->isCopyConstructor()) { - assert(!ClassDecl->hasUserDeclaredCopyConstructor() && - "Cannot synthesize a non-implicit copy constructor"); - SynthesizeCXXCopyConstructor(CD, GD.getCtorType(), Fn, Args); - } else if (CD->isDefaultConstructor()) { - assert(!ClassDecl->hasUserDeclaredConstructor() && - "Cannot synthesize a non-implicit default constructor."); - SynthesizeDefaultConstructor(CD, GD.getCtorType(), Fn, Args); - } else { - assert(false && "Implicit constructor cannot be synthesized"); - } - } else if (const CXXDestructorDecl *CD = dyn_cast(FD)) { - assert(!ClassDecl->hasUserDeclaredDestructor() && - "Cannot synthesize a non-implicit destructor"); - SynthesizeDefaultDestructor(CD, GD.getDtorType(), Fn, Args); - } else if (const CXXMethodDecl *MD = dyn_cast(FD)) { - assert(MD->isCopyAssignment() && - !ClassDecl->hasUserDeclaredCopyAssignment() && - "Cannot synthesize a method that is not an implicit-defined " - "copy constructor"); - SynthesizeCXXCopyAssignment(MD, Fn, Args); - } else { - assert(false && "Cannot synthesize unknown implicit function"); - } - } else if (const Stmt *S = FD->getBody()) { - if (const CXXTryStmt *TS = dyn_cast(S)) { - OuterTryBlock = TS; - StartFunction(GD, FD->getResultType(), Fn, Args, TS->getTryLoc()); - EmitStmt(TS); - FinishFunction(TS->getEndLoc()); - } - } + // Emit the standard function epilogue. + FinishFunction(BodyRange.getEnd()); // Destroy the 'this' declaration. if (CXXThisDecl) diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index a694b894df61..29c75fdb8e03 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -494,6 +494,8 @@ public: const FunctionArgList &Args, SourceLocation StartLoc); + void GenerateBody(GlobalDecl GD, llvm::Function *Fn, FunctionArgList &Args); + /// EmitReturnBlock - Emit the unified return block, trying to avoid its /// emission when possible. void EmitReturnBlock(); @@ -536,15 +538,9 @@ public: llvm::Function *Fn, const FunctionArgList &Args); - void SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor, - CXXCtorType Type, - llvm::Function *Fn, - const FunctionArgList &Args); - - void SynthesizeDefaultDestructor(const CXXDestructorDecl *Dtor, - CXXDtorType Type, - llvm::Function *Fn, - const FunctionArgList &Args); + void SynthesizeImplicitFunctionBody(GlobalDecl GD, + llvm::Function *Fn, + const FunctionArgList &Args); /// EmitDtorEpilogue - Emit all code that comes at the end of class's /// destructor. This is to call destructors on members and base classes in