Fix crash on finally blocks that don't fall through

llvm-svn: 228243
This commit is contained in:
Reid Kleckner 2015-02-05 00:58:46 +00:00
parent 9c26d80c18
commit 16f9a6b43d
2 changed files with 52 additions and 1 deletions

View File

@ -1902,12 +1902,20 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo &FI) {
// Just pop the cleanup if it's a __finally block.
if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) {
PopCleanupBlock();
assert(FI.ContBB && "did not emit normal cleanup");
// Emit the code into FinallyBB.
Builder.SetInsertPoint(FI.FinallyBB);
EmitStmt(Finally->getBlock());
assert(FI.ContBB);
// If the finally block doesn't fall through, we don't need these blocks.
if (!HaveInsertPoint()) {
FI.ContBB->eraseFromParent();
if (FI.ResumeBB)
FI.ResumeBB->eraseFromParent();
return;
}
if (FI.ResumeBB) {
llvm::Value *IsEH = Builder.CreateLoad(getAbnormalTerminationSlot(),
"abnormal.termination");

View File

@ -1,5 +1,6 @@
// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fexceptions -fms-extensions -emit-llvm -o - | FileCheck %s
void abort(void) __attribute__((noreturn));
void might_crash(void);
void cleanup(void);
int check_condition(void);
@ -117,3 +118,45 @@ void use_abnormal_termination(void) {
//
// CHECK: [[ehresume]]
// CHECK: resume { i8*, i32 }
void noreturn_noop_finally() {
__try {
__noop();
} __finally {
abort();
}
}
// CHECK-LABEL: define void @noreturn_noop_finally()
// CHECK: store i8 0, i8* %
// CHECK: br label %[[finally:[^ ]*]]
// CHECK: [[finally]]
// CHECK: call void @abort()
// CHECK-NEXT: unreachable
// CHECK-NOT: load
void noreturn_finally() {
__try {
might_crash();
} __finally {
abort();
}
}
// CHECK-LABEL: define void @noreturn_finally()
// CHECK: invoke void @might_crash()
// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CHECK: [[cont]]
// CHECK: store i8 0, i8* %
// CHECK: br label %[[finally:[^ ]*]]
//
// CHECK: [[finally]]
// CHECK: call void @abort()
// CHECK-NEXT: unreachable
//
// CHECK: [[lpad]]
// CHECK: landingpad
// CHECK-NEXT: cleanup
// CHECK: store i8 1, i8* %
// CHECK: br label %[[finally]]