1*67e74705SXin Li // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -O0 %s -emit-llvm -o - | FileCheck %s
2*67e74705SXin Li
3*67e74705SXin Li extern "C" int printf(const char *, ...);
4*67e74705SXin Li
5*67e74705SXin Li static int N;
6*67e74705SXin Li struct S {
SS7*67e74705SXin Li S()
8*67e74705SXin Li __attribute__((nothrow)) { printf("%d: S()\n", ++N); }
~SS9*67e74705SXin Li ~S() __attribute__((nothrow)) { printf("%d: ~S()\n", N--); }
10*67e74705SXin Li int n[17];
11*67e74705SXin Li };
12*67e74705SXin Li // CHECK: [[struct_S:%.+]] = type { [17 x i32] }
print(int n,int a,int b,int c,int d)13*67e74705SXin Li void print(int n, int a, int b, int c, int d) {
14*67e74705SXin Li printf("n=%d\n,sizeof(S)=%d\nsizeof(array_t[0][0])=%d\nsizeof(array_t[0])=%d\nsizeof(array_t)=%d\n",
15*67e74705SXin Li n, a, b, c, d);
16*67e74705SXin Li if (n == 2)
17*67e74705SXin Li throw(n);
18*67e74705SXin Li }
19*67e74705SXin Li
test(int n)20*67e74705SXin Li void test(int n) {
21*67e74705SXin Li // CHECK: define void {{.*test.*}}(i32 [[n:%.+]]) #
22*67e74705SXin Li // CHECK: [[n_addr:%.+]] = alloca
23*67e74705SXin Li // CHECK-NEXT: [[saved_stack:%.+]] = alloca
24*67e74705SXin Li // CHECK-NEXT: [[sizeof_S:%.+]] = alloca
25*67e74705SXin Li // CHECK-NEXT: [[sizeof_array_t_0_0:%.+]] = alloca
26*67e74705SXin Li // CHECK-NEXT: [[sizeof_array_t_0:%.+]] = alloca
27*67e74705SXin Li // CHECK-NEXT: [[sizeof_array_t:%.+]] = alloca
28*67e74705SXin Li // CHECK-NEXT: [[exn_slot:%.+]] = alloca i8*
29*67e74705SXin Li // CHECK-NEXT: [[ehselector_slot:%.+]] = alloca i32
30*67e74705SXin Li // CHECK-NEXT: store i32 [[n]], i32* [[n_addr]]
31*67e74705SXin Li // CHECK-NEXT: [[t0:%.+]] = load i32, i32* [[n_addr]]
32*67e74705SXin Li // CHECK-NEXT: [[t1:%.+]] = zext i32 [[t0]] to i64
33*67e74705SXin Li // CHECK-NEXT: [[t2:%.+]] = load i32, i32* [[n_addr]]
34*67e74705SXin Li // CHECK-NEXT: [[add:%.+]] = add nsw i32 [[t2]], 1
35*67e74705SXin Li // CHECK-NEXT: [[t3:%.+]] = zext i32 [[add]] to i64
36*67e74705SXin Li // CHECK-NEXT: [[t4:%.+]] = call i8* @llvm.stacksave()
37*67e74705SXin Li // CHECK-NEXT: store i8* [[t4]], i8** [[saved_stack]]
38*67e74705SXin Li // CHECK-NEXT: [[t5:%.+]] = mul nuw i64 [[t1]], [[t3]]
39*67e74705SXin Li // CHECK-NEXT: [[vla:%.+]] = alloca [[struct_S]], i64 [[t5]]
40*67e74705SXin Li // CHECK-NEXT: [[t6:%.+]] = mul nuw i64 [[t1]], [[t3]]
41*67e74705SXin Li // CHECK-NEXT: [[isempty:%.+]] = icmp eq i64 [[t6]], 0
42*67e74705SXin Li // CHECK-NEXT: br i1 [[isempty]], label %[[arrayctor_cont:.+]], label %[[new_ctorloop:.+]]
43*67e74705SXin Li
44*67e74705SXin Li S array_t[n][n + 1];
45*67e74705SXin Li
46*67e74705SXin Li // CHECK: [[new_ctorloop]]
47*67e74705SXin Li // CHECK-NEXT: [[arrayctor_end:%.+]] = getelementptr inbounds [[struct_S]], [[struct_S]]* [[vla]], i64 [[t6]]
48*67e74705SXin Li // CHECK-NEXT: br label %[[arrayctor_loop:.+]]
49*67e74705SXin Li
50*67e74705SXin Li // CHECK: [[arrayctor_loop]]
51*67e74705SXin Li // CHECK-NEXT: [[arrayctor_cur:%.+]] = phi [[struct_S]]* [ [[vla]], %[[new_ctorloop]] ], [ [[arrayctor_next:%.+]], %[[arrayctor_loop]] ]
52*67e74705SXin Li // CHECK-NEXT: call void [[ctor:@.+]]([[struct_S]]* [[arrayctor_cur]])
53*67e74705SXin Li // CHECK-NEXT: [[arrayctor_next]] = getelementptr inbounds [[struct_S]], [[struct_S]]* [[arrayctor_cur]], i64 1
54*67e74705SXin Li // CHECK-NEXT: [[arrayctor_done:%.+]] = icmp eq [[struct_S]]* [[arrayctor_next]], [[arrayctor_end]]
55*67e74705SXin Li // CHECK-NEXT: br i1 [[arrayctor_done]], label %[[arrayctor_cont]], label %[[arrayctor_loop]]
56*67e74705SXin Li
57*67e74705SXin Li int sizeof_S = sizeof(S);
58*67e74705SXin Li int sizeof_array_t_0_0 = sizeof(array_t[0][0]);
59*67e74705SXin Li int sizeof_array_t_0 = sizeof(array_t[0]);
60*67e74705SXin Li int sizeof_array_t = sizeof(array_t);
61*67e74705SXin Li print(n, sizeof_S, sizeof_array_t_0_0, sizeof_array_t_0, sizeof_array_t);
62*67e74705SXin Li
63*67e74705SXin Li // CHECK: [[arrayctor_cont]]
64*67e74705SXin Li // CHECK-NEXT: store i32 68, i32* [[sizeof_S]]
65*67e74705SXin Li // CHECK-NEXT: store i32 68, i32* [[sizeof_array_t_0_0]]
66*67e74705SXin Li // CHECK: [[t8:%.+]] = mul nuw i64 68, [[t3]]
67*67e74705SXin Li // CHECK-NEXT: [[conv:%.+]] = trunc i64 [[t8]] to i32
68*67e74705SXin Li // CHECK-NEXT: store i32 [[conv]], i32* [[sizeof_array_t_0]]
69*67e74705SXin Li // CHECK-NEXT: [[t9:%.+]] = mul nuw i64 [[t1]], [[t3]]
70*67e74705SXin Li // CHECK-NEXT: [[t10:%.+]] = mul nuw i64 68, [[t9]]
71*67e74705SXin Li // CHECK-NEXT: [[conv1:%.+]] = trunc i64 [[t10]] to i32
72*67e74705SXin Li // CHECK-NEXT: store i32 [[conv1]], i32* [[sizeof_array_t]]
73*67e74705SXin Li // CHECK-NEXT: [[t11:%.+]] = load i32, i32* [[n_addr:%.+]]
74*67e74705SXin Li // CHECK-NEXT: [[t12:%.+]] = load i32, i32* [[sizeof_S]]
75*67e74705SXin Li // CHECK-NEXT: [[t13:%.+]] = load i32, i32* [[sizeof_array_t_0_0]]
76*67e74705SXin Li // CHECK-NEXT: [[t14:%.+]] = load i32, i32* [[sizeof_array_t_0]]
77*67e74705SXin Li // CHECK-NEXT: [[t15:%.+]] = load i32, i32* [[sizeof_array_t]]
78*67e74705SXin Li // CHECK-NEXT: invoke void @{{.*print.*}}(i32 [[t11]], i32 [[t12]], i32 [[t13]], i32 [[t14]], i32 [[t15]])
79*67e74705SXin Li // CHECK-NEXT: to label %[[invoke_cont:.+]] unwind label %[[lpad:.+]]
80*67e74705SXin Li
81*67e74705SXin Li // CHECK: [[invoke_cont]]
82*67e74705SXin Li // CHECK-NEXT: [[t16:%.+]] = mul nuw i64 [[t1]], [[t3]]
83*67e74705SXin Li // CHECK-NEXT: [[t17:%.+]] = getelementptr inbounds [[struct_S]], [[struct_S]]* [[vla]], i64 [[t16]]
84*67e74705SXin Li // CHECK-NEXT: [[arraydestroy_isempty:%.+]] = icmp eq [[struct_S]]* [[vla]], [[t17]]
85*67e74705SXin Li // CHECK-NEXT: br i1 [[arraydestroy_isempty]], label %[[arraydestroy_done2:.+]], label %[[arraydestroy_body:.+]]
86*67e74705SXin Li
87*67e74705SXin Li // CHECK: [[arraydestroy_body]]
88*67e74705SXin Li // CHECK-NEXT: [[arraydestroy_elementPast:%.+]] = phi [[struct_S]]* [ [[t17]], %[[invoke_cont]] ], [ [[arraydestroy_element:%.+]], %[[arraydestroy_body]] ]
89*67e74705SXin Li // CHECK-NEXT: [[arraydestroy_element]] = getelementptr inbounds [[struct_S]], [[struct_S]]* [[arraydestroy_elementPast]]
90*67e74705SXin Li // CHECK-NEXT: call void @[[dtor:.+]]([[struct_S]]* [[arraydestroy_element]])
91*67e74705SXin Li // CHECK-NEXT: [[arraydestroy_done:%.+]] = icmp eq [[struct_S]]* [[arraydestroy_element]], [[vla]]
92*67e74705SXin Li // CHECK-NEXT: br i1 [[arraydestroy_done]], label %[[arraydestroy_done2]], label %[[arraydestroy_body]]
93*67e74705SXin Li
94*67e74705SXin Li // CHECK: [[arraydestroy_done2]]
95*67e74705SXin Li // CHECK-NEXT: [[t17:%.+]] = load i8*, i8** [[saved_stack]]
96*67e74705SXin Li // CHECK-NEXT: call void @llvm.stackrestore(i8* [[t17]])
97*67e74705SXin Li // CHECK: ret void
98*67e74705SXin Li
99*67e74705SXin Li // CHECK: [[lpad]]
100*67e74705SXin Li // CHECK-NEXT: [[t19:%.+]] = landingpad { i8*, i32 }
101*67e74705SXin Li // CHECK: [[t20:%.+]] = extractvalue { i8*, i32 } [[t19]], 0
102*67e74705SXin Li // CHECK-NEXT: store i8* [[t20]], i8** [[exn_slot]]
103*67e74705SXin Li // CHECK-NEXT: [[t21:%.+]] = extractvalue { i8*, i32 } [[t19]], 1
104*67e74705SXin Li // CHECK-NEXT: store i32 [[t21]], i32* [[ehselector_slot]]
105*67e74705SXin Li // CHECK-NEXT: [[t22:%.+]] = mul nuw i64 [[t1]], [[t3]]
106*67e74705SXin Li // CHECK-NEXT: [[t23:%.+]] = getelementptr inbounds [[struct_S]], [[struct_S]]* [[vla]], i64 [[t22]]
107*67e74705SXin Li // CHECK-NEXT: [[arraydestroy_isempty3:%.+]] = icmp eq [[struct_S]]* [[vla]], [[t23]]
108*67e74705SXin Li // CHECK-NEXT: br i1 [[arraydestroy_isempty3]], label %[[arraydestroy_done8:.+]], label %[[arraydestroy_body4:.+]]
109*67e74705SXin Li
110*67e74705SXin Li // CHECK: [[arraydestroy_body4]]
111*67e74705SXin Li // CHECK: [[arraydestroy_elementPast5:%.+]] = phi [[struct_S]]* [ [[t23]], %[[lpad]] ], [ [[arraydestroy_element6:.+]], %[[arraydestroy_body4]] ]
112*67e74705SXin Li // CHECK-NEXT: [[arraydestroy_element6]] = getelementptr inbounds [[struct_S]], [[struct_S]]* [[arraydestroy_elementPast5]], i64 -1
113*67e74705SXin Li // CHECK-NEXT: call void @[[dtor]]([[struct_S]]* [[arraydestroy_element6]])
114*67e74705SXin Li // CHECK-NEXT: [[arraydestroy_done7:%.+]] = icmp eq [[struct_S]]* [[arraydestroy_element6]], [[vla]]
115*67e74705SXin Li // CHECK-NEXT: br i1 [[arraydestroy_done7]], label %[[arraydestroy_done8]], label %[[arraydestroy_body4]]
116*67e74705SXin Li
117*67e74705SXin Li // CHECK: [[arraydestroy_done8]]
118*67e74705SXin Li // CHECK-NEXT: br label %[[eh_resume:.+]]
119*67e74705SXin Li
120*67e74705SXin Li // CHECK: [[eh_resume]]
121*67e74705SXin Li // CHECK-NEXT: [[exn:%.+]] = load i8*, i8** [[exn_slot]]
122*67e74705SXin Li // CHECK-NEXT: [[sel:%.+]] = load i32, i32* [[ehselector_slot]]
123*67e74705SXin Li // CHECK-NEXT: [[lpad_val:%.+]] = insertvalue { i8*, i32 } undef, i8* [[exn]], 0
124*67e74705SXin Li // CHECK-NEXT: [[lpad_val9:%.+]] = insertvalue { i8*, i32 } [[lpad_val]], i32 [[sel]], 1
125*67e74705SXin Li // CHECK-NEXT: resume { i8*, i32 } [[lpad_val9]]
126*67e74705SXin Li }
127*67e74705SXin Li
main()128*67e74705SXin Li int main() {
129*67e74705SXin Li try {
130*67e74705SXin Li test(2);
131*67e74705SXin Li } catch (int e) {
132*67e74705SXin Li printf("expeption %d\n", e);
133*67e74705SXin Li }
134*67e74705SXin Li try {
135*67e74705SXin Li test(3);
136*67e74705SXin Li } catch (int e) {
137*67e74705SXin Li printf("expeption %d", e);
138*67e74705SXin Li }
139*67e74705SXin Li }
140