From: Daniel Dunbar Date: Wed, 1 Apr 2009 04:37:47 +0000 (+0000) Subject: Fix a subtle bug where the cleanup scope entries had a dangling block reference X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=aa5bd87f1fd5f9ca47924248817c89325759b30e;p=clang Fix a subtle bug where the cleanup scope entries had a dangling block reference - Crash when generating @synchronize for zero-cost exception - Thanks to Anders for helping track down the problem. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68186 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 91aa88569e..ff90210126 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -175,6 +175,24 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, return RV; } +void CodeGenFunction::SimplifyForwardingBlocks(llvm::BasicBlock *BB) { + llvm::BranchInst *BI = dyn_cast(BB->getTerminator()); + + // If there is a cleanup stack, then we it isn't worth trying to + // simplify this block (we would need to remove it from the scope map + // and cleanup entry). + if (!CleanupEntries.empty()) + return; + + // Can only simplify direct branches. + if (!BI || !BI->isUnconditional()) + return; + + BB->replaceAllUsesWith(BI->getSuccessor(0)); + BI->eraseFromParent(); + BB->eraseFromParent(); +} + void CodeGenFunction::EmitBlock(llvm::BasicBlock *BB, bool IsFinished) { // Fall out of the current block (if necessary). EmitBranch(BB); @@ -339,13 +357,10 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) { // Emit the exit block. EmitBlock(ExitBlock, true); - // If LoopHeader is a simple forwarding block then eliminate it. - if (!EmitBoolCondBranch - && &LoopHeader->front() == LoopHeader->getTerminator()) { - LoopHeader->replaceAllUsesWith(LoopBody); - LoopHeader->getTerminator()->eraseFromParent(); - LoopHeader->eraseFromParent(); - } + // The LoopHeader typically is just a branch if we skipped emitting + // a branch, try to erase it. + if (!EmitBoolCondBranch) + SimplifyForwardingBlocks(LoopHeader); } void CodeGenFunction::EmitDoStmt(const DoStmt &S) { @@ -387,14 +402,12 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S) { Builder.CreateCondBr(BoolCondVal, LoopBody, AfterDo); // Emit the exit block. - EmitBlock(AfterDo, true); + EmitBlock(AfterDo); - // If DoCond is a simple forwarding block then eliminate it. - if (!EmitBoolCondBranch && &DoCond->front() == DoCond->getTerminator()) { - DoCond->replaceAllUsesWith(AfterDo); - DoCond->getTerminator()->eraseFromParent(); - DoCond->eraseFromParent(); - } + // The DoCond block typically is just a branch if we skipped + // emitting a branch, try to erase it. + if (!EmitBoolCondBranch) + SimplifyForwardingBlocks(DoCond); } void CodeGenFunction::EmitForStmt(const ForStmt &S) { diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 9dbbb25b22..61b2665428 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -339,6 +339,11 @@ public: /// label maps to. llvm::BasicBlock *getBasicBlockForLabel(const LabelStmt *S); + /// SimplifyForwardingBlocks - If the given basic block is only a + /// branch to another basic block, simplify it. This assumes that no + /// other code could potentially reference the basic block. + void SimplifyForwardingBlocks(llvm::BasicBlock *BB); + /// EmitBlock - Emit the given block \arg BB and set it as the insert point, /// adding a fall-through branch from the current insert block if /// necessary. It is legal to call this function even if there is no current diff --git a/test/CodeGen/rdr-6732143-dangling-block-reference.m b/test/CodeGen/rdr-6732143-dangling-block-reference.m new file mode 100644 index 0000000000..2d1baa6220 --- /dev/null +++ b/test/CodeGen/rdr-6732143-dangling-block-reference.m @@ -0,0 +1,10 @@ +// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm %s -o - + +void f0(id x) { + @synchronized (x) { + do { ; } while(0); + @try { + } @finally { + } + } +}