diff options
Diffstat (limited to 'test/CodeGenCXX/exceptions.cpp')
-rw-r--r-- | test/CodeGenCXX/exceptions.cpp | 82 |
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 } |