aboutsummaryrefslogtreecommitdiff
path: root/test/CodeGenCXX/exceptions.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2013-02-01 05:11:40 +0000
committerJohn McCall <rjmccall@apple.com>2013-02-01 05:11:40 +0000
commit074cae0861a87bf96d8ea56d02e34839d9ccbd0a (patch)
treea75e3a668f4ebae4ffeaa83a0cc11606862df0f0 /test/CodeGenCXX/exceptions.cpp
parent10318845f40d50b9d0ce010b0ea8d93a7b5ab029 (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.cpp67
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.)
+}