summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX/exceptions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenCXX/exceptions.cpp')
-rw-r--r--test/CodeGenCXX/exceptions.cpp82
1 files changed, 79 insertions, 3 deletions
diff --git a/test/CodeGenCXX/exceptions.cpp b/test/CodeGenCXX/exceptions.cpp
index 723e8d1..f6f5079 100644
--- a/test/CodeGenCXX/exceptions.cpp
+++ b/test/CodeGenCXX/exceptions.cpp
@@ -69,6 +69,13 @@ namespace test1 {
return new A(B().x);
}
+ // rdar://11904428
+ // Terminate landing pads should call __cxa_begin_catch first.
+ // CHECK: define linkonce_odr hidden void @__clang_call_terminate(i8*) [[NI_NR_NUW:#[0-9]+]]
+ // CHECK-NEXT: [[T0:%.*]] = call i8* @__cxa_begin_catch(i8* %0) [[NUW:#[0-9]+]]
+ // CHECK-NEXT: call void @_ZSt9terminatev() [[NR_NUW:#[0-9]+]]
+ // CHECK-NEXT: unreachable
+
A *d() {
// CHECK: define [[A:%.*]]* @_ZN5test11dEv()
// CHECK: [[ACTIVE:%.*]] = alloca i1
@@ -157,7 +164,7 @@ namespace test2 {
// CHECK-NEXT: invoke void @_ZN5test21AC1Ei([[A]]* [[CAST]], i32 5)
// CHECK: ret [[A]]* [[CAST]]
// CHECK: invoke void @_ZN5test21AdlEPvm(i8* [[NEW]], i64 8)
- // CHECK: call void @_ZSt9terminatev()
+ // CHECK: call void @__clang_call_terminate(i8* {{%.*}}) [[NR_NUW]]
return new A(5);
}
}
@@ -183,7 +190,7 @@ namespace test3 {
// CHECK-NEXT: invoke void @_ZN5test31AC1Ei([[A]]* [[CAST]], i32 5)
// CHECK: ret [[A]]* [[CAST]]
// CHECK: invoke void @_ZN5test31AdlEPvS1_d(i8* [[NEW]], i8* [[FOO]], double [[BAR]])
- // CHECK: call void @_ZSt9terminatev()
+ // CHECK: call void @__clang_call_terminate(i8* {{%.*}}) [[NR_NUW]]
return new(foo(),bar()) A(5);
}
@@ -274,7 +281,7 @@ namespace test5 {
// CHECK-NEXT: invoke void @_ZN5test51TC1Ev([[T_T]]* [[T]])
// CHECK: invoke void @_ZN5test51AC1ERKS0_RKNS_1TE([[A_T]]* [[A]], [[A_T]]* [[SRC]], [[T_T]]* [[T]])
// CHECK: invoke void @_ZN5test51TD1Ev([[T_T]]* [[T]])
- // CHECK: call i8* @__cxa_begin_catch(i8* [[EXN]]) nounwind
+ // CHECK: call i8* @__cxa_begin_catch(i8* [[EXN]]) [[NUW]]
// CHECK-NEXT: invoke void @_ZN5test51AD1Ev([[A_T]]* [[A]])
// CHECK: call void @__cxa_end_catch()
void test() {
@@ -451,3 +458,72 @@ namespace test10 {
// CHECK: invoke void @__cxa_rethrow()
// CHECK: unreachable
}
+
+// Ensure that an exception in a constructor destroys
+// already-constructed array members. PR14514
+namespace test11 {
+ struct A {
+ A();
+ ~A() {}
+ };
+
+ struct C {
+ A single;
+ A array[2][3];
+
+ C();
+ };
+
+ C::C() {
+ throw 0;
+ }
+ // CHECK: define void @_ZN6test111CC2Ev(
+ // CHECK: [[THIS:%.*]] = load [[C:%.*]]** {{%.*}}
+ // Construct single.
+ // CHECK-NEXT: [[SINGLE:%.*]] = getelementptr inbounds [[C]]* [[THIS]], i32 0, i32 0
+ // CHECK-NEXT: call void @_ZN6test111AC1Ev([[A:%.*]]* [[SINGLE]])
+ // Construct array.
+ // CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[C]]* [[THIS]], i32 0, i32 1
+ // CHECK-NEXT: [[ARRAYBEGIN:%.*]] = getelementptr inbounds [2 x [3 x [[A]]]]* [[ARRAY]], i32 0, i32 0, i32 0
+ // CHECK-NEXT: [[ARRAYEND:%.*]] = getelementptr inbounds [[A]]* [[ARRAYBEGIN]], i64 6
+ // CHECK-NEXT: br label
+ // CHECK: [[CUR:%.*]] = phi [[A]]* [ [[ARRAYBEGIN]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ]
+ // CHECK-NEXT: invoke void @_ZN6test111AC1Ev([[A:%.*]]* [[CUR]])
+ // CHECK: [[NEXT]] = getelementptr inbounds [[A]]* [[CUR]], i64 1
+ // CHECK-NEXT: [[DONE:%.*]] = icmp eq [[A]]* [[NEXT]], [[ARRAYEND]]
+ // CHECK-NEXT: br i1 [[DONE]],
+ // throw 0;
+ // CHECK: invoke void @__cxa_throw(
+ // Landing pad 1, from constructor in array-initialization loop:
+ // CHECK: landingpad
+ // - First, destroy already-constructed bits of array.
+ // CHECK: [[EMPTY:%.*]] = icmp eq [[A]]* [[ARRAYBEGIN]], [[CUR]]
+ // CHECK-NEXT: br i1 [[EMPTY]]
+ // CHECK: [[AFTER:%.*]] = phi [[A]]* [ [[CUR]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ]
+ // CHECK-NEXT: [[ELT]] = getelementptr inbounds [[A]]* [[AFTER]], i64 -1
+ // CHECK-NEXT: invoke void @_ZN6test111AD1Ev([[A]]* [[ELT]])
+ // CHECK: [[DONE:%.*]] = icmp eq [[A]]* [[ELT]], [[ARRAYBEGIN]]
+ // CHECK-NEXT: br i1 [[DONE]],
+ // - Next, chain to cleanup for single.
+ // CHECK: br label
+ // Landing pad 2, from throw site.
+ // CHECK: landingpad
+ // - First, destroy all of array.
+ // CHECK: [[ARRAYBEGIN:%.*]] = getelementptr inbounds [2 x [3 x [[A]]]]* [[ARRAY]], i32 0, i32 0, i32 0
+ // CHECK-NEXT: [[ARRAYEND:%.*]] = getelementptr inbounds [[A]]* [[ARRAYBEGIN]], i64 6
+ // CHECK-NEXT: br label
+ // CHECK: [[AFTER:%.*]] = phi [[A]]* [ [[ARRAYEND]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ]
+ // CHECK-NEXT: [[ELT]] = getelementptr inbounds [[A]]* [[AFTER]], i64 -1
+ // CHECK-NEXT: invoke void @_ZN6test111AD1Ev([[A]]* [[ELT]])
+ // CHECK: [[DONE:%.*]] = icmp eq [[A]]* [[ELT]], [[ARRAYBEGIN]]
+ // CHECK-NEXT: br i1 [[DONE]],
+ // - Next, chain to cleanup for single.
+ // CHECK: br label
+ // Finally, the cleanup for single.
+ // CHECK: invoke void @_ZN6test111AD1Ev([[A]]* [[SINGLE]])
+ // CHECK: br label
+ // CHECK: resume
+ // (After this is a terminate landingpad.)
+}
+
+// CHECK: attributes [[NI_NR_NUW]] = { noinline noreturn nounwind }
OpenPOWER on IntegriCloud