summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/CodeGen/CGException.cpp11
-rw-r--r--clang/test/CodeGenCXX/noexcept.cpp49
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
OpenPOWER on IntegriCloud