diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index b1ceb4627712..2021ced31683 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -515,18 +515,22 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { const CXXDestructorDecl *D = ClassDecl->getDestructor(getContext()); assert(D && "EmitLocalBlockVarDecl - destructor is nul"); - CleanupScope scope(*this); if (const ConstantArrayType *Array = getContext().getAsConstantArrayType(Ty)) { + CleanupScope Scope(*this); QualType BaseElementTy = getContext().getBaseElementType(Array); const llvm::Type *BasePtr = ConvertType(BaseElementTy); BasePtr = llvm::PointerType::getUnqual(BasePtr); llvm::Value *BaseAddrPtr = Builder.CreateBitCast(DeclPtr, BasePtr); EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr); - } - else + + // Make sure to jump to the exit block. + EmitBranch(Scope.getCleanupExitBlock()); + } else { + CleanupScope Scope(*this); EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr); + } } } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 88beadf33140..4be341311ce4 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -665,8 +665,9 @@ llvm::Value* CodeGenFunction::EmitVAListRef(const Expr* E) { return EmitLValue(E).getAddress(); } -void CodeGenFunction::PushCleanupBlock(llvm::BasicBlock *CleanupBlock) { - CleanupEntries.push_back(CleanupEntry(CleanupBlock)); +void CodeGenFunction::PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock, + llvm::BasicBlock *CleanupExitBlock) { + CleanupEntries.push_back(CleanupEntry(CleanupEntryBlock, CleanupExitBlock)); } void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) { @@ -680,7 +681,7 @@ void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) { CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() { CleanupEntry &CE = CleanupEntries.back(); - llvm::BasicBlock *CleanupBlock = CE.CleanupBlock; + llvm::BasicBlock *CleanupEntryBlock = CE.CleanupEntryBlock; std::vector Blocks; std::swap(Blocks, CE.Blocks); @@ -711,10 +712,11 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() { } } - llvm::BasicBlock *SwitchBlock = 0; + llvm::BasicBlock *SwitchBlock = CE.CleanupExitBlock; llvm::BasicBlock *EndBlock = 0; if (!BranchFixups.empty()) { - SwitchBlock = createBasicBlock("cleanup.switch"); + if (!SwitchBlock) + SwitchBlock = createBasicBlock("cleanup.switch"); EndBlock = createBasicBlock("cleanup.end"); llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); @@ -745,7 +747,7 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() { llvm::BasicBlock *Dest = BI->getSuccessor(0); // Fixup the branch instruction to point to the cleanup block. - BI->setSuccessor(0, CleanupBlock); + BI->setSuccessor(0, CleanupEntryBlock); if (CleanupEntries.empty()) { llvm::ConstantInt *ID; @@ -802,7 +804,7 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() { BlockScopes.erase(Blocks[i]); } - return CleanupBlockInfo(CleanupBlock, SwitchBlock, EndBlock); + return CleanupBlockInfo(CleanupEntryBlock, SwitchBlock, EndBlock); } void CodeGenFunction::EmitCleanupBlock() { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 9bb219642ab4..fe8113e95332 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -108,11 +108,12 @@ public: /// PushCleanupBlock - Push a new cleanup entry on the stack and set the /// passed in block as the cleanup block. - void PushCleanupBlock(llvm::BasicBlock *CleanupBlock); + void PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock, + llvm::BasicBlock *CleanupExitBlock = 0); /// CleanupBlockInfo - A struct representing a popped cleanup block. struct CleanupBlockInfo { - /// CleanupBlock - the cleanup block + /// CleanupEntryBlock - the cleanup entry block llvm::BasicBlock *CleanupBlock; /// SwitchBlock - the block (if any) containing the switch instruction used @@ -138,17 +139,24 @@ public: class CleanupScope { CodeGenFunction& CGF; llvm::BasicBlock *CurBB; - llvm::BasicBlock *CleanupBB; - + llvm::BasicBlock *CleanupEntryBB; + llvm::BasicBlock *CleanupExitBB; + public: CleanupScope(CodeGenFunction &cgf) - : CGF(cgf), CurBB(CGF.Builder.GetInsertBlock()) { - CleanupBB = CGF.createBasicBlock("cleanup"); - CGF.Builder.SetInsertPoint(CleanupBB); + : CGF(cgf), CurBB(CGF.Builder.GetInsertBlock()), + CleanupEntryBB(CGF.createBasicBlock("cleanup")), CleanupExitBB(0) { + CGF.Builder.SetInsertPoint(CleanupEntryBB); } + llvm::BasicBlock *getCleanupExitBlock() { + if (!CleanupExitBB) + CleanupExitBB = CGF.createBasicBlock("cleanup.exit"); + return CleanupExitBB; + } + ~CleanupScope() { - CGF.PushCleanupBlock(CleanupBB); + CGF.PushCleanupBlock(CleanupEntryBB, CleanupExitBB); // FIXME: This is silly, move this into the builder. if (CurBB) CGF.Builder.SetInsertPoint(CurBB); @@ -250,9 +258,12 @@ private: bool DidCallStackSave; struct CleanupEntry { - /// CleanupBlock - The block of code that does the actual cleanup. - llvm::BasicBlock *CleanupBlock; + /// CleanupEntryBlock - The block of code that does the actual cleanup. + llvm::BasicBlock *CleanupEntryBlock; + /// CleanupExitBlock - The cleanup exit block. + llvm::BasicBlock *CleanupExitBlock; + /// Blocks - Basic blocks that were emitted in the current cleanup scope. std::vector Blocks; @@ -260,8 +271,10 @@ private: /// inserted into the current function yet. std::vector BranchFixups; - explicit CleanupEntry(llvm::BasicBlock *cb) - : CleanupBlock(cb) {} + explicit CleanupEntry(llvm::BasicBlock *CleanupEntryBlock, + llvm::BasicBlock *CleanupExitBlock) + : CleanupEntryBlock(CleanupEntryBlock), + CleanupExitBlock(CleanupExitBlock) {} }; /// CleanupEntries - Stack of cleanup entries. diff --git a/clang/test/CodeGenCXX/array-construction.cpp b/clang/test/CodeGenCXX/array-construction.cpp index b444221533d3..5b6bc2e5b511 100644 --- a/clang/test/CodeGenCXX/array-construction.cpp +++ b/clang/test/CodeGenCXX/array-construction.cpp @@ -17,12 +17,9 @@ public: int i; float f; -/** - NYI ~xpto() { printf("xpto::~xpto()\n"); } -*/ }; int main() {