diff options
author | John McCall <rjmccall@apple.com> | 2010-07-06 17:35:03 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-07-06 17:35:03 +0000 |
commit | 2d605ac1f511b433408362df5d7dba19d5eac6f1 (patch) | |
tree | c865f6138b75f24c092a991f9b917512a838d175 | |
parent | 4626285dba87fb675fbef7946b0f74b5ee4555f2 (diff) | |
download | bcm5719-llvm-2d605ac1f511b433408362df5d7dba19d5eac6f1.tar.gz bcm5719-llvm-2d605ac1f511b433408362df5d7dba19d5eac6f1.zip |
When destroying a cleanup, kill any references to instructions in the entry
block before deleting it. Fixes PR7575.
This really just a short-term fix before implementing lazy cleanups.
llvm-svn: 107676
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 6 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/destructors.cpp | 31 |
2 files changed, 37 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 306989f11e2..9375b77360c 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -688,6 +688,12 @@ static void DestroyCleanup(CodeGenFunction &CGF, llvm::BranchInst::Create(CGF.getUnreachableBlock(), Exit); assert(!Entry->getParent() && "cleanup entry already positioned?"); + // We can't just delete the entry; we have to kill any references to + // its instructions in other blocks. + for (llvm::BasicBlock::iterator I = Entry->begin(), E = Entry->end(); + I != E; ++I) + if (!I->use_empty()) + I->replaceAllUsesWith(llvm::UndefValue::get(I->getType())); delete Entry; } diff --git a/clang/test/CodeGenCXX/destructors.cpp b/clang/test/CodeGenCXX/destructors.cpp index ee8f1a5f543..965aea52ee3 100644 --- a/clang/test/CodeGenCXX/destructors.cpp +++ b/clang/test/CodeGenCXX/destructors.cpp @@ -228,6 +228,37 @@ namespace test4 { } } +// PR7575 +namespace test5 { + struct A { ~A(); }; + + // This is really unnecessarily verbose; we should be using phis, + // even at -O0. + + // CHECK: define void @_ZN5test53fooEv() + // CHECK: [[ELEMS:%.*]] = alloca [5 x [[A:%.*]]], align + // CHECK-NEXT: [[IVAR:%.*]] = alloca i64 + // CHECK: [[ELEMSARRAY:%.*]] = bitcast [5 x [[A]]]* [[ELEMS]] to [[A]] + // CHECK-NEXT: store i64 5, i64* [[IVAR]] + // CHECK-NEXT: br label + // CHECK: [[I:%.*]] = load i64* [[IVAR]] + // CHECK-NEXT: icmp ne i64 [[I]], 0 + // CHECK-NEXT: br i1 + // CHECK: [[I:%.*]] = load i64* [[IVAR]] + // CHECK-NEXT: [[I2:%.*]] = sub i64 [[I]], 1 + // CHECK-NEXT: getelementptr inbounds [[A]]* [[ELEMSARRAY]], i64 [[I2]] + // CHECK-NEXT: call void @_ZN5test51AD1Ev( + // CHECK-NEXT: br label + // CHECK: [[I:%.*]] = load i64* [[IVAR]] + // CHECK-NEXT: [[I1:%.*]] = sub i64 [[I]], 1 + // CHECK-NEXT: store i64 [[I1]], i64* [[IVAR]] + // CHECK-NEXT: br label + // CHECK: ret void + void foo() { + A elems[5]; + } +} + // Checks from test3: // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev( |