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.

llvm-svn: 115668
This commit is contained in:
John McCall 2010-10-05 20:48:15 +00:00
parent 44e5c1f16c
commit e5dd32da11
2 changed files with 43 additions and 9 deletions

View File

@ -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();

View File

@ -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 X> 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>();
}
}