diff options
Diffstat (limited to 'lib/CodeGen/CGClass.cpp')
-rw-r--r-- | lib/CodeGen/CGClass.cpp | 83 |
1 files changed, 49 insertions, 34 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 085cfd3168..a69a3f9566 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -340,7 +340,7 @@ static void EmitBaseInitializer(CodeGenFunction &CGF, if (CGF.Exceptions && !BaseClassDecl->hasTrivialDestructor()) { // FIXME: Is this OK for C++0x delegating constructors? - CodeGenFunction::EHCleanupBlock Cleanup(CGF); + CodeGenFunction::CleanupBlock Cleanup(CGF, CodeGenFunction::EHCleanup); CXXDestructorDecl *DD = BaseClassDecl->getDestructor(); CGF.EmitCXXDestructorCall(DD, Dtor_Base, isBaseVirtual, V); @@ -354,7 +354,7 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF, QualType T, unsigned Index) { if (Index == MemberInit->getNumArrayIndices()) { - CodeGenFunction::CleanupScope Cleanups(CGF); + CodeGenFunction::RunCleanupsScope Cleanups(CGF); llvm::Value *Dest = LHS.getAddress(); if (ArrayIndexVar) { @@ -410,7 +410,7 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF, llvm::BasicBlock *ContinueBlock = CGF.createBasicBlock("for.inc"); { - CodeGenFunction::CleanupScope Cleanups(CGF); + CodeGenFunction::RunCleanupsScope Cleanups(CGF); // Inside the loop body recurse to emit the inner loop or, eventually, the // constructor call. @@ -534,7 +534,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); if (!RD->hasTrivialDestructor()) { // FIXME: Is this OK for C++0x delegating constructors? - CodeGenFunction::EHCleanupBlock Cleanup(CGF); + CodeGenFunction::CleanupBlock Cleanup(CGF, CodeGenFunction::EHCleanup); llvm::Value *ThisPtr = CGF.LoadCXXThis(); LValue LHS = CGF.EmitLValueForField(ThisPtr, Field, 0); @@ -612,7 +612,7 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) { if (IsTryBody) TryInfo = EnterCXXTryStmt(*cast<CXXTryStmt>(Body)); - unsigned CleanupStackSize = CleanupEntries.size(); + EHScopeStack::stable_iterator CleanupDepth = EHStack.stable_begin(); // Emit the constructor prologue, i.e. the base and member // initializers. @@ -628,7 +628,7 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) { // initializers, which includes (along the exceptional path) the // destructors for those members and bases that were fully // constructed. - EmitCleanupBlocks(CleanupStackSize); + PopCleanupBlocks(CleanupDepth); if (IsTryBody) ExitCXXTryStmt(*cast<CXXTryStmt>(Body), TryInfo); @@ -648,9 +648,6 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, B != E; ++B) { CXXBaseOrMemberInitializer *Member = (*B); - assert(LiveTemporaries.empty() && - "Should not have any live temporaries at initializer start!"); - if (Member->isBaseInitializer()) EmitBaseInitializer(*this, ClassDecl, Member, CtorType); else @@ -659,12 +656,8 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, InitializeVTablePointers(ClassDecl); - for (unsigned I = 0, E = MemberInitializers.size(); I != E; ++I) { - assert(LiveTemporaries.empty() && - "Should not have any live temporaries at initializer start!"); - + for (unsigned I = 0, E = MemberInitializers.size(); I != E; ++I) EmitMemberInitializer(*this, ClassDecl, MemberInitializers[I], CD, Args); - } } /// EmitDestructorBody - Emits the body of the current destructor. @@ -684,8 +677,28 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { if (isTryBody) TryInfo = EnterCXXTryStmt(*cast<CXXTryStmt>(Body)); - llvm::BasicBlock *DtorEpilogue = createBasicBlock("dtor.epilogue"); - PushCleanupBlock(DtorEpilogue); + // Emit the destructor epilogue now. If this is a complete + // destructor with a function-try-block, perform the base epilogue + // as well. + // + // FIXME: This isn't really right, because an exception in the + // non-EH epilogue should jump to the appropriate place in the + // EH epilogue. + { + CleanupBlock Cleanup(*this, NormalCleanup); + + if (isTryBody && DtorType == Dtor_Complete) + EmitDtorEpilogue(Dtor, Dtor_Base); + EmitDtorEpilogue(Dtor, DtorType); + + if (Exceptions) { + Cleanup.beginEHCleanup(); + + if (isTryBody && DtorType == Dtor_Complete) + EmitDtorEpilogue(Dtor, Dtor_Base); + EmitDtorEpilogue(Dtor, DtorType); + } + } bool SkipBody = false; // should get jump-threaded @@ -724,23 +737,8 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { // nothing to do besides what's in the epilogue } - // Jump to the cleanup block. - CleanupBlockInfo Info = PopCleanupBlock(); - assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!"); - EmitBlock(DtorEpilogue); - - // Emit the destructor epilogue now. If this is a complete - // destructor with a function-try-block, perform the base epilogue - // as well. - if (isTryBody && DtorType == Dtor_Complete) - EmitDtorEpilogue(Dtor, Dtor_Base); - EmitDtorEpilogue(Dtor, DtorType); - - // Link up the cleanup information. - if (Info.SwitchBlock) - EmitBlock(Info.SwitchBlock); - if (Info.EndBlock) - EmitBlock(Info.EndBlock); + // We're done with the epilogue cleanup. + PopCleanupBlock(); // Exit the try if applicable. if (isTryBody) @@ -939,7 +937,7 @@ CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, // Keep track of the current number of live temporaries. { - CXXTemporariesCleanupScope Scope(*this); + RunCleanupsScope Scope(*this); EmitCXXConstructorCall(D, Ctor_Complete, /*ForVirtualBase=*/false, Address, ArgBeg, ArgEnd); @@ -1114,6 +1112,23 @@ void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, EmitCXXMemberCall(DD, Callee, ReturnValueSlot(), This, VTT, 0, 0); } +void CodeGenFunction::PushDestructorCleanup(QualType T, llvm::Value *Addr) { + CXXRecordDecl *ClassDecl = T->getAsCXXRecordDecl(); + if (!ClassDecl) return; + if (ClassDecl->hasTrivialDestructor()) return; + + const CXXDestructorDecl *D = ClassDecl->getDestructor(); + + CleanupBlock Scope(*this, NormalCleanup); + + EmitCXXDestructorCall(D, Dtor_Complete, /*ForVirtualBase=*/false, Addr); + + if (Exceptions) { + Scope.beginEHCleanup(); + EmitCXXDestructorCall(D, Dtor_Complete, /*ForVirtualBase=*/false, Addr); + } +} + llvm::Value * CodeGenFunction::GetVirtualBaseClassOffset(llvm::Value *This, const CXXRecordDecl *ClassDecl, |