diff options
| -rw-r--r-- | clang/lib/CodeGen/CGException.cpp | 11 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/noexcept.cpp | 49 |
2 files changed, 58 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 4b09e973448..b01fdd4b264 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -1619,8 +1619,15 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() { // end of the function by FinishFunction. TerminateHandler = createBasicBlock("terminate.handler"); Builder.SetInsertPoint(TerminateHandler); - llvm::CallInst *TerminateCall = EmitNounwindRuntimeCall(getTerminateFn(CGM)); - TerminateCall->setDoesNotReturn(); + llvm::CallInst *terminateCall; + if (useClangCallTerminate(CGM)) { + // Load the exception pointer. + llvm::Value *exn = getExceptionFromSlot(); + terminateCall = EmitNounwindRuntimeCall(getClangCallTerminateFn(CGM), exn); + } else { + terminateCall = EmitNounwindRuntimeCall(getTerminateFn(CGM)); + } + terminateCall->setDoesNotReturn(); Builder.CreateUnreachable(); // Restore the saved insertion state. diff --git a/clang/test/CodeGenCXX/noexcept.cpp b/clang/test/CodeGenCXX/noexcept.cpp new file mode 100644 index 00000000000..4ee149ed8dd --- /dev/null +++ b/clang/test/CodeGenCXX/noexcept.cpp @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions -std=c++11 | FileCheck %s + +// rdar://11904428 +// Ensure that we call __cxa_begin_catch before calling +// std::terminate in a noexcept function. +namespace test0 { + void foo(); + + struct A { + A(); + ~A(); + }; + + void test() noexcept { + A a; + foo(); + } +} +// CHECK: define void @_ZN5test04testEv() +// CHECK: [[EXN:%.*]] = alloca i8* +// This goes to the terminate lpad. +// CHECK: invoke void @_ZN5test01AC1Ev( +// This goes to the cleanup-and-then-terminate lpad. +// CHECK: invoke void @_ZN5test03fooEv() +// Destructors don't throw by default in C++11. +// CHECK: call void @_ZN5test01AD1Ev( +// Cleanup lpad. +// CHECK: [[T0:%.*]] = landingpad +// CHECK-NEXT: catch i8* null +// CHECK-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0 +// CHECK-NEXT: store i8* [[T1]], i8** [[EXN]] +// (Calling this destructor is not technically required.) +// CHECK: call void @_ZN5test01AD1Ev( +// CHECK-NEXT: br label +// The terminate landing pad jumps in here for some reason. +// CHECK: [[T0:%.*]] = landingpad +// CHECK-NEXT: catch i8* null +// CHECK-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0 +// CHECK-NEXT: call void @__clang_call_terminate(i8* [[T1]]) +// CHECK-NEXT: unreachable +// The terminate handler chained to by the cleanup lpad. +// CHECK: [[T0:%.*]] = load i8** [[EXN]] +// CHECK-NEXT: call void @__clang_call_terminate(i8* [[T0]]) +// CHECK-NEXT: unreachable + +// CHECK: define linkonce_odr hidden void @__clang_call_terminate( +// CHECK: call i8* @__cxa_begin_catch( +// CHECK-NEXT: call void @_ZSt9terminatev() +// CHECK-NEXT: unreachable |

