1// RUN: %clang_cc1 %s -triple=thumbv7-apple-ios6.0 -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - -fexceptions | FileCheck %s
2
3// CHECK: @_ZZN5test74testEvE1x = internal global i32 0, align 4
4// CHECK: @_ZGVZN5test74testEvE1x = internal global i32 0
5// CHECK: @_ZZN5test84testEvE1x = internal global [[TEST8A:.*]] zeroinitializer, align 1
6// CHECK: @_ZGVZN5test84testEvE1x = internal global i32 0
7
8typedef typeof(sizeof(int)) size_t;
9
10class foo {
11public:
12    foo();
13    virtual ~foo();
14};
15
16class bar : public foo {
17public:
18	bar();
19};
20
21// The global dtor needs the right calling conv with -fno-use-cxa-atexit
22// rdar://7817590
23bar baz;
24
25// PR9593
26// Make sure atexit(3) is used for global dtors.
27
28// CHECK:      call [[BAR:%.*]]* @_ZN3barC1Ev(
29// CHECK-NEXT: call i32 @atexit(void ()* @__dtor_baz)
30
31// CHECK-NOT: @_GLOBAL__D_a()
32// CHECK-LABEL: define internal void @__dtor_baz()
33// CHECK: call [[BAR]]* @_ZN3barD1Ev([[BAR]]* @baz)
34
35// Destructors and constructors must return this.
36namespace test1 {
37  void foo();
38
39  struct A {
40    A(int i) { foo(); }
41    ~A() { foo(); }
42    void bar() { foo(); }
43  };
44
45  // CHECK-LABEL: define void @_ZN5test14testEv()
46  void test() {
47    // CHECK: [[AV:%.*]] = alloca [[A:%.*]], align 1
48    // CHECK: call [[A]]* @_ZN5test11AC1Ei([[A]]* [[AV]], i32 10)
49    // CHECK: invoke void @_ZN5test11A3barEv([[A]]* [[AV]])
50    // CHECK: call [[A]]* @_ZN5test11AD1Ev([[A]]* [[AV]])
51    // CHECK: ret void
52    A a = 10;
53    a.bar();
54  }
55
56  // CHECK: define linkonce_odr [[A]]* @_ZN5test11AC1Ei([[A]]* returned %this, i32 %i) unnamed_addr
57  // CHECK:   [[THIS:%.*]] = alloca [[A]]*, align 4
58  // CHECK:   store [[A]]* {{.*}}, [[A]]** [[THIS]]
59  // CHECK:   [[THIS1:%.*]] = load [[A]]** [[THIS]]
60  // CHECK:   {{%.*}} = call [[A]]* @_ZN5test11AC2Ei(
61  // CHECK:   ret [[A]]* [[THIS1]]
62
63  // CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]* returned %this) unnamed_addr
64  // CHECK:   [[THIS:%.*]] = alloca [[A]]*, align 4
65  // CHECK:   store [[A]]* {{.*}}, [[A]]** [[THIS]]
66  // CHECK:   [[THIS1:%.*]] = load [[A]]** [[THIS]]
67  // CHECK:   {{%.*}} = call [[A]]* @_ZN5test11AD2Ev(
68  // CHECK:   ret [[A]]* [[THIS1]]
69}
70
71// Awkward virtual cases.
72namespace test2 {
73  void foo();
74
75  struct A {
76    int x;
77
78    A(int);
79    virtual ~A() { foo(); }
80  };
81
82  struct B {
83    int y;
84    int z;
85
86    B(int);
87    virtual ~B() { foo(); }
88  };
89
90  struct C : A, virtual B {
91    int q;
92
93    C(int i) : A(i), B(i) { foo(); }
94    ~C() { foo(); }
95  };
96
97  void test() {
98    C c = 10;
99  }
100
101  // Tests at eof
102}
103
104namespace test3 {
105  struct A {
106    int x;
107    ~A();
108  };
109
110  void a() {
111    // CHECK-LABEL: define void @_ZN5test31aEv()
112    // CHECK: call noalias i8* @_Znam(i32 48)
113    // CHECK: store i32 4
114    // CHECK: store i32 10
115    A *x = new A[10];
116  }
117
118  void b(int n) {
119    // CHECK-LABEL: define void @_ZN5test31bEi(
120    // CHECK: [[N:%.*]] = load i32*
121    // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4)
122    // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
123    // CHECK: [[OR:%.*]] = or i1
124    // CHECK: [[SZ:%.*]] = select i1 [[OR]]
125    // CHECK: call noalias i8* @_Znam(i32 [[SZ]])
126    // CHECK: store i32 4
127    // CHECK: store i32 [[N]]
128    A *x = new A[n];
129  }
130
131  void c() {
132    // CHECK-LABEL: define void @_ZN5test31cEv()
133    // CHECK: call  noalias i8* @_Znam(i32 808)
134    // CHECK: store i32 4
135    // CHECK: store i32 200
136    A (*x)[20] = new A[10][20];
137  }
138
139  void d(int n) {
140    // CHECK-LABEL: define void @_ZN5test31dEi(
141    // CHECK: [[N:%.*]] = load i32*
142    // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 80)
143    // CHECK: [[NE:%.*]] = mul i32 [[N]], 20
144    // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
145    // CHECK: [[SZ:%.*]] = select
146    // CHECK: call noalias i8* @_Znam(i32 [[SZ]])
147    // CHECK: store i32 4
148    // CHECK: store i32 [[NE]]
149    A (*x)[20] = new A[n][20];
150  }
151
152  void e(A *x) {
153    // CHECK-LABEL: define void @_ZN5test31eEPNS_1AE(
154    // CHECK: icmp eq {{.*}}, null
155    // CHECK: getelementptr {{.*}}, i64 -8
156    // CHECK: getelementptr {{.*}}, i64 4
157    // CHECK: bitcast {{.*}} to i32*
158    // CHECK: load
159    // CHECK: invoke {{.*}} @_ZN5test31AD1Ev
160    // CHECK: call void @_ZdaPv
161    delete [] x;
162  }
163
164  void f(A (*x)[20]) {
165    // CHECK-LABEL: define void @_ZN5test31fEPA20_NS_1AE(
166    // CHECK: icmp eq {{.*}}, null
167    // CHECK: getelementptr {{.*}}, i64 -8
168    // CHECK: getelementptr {{.*}}, i64 4
169    // CHECK: bitcast {{.*}} to i32*
170    // CHECK: load
171    // CHECK: invoke {{.*}} @_ZN5test31AD1Ev
172    // CHECK: call void @_ZdaPv
173    delete [] x;
174  }
175}
176
177namespace test4 {
178  struct A {
179    int x;
180    void operator delete[](void *, size_t sz);
181  };
182
183  void a() {
184    // CHECK-LABEL: define void @_ZN5test41aEv()
185    // CHECK: call noalias i8* @_Znam(i32 48)
186    // CHECK: store i32 4
187    // CHECK: store i32 10
188    A *x = new A[10];
189  }
190
191  void b(int n) {
192    // CHECK-LABEL: define void @_ZN5test41bEi(
193    // CHECK: [[N:%.*]] = load i32*
194    // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4)
195    // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
196    // CHECK: [[SZ:%.*]] = select
197    // CHECK: call noalias i8* @_Znam(i32 [[SZ]])
198    // CHECK: store i32 4
199    // CHECK: store i32 [[N]]
200    A *x = new A[n];
201  }
202
203  void c() {
204    // CHECK-LABEL: define void @_ZN5test41cEv()
205    // CHECK: call  noalias i8* @_Znam(i32 808)
206    // CHECK: store i32 4
207    // CHECK: store i32 200
208    A (*x)[20] = new A[10][20];
209  }
210
211  void d(int n) {
212    // CHECK-LABEL: define void @_ZN5test41dEi(
213    // CHECK: [[N:%.*]] = load i32*
214    // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 80)
215    // CHECK: [[NE:%.*]] = mul i32 [[N]], 20
216    // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
217    // CHECK: [[SZ:%.*]] = select
218    // CHECK: call noalias i8* @_Znam(i32 [[SZ]])
219    // CHECK: store i32 4
220    // CHECK: store i32 [[NE]]
221    A (*x)[20] = new A[n][20];
222  }
223
224  void e(A *x) {
225    // CHECK-LABEL: define void @_ZN5test41eEPNS_1AE(
226    // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8
227    // CHECK: getelementptr inbounds {{.*}}, i64 4
228    // CHECK: bitcast
229    // CHECK: [[T0:%.*]] = load i32*
230    // CHECK: [[T1:%.*]] = mul i32 4, [[T0]]
231    // CHECK: [[T2:%.*]] = add i32 [[T1]], 8
232    // CHECK: call void @_ZN5test41AdaEPvm(i8* [[ALLOC]], i32 [[T2]])
233    delete [] x;
234  }
235
236  void f(A (*x)[20]) {
237    // CHECK-LABEL: define void @_ZN5test41fEPA20_NS_1AE(
238    // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8
239    // CHECK: getelementptr inbounds {{.*}}, i64 4
240    // CHECK: bitcast
241    // CHECK: [[T0:%.*]] = load i32*
242    // CHECK: [[T1:%.*]] = mul i32 4, [[T0]]
243    // CHECK: [[T2:%.*]] = add i32 [[T1]], 8
244    // CHECK: call void @_ZN5test41AdaEPvm(i8* [[ALLOC]], i32 [[T2]])
245    delete [] x;
246  }
247}
248
249// <rdar://problem/8386802>: don't crash
250namespace test5 {
251  struct A {
252    ~A();
253  };
254
255  // CHECK-LABEL: define void @_ZN5test54testEPNS_1AE
256  void test(A *a) {
257    // CHECK:      [[PTR:%.*]] = alloca [[A:%.*]]*, align 4
258    // CHECK-NEXT: store [[A]]* {{.*}}, [[A]]** [[PTR]], align 4
259    // CHECK-NEXT: [[TMP:%.*]] = load [[A]]** [[PTR]], align 4
260    // CHECK-NEXT: call [[A]]* @_ZN5test51AD1Ev([[A]]* [[TMP]])
261    // CHECK-NEXT: ret void
262    a->~A();
263  }
264}
265
266namespace test6 {
267  struct A {
268    virtual ~A();
269  };
270
271  // CHECK-LABEL: define void @_ZN5test64testEPNS_1AE
272  void test(A *a) {
273    // CHECK:      [[AVAR:%.*]] = alloca [[A:%.*]]*, align 4
274    // CHECK-NEXT: store [[A]]* {{.*}}, [[A]]** [[AVAR]], align 4
275    // CHECK-NEXT: [[V:%.*]] = load [[A]]** [[AVAR]], align 4
276    // CHECK-NEXT: [[ISNULL:%.*]] = icmp eq [[A]]* [[V]], null
277    // CHECK-NEXT: br i1 [[ISNULL]]
278    // CHECK:      [[T0:%.*]] = bitcast [[A]]* [[V]] to void ([[A]]*)***
279    // CHECK-NEXT: [[T1:%.*]] = load void ([[A]]*)*** [[T0]]
280    // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds void ([[A]]*)** [[T1]], i64 1
281    // CHECK-NEXT: [[T3:%.*]] = load void ([[A]]*)** [[T2]]
282    // CHECK-NEXT: call void [[T3]]([[A]]* [[V]])
283    // CHECK-NEXT: br label
284    // CHECK:      ret void
285    delete a;
286  }
287}
288
289namespace test7 {
290  int foo();
291
292  // Static and guard tested at top of file
293
294  // CHECK-LABEL: define void @_ZN5test74testEv()
295  void test() {
296    // CHECK:      [[T0:%.*]] = load atomic i8* bitcast (i32* @_ZGVZN5test74testEvE1x to i8*) acquire, align 1
297    // CHECK-NEXT: [[T1:%.*]] = and i8 [[T0]], 1
298    // CHECK-NEXT: [[T2:%.*]] = icmp eq i8 [[T1]], 0
299    // CHECK-NEXT: br i1 [[T2]]
300    //   -> fallthrough, end
301    // CHECK:      [[T3:%.*]] = call i32 @__cxa_guard_acquire(i32* @_ZGVZN5test74testEvE1x)
302    // CHECK-NEXT: [[T4:%.*]] = icmp ne i32 [[T3]], 0
303    // CHECK-NEXT: br i1 [[T4]]
304    //   -> fallthrough, end
305    // CHECK:      [[INIT:%.*]] = invoke i32 @_ZN5test73fooEv()
306    // CHECK:      store i32 [[INIT]], i32* @_ZZN5test74testEvE1x, align 4
307    // CHECK-NEXT: call void @__cxa_guard_release(i32* @_ZGVZN5test74testEvE1x)
308    // CHECK-NEXT: br label
309    //   -> end
310    // end:
311    // CHECK:      ret void
312    static int x = foo();
313
314    // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
315    // CHECK-NEXT:   cleanup
316    // CHECK:      call void @__cxa_guard_abort(i32* @_ZGVZN5test74testEvE1x)
317    // CHECK:      resume { i8*, i32 }
318  }
319}
320
321namespace test8 {
322  struct A {
323    A();
324    ~A();
325  };
326
327  // Static and guard tested at top of file
328
329  // CHECK-LABEL: define void @_ZN5test84testEv()
330  void test() {
331    // CHECK:      [[T0:%.*]] = load atomic i8* bitcast (i32* @_ZGVZN5test84testEvE1x to i8*) acquire, align 1
332    // CHECK-NEXT: [[T1:%.*]] = and i8 [[T0]], 1
333    // CHECK-NEXT: [[T2:%.*]] = icmp eq i8 [[T1]], 0
334    // CHECK-NEXT: br i1 [[T2]]
335    //   -> fallthrough, end
336    // CHECK:      [[T3:%.*]] = call i32 @__cxa_guard_acquire(i32* @_ZGVZN5test84testEvE1x)
337    // CHECK-NEXT: [[T4:%.*]] = icmp ne i32 [[T3]], 0
338    // CHECK-NEXT: br i1 [[T4]]
339    //   -> fallthrough, end
340    // CHECK:      [[INIT:%.*]] = invoke [[TEST8A]]* @_ZN5test81AC1Ev([[TEST8A]]* @_ZZN5test84testEvE1x)
341
342    // FIXME: Here we register a global destructor that
343    // unconditionally calls the destructor.  That's what we've always
344    // done for -fno-use-cxa-atexit here, but that's really not
345    // semantically correct at all.
346
347    // CHECK:      call void @__cxa_guard_release(i32* @_ZGVZN5test84testEvE1x)
348    // CHECK-NEXT: br label
349    //   -> end
350    // end:
351    // CHECK:      ret void
352    static A x;
353
354    // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
355    // CHECK-NEXT:   cleanup
356    // CHECK:      call void @__cxa_guard_abort(i32* @_ZGVZN5test84testEvE1x)
357    // CHECK:      resume { i8*, i32 }
358  }
359}
360
361//   rdar://12836470
362// Use a larger-than-mandated array cookie when allocating an
363// array whose type is overaligned.
364namespace test9 {
365  class __attribute__((aligned(16))) A {
366    float data[4];
367  public:
368    A();
369    ~A();
370  };
371
372  A *testNew(unsigned n) {
373    return new A[n];
374  }
375// CHECK:    define [[TEST9:%.*]]* @_ZN5test97testNewEj(i32
376// CHECK:      [[N_VAR:%.*]] = alloca i32, align 4
377// CHECK:      [[N:%.*]] = load i32* [[N_VAR]], align 4
378// CHECK-NEXT: [[T0:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[N]], i32 16)
379// CHECK-NEXT: [[O0:%.*]] = extractvalue { i32, i1 } [[T0]], 1
380// CHECK-NEXT: [[T1:%.*]] = extractvalue { i32, i1 } [[T0]], 0
381// CHECK-NEXT: [[T2:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[T1]], i32 16)
382// CHECK-NEXT: [[O1:%.*]] = extractvalue { i32, i1 } [[T2]], 1
383// CHECK-NEXT: [[OVERFLOW:%.*]] = or i1 [[O0]], [[O1]]
384// CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 0
385// CHECK-NEXT: [[T4:%.*]] = select i1 [[OVERFLOW]], i32 -1, i32 [[T3]]
386// CHECK-NEXT: [[ALLOC:%.*]] = call noalias i8* @_Znam(i32 [[T4]])
387// CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[ALLOC]] to i32*
388// CHECK-NEXT: store i32 16, i32* [[T0]]
389// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i32* [[T0]], i32 1
390// CHECK-NEXT: store i32 [[N]], i32* [[T1]]
391// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8* [[ALLOC]], i64 16
392// CHECK-NEXT: bitcast i8* [[T0]] to [[TEST9]]*
393//   Array allocation follows.
394
395  void testDelete(A *array) {
396    delete[] array;
397  }
398// CHECK-LABEL:    define void @_ZN5test910testDeleteEPNS_1AE(
399// CHECK:      [[BEGIN:%.*]] = load [[TEST9]]**
400// CHECK-NEXT: [[T0:%.*]] = icmp eq [[TEST9]]* [[BEGIN]], null
401// CHECK-NEXT: br i1 [[T0]],
402// CHECK:      [[T0:%.*]] = bitcast [[TEST9]]* [[BEGIN]] to i8*
403// CHECK-NEXT: [[ALLOC:%.*]] = getelementptr inbounds i8* [[T0]], i64 -16
404// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8* [[ALLOC]], i64 4
405// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to i32*
406// CHECK-NEXT: [[N:%.*]] = load i32* [[T1]]
407// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[TEST9]]* [[BEGIN]], i32 [[N]]
408// CHECK-NEXT: [[T0:%.*]] = icmp eq [[TEST9]]* [[BEGIN]], [[END]]
409// CHECK-NEXT: br i1 [[T0]],
410//   Array deallocation follows.
411}
412
413  // CHECK: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev(
414  // CHECK:   call [[C]]* @_ZN5test21CD1Ev(
415  // CHECK:   ret [[C]]* undef
416
417  // CHECK-LABEL: define linkonce_odr void @_ZTv0_n12_N5test21CD0Ev(
418  // CHECK:   call void @_ZN5test21CD0Ev(
419  // CHECK:   ret void
420