From e71d60d2c948bef21443c3370a9922a2f58bcc3a Mon Sep 17 00:00:00 2001 From: John McCall Date: Tue, 5 Oct 2010 20:48:15 +0000 Subject: [PATCH] Teach PopCleanupBlock to correctly handle the possibility of branching through a EH-only cleanup as part of a fallthrough branch-through. That this happens for this test case is actually a separate bug. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@115668 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenFunction.cpp | 23 ++++++++++++++--------- test/CodeGenCXX/goto.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 test/CodeGenCXX/goto.cpp diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 043195cecf..56dccc1c0a 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -846,26 +846,31 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { llvm::BasicBlock *FallthroughSource = Builder.GetInsertBlock(); bool HasFallthrough = (FallthroughSource != 0 && IsActive); - // As a kindof crazy internal case, branch-through fall-throughs - // leave the insertion point set to the end of the last cleanup. + // Branch-through fall-throughs leave the insertion point set to the + // end of the last cleanup, which points to the current scope. The + // rest of IR gen doesn't need to worry about this; it only happens + // during the execution of PopCleanupBlocks(). bool HasPrebranchedFallthrough = (FallthroughSource && FallthroughSource->getTerminator()); + // If this is a normal cleanup, then having a prebranched + // fallthrough implies that the fallthrough source unconditionally + // jumps here. + assert(!Scope.isNormalCleanup() || !HasPrebranchedFallthrough || + (Scope.getNormalBlock() && + FallthroughSource->getTerminator()->getSuccessor(0) + == Scope.getNormalBlock())); + bool RequiresNormalCleanup = false; if (Scope.isNormalCleanup() && (HasFixups || HasExistingBranches || HasFallthrough)) { RequiresNormalCleanup = true; } - assert(!HasPrebranchedFallthrough || RequiresNormalCleanup || !IsActive); - assert(!HasPrebranchedFallthrough || - (Scope.isNormalCleanup() && Scope.getNormalBlock() && - FallthroughSource->getTerminator()->getSuccessor(0) - == Scope.getNormalBlock())); - // Even if we don't need the normal cleanup, we might still have // prebranched fallthrough to worry about. - if (!RequiresNormalCleanup && HasPrebranchedFallthrough) { + if (Scope.isNormalCleanup() && !RequiresNormalCleanup && + HasPrebranchedFallthrough) { assert(!IsActive); llvm::BasicBlock *NormalEntry = Scope.getNormalBlock(); diff --git a/test/CodeGenCXX/goto.cpp b/test/CodeGenCXX/goto.cpp new file mode 100644 index 0000000000..7ebb72f54a --- /dev/null +++ b/test/CodeGenCXX/goto.cpp @@ -0,0 +1,29 @@ +// RUN: %clang-cc1 %s -fexceptions + +// Reduced from a crash on boost::interprocess's node_allocator_test.cpp. +namespace test0 { + struct A { A(); ~A(); }; + struct V { V(const A &a = A()); ~V(); }; + + template int vector_test() + { + A process_name; + try { + A segment; + + V *stdvector = new V(); + + int x = 5, y = 7; + if(x == y) return 1; + } + catch(int ex){ + return 1; + } + return 0; +} + +int main () +{ + return vector_test<0>(); +} +} -- 2.40.0