diff options
author | John McCall <rjmccall@apple.com> | 2013-02-01 05:11:40 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2013-02-01 05:11:40 +0000 |
commit | 074cae0861a87bf96d8ea56d02e34839d9ccbd0a (patch) | |
tree | a75e3a668f4ebae4ffeaa83a0cc11606862df0f0 /test/CodeGenCXX/exceptions.cpp | |
parent | 10318845f40d50b9d0ce010b0ea8d93a7b5ab029 (diff) |
Destroy arrays and ARC fields when throwing out of ctors.
Previously we were only handling non-array fields of class type.
Testcases derived from a patch by WenHan Gu.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174146 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenCXX/exceptions.cpp')
-rw-r--r-- | test/CodeGenCXX/exceptions.cpp | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/test/CodeGenCXX/exceptions.cpp b/test/CodeGenCXX/exceptions.cpp index 723e8d1393..06003c0cd6 100644 --- a/test/CodeGenCXX/exceptions.cpp +++ b/test/CodeGenCXX/exceptions.cpp @@ -451,3 +451,70 @@ 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.) +} |