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