summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2013-06-20 21:37:43 +0000
committerJohn McCall <rjmccall@apple.com>2013-06-20 21:37:43 +0000
commitc84e4e9b1ce2e7dbb4d19ad4c1bfa4035c407685 (patch)
treea867b27bd586d577f925ad1178bbb8628ce23af8
parentc575a37ac94e6a2d6a32b902cb428631a94a2273 (diff)
downloadbcm5719-llvm-c84e4e9b1ce2e7dbb4d19ad4c1bfa4035c407685.tar.gz
bcm5719-llvm-c84e4e9b1ce2e7dbb4d19ad4c1bfa4035c407685.zip
Call __cxa_begin_catch before std::terminate() in a noexcept trap.
r174939-40 caused us to do this in the canonical terminate lpad, but when the EH stack has other cleanups on it we use the terminate handler block, which wasn't doing this. Fixes the rest of rdar://11904428 given appropriate stdlib support. llvm-svn: 184475
-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