1 | // RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -mconstructor-aliases -fcxx-exceptions -fexceptions -O1 -disable-llvm-passes -std=c++03 > %t |
2 | // RUN: FileCheck --check-prefix=CHECK1 --input-file=%t %s |
3 | // RUN: FileCheck --check-prefix=CHECK2 --input-file=%t %s |
4 | // RUN: FileCheck --check-prefix=CHECK3 --input-file=%t %s |
5 | // RUN: FileCheck --check-prefixes=CHECK4,CHECK4v03 --input-file=%t %s |
6 | // RUN: FileCheck --check-prefixes=CHECK5,CHECK5v03 --input-file=%t %s |
7 | // RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -mconstructor-aliases -fcxx-exceptions -fexceptions -O1 -disable-llvm-passes -std=c++11 > %t2 |
8 | // RUN: FileCheck --check-prefix=CHECK1 --input-file=%t2 %s |
9 | // RUN: FileCheck --check-prefix=CHECK2v11 --input-file=%t2 %s |
10 | // RUN: FileCheck --check-prefix=CHECK3 --input-file=%t2 %s |
11 | // RUN: FileCheck --check-prefixes=CHECK4,CHECK4v11 --input-file=%t2 %s |
12 | // RUN: FileCheck --check-prefixes=CHECK5,CHECK5v11 --input-file=%t2 %s |
13 | // RUN: FileCheck --check-prefix=CHECK6 --input-file=%t2 %s |
14 | // REQUIRES: asserts |
15 | |
16 | struct A { |
17 | int a; |
18 | |
19 | ~A(); |
20 | }; |
21 | |
22 | // Base with non-trivial destructor |
23 | struct B : A { |
24 | ~B(); |
25 | }; |
26 | |
27 | B::~B() { } |
28 | |
29 | // Field with non-trivial destructor |
30 | struct C { |
31 | A a; |
32 | |
33 | ~C(); |
34 | }; |
35 | |
36 | C::~C() { } |
37 | |
38 | namespace PR7526 { |
39 | extern void foo(); |
40 | struct allocator { |
41 | ~allocator() throw(); |
42 | }; |
43 | |
44 | struct allocator_derived : allocator { }; |
45 | |
46 | // CHECK1-LABEL: define void @_ZN6PR75263fooEv() |
47 | // CHECK1: call void {{.*}} @_ZN6PR75269allocatorD2Ev |
48 | |
49 | // CHECK1-LABEL: define void @_ZN6PR75269allocatorD2Ev(%"struct.PR7526::allocator"* %this) unnamed_addr |
50 | // CHECK1: call void @__cxa_call_unexpected |
51 | allocator::~allocator() throw() { foo(); } |
52 | |
53 | void foo() { |
54 | allocator_derived ad; |
55 | } |
56 | } |
57 | |
58 | // PR5084 |
59 | template<typename T> |
60 | class A1 { |
61 | ~A1(); |
62 | }; |
63 | |
64 | template<> A1<char>::~A1(); |
65 | |
66 | // PR5529 |
67 | namespace PR5529 { |
68 | struct A { |
69 | ~A(); |
70 | }; |
71 | |
72 | A::~A() { } |
73 | struct B : A { |
74 | virtual ~B(); |
75 | }; |
76 | |
77 | B::~B() {} |
78 | } |
79 | |
80 | // FIXME: there's a known problem in the codegen here where, if one |
81 | // destructor throws, the remaining destructors aren't run. Fix it, |
82 | // then make this code check for it. |
83 | namespace test0 { |
84 | void foo(); |
85 | struct VBase { ~VBase(); }; |
86 | struct Base { ~Base(); }; |
87 | struct Member { ~Member(); }; |
88 | |
89 | struct A : Base { |
90 | Member M; |
91 | ~A(); |
92 | }; |
93 | |
94 | // The function-try-block won't suppress -mconstructor-aliases here. |
95 | A::~A() try { } catch (int i) {} |
96 | |
97 | // complete destructor alias tested above |
98 | |
99 | // CHECK2-LABEL: @_ZN5test01AD1Ev = unnamed_addr alias {{.*}} @_ZN5test01AD2Ev |
100 | // CHECK2-LABEL: define void @_ZN5test01AD2Ev(%"struct.test0::A"* %this) unnamed_addr |
101 | // CHECK2: invoke void @_ZN5test06MemberD1Ev |
102 | // CHECK2: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] |
103 | // CHECK2: invoke void @_ZN5test04BaseD2Ev |
104 | // CHECK2: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] |
105 | |
106 | // In C++11, the destructors are often known not to throw. |
107 | // CHECK2v11-LABEL: @_ZN5test01AD1Ev = unnamed_addr alias {{.*}} @_ZN5test01AD2Ev |
108 | // CHECK2v11-LABEL: define void @_ZN5test01AD2Ev(%"struct.test0::A"* %this) unnamed_addr |
109 | // CHECK2v11: call void @_ZN5test06MemberD1Ev |
110 | // CHECK2v11: call void @_ZN5test04BaseD2Ev |
111 | |
112 | struct B : Base, virtual VBase { |
113 | Member M; |
114 | ~B(); |
115 | }; |
116 | B::~B() try { } catch (int i) {} |
117 | // It will suppress the delegation optimization here, though. |
118 | |
119 | // CHECK2-LABEL: define void @_ZN5test01BD2Ev(%"struct.test0::B"* %this, i8** %vtt) unnamed_addr |
120 | // CHECK2: invoke void @_ZN5test06MemberD1Ev |
121 | // CHECK2: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] |
122 | // CHECK2: invoke void @_ZN5test04BaseD2Ev |
123 | // CHECK2: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] |
124 | |
125 | // CHECK2v11-LABEL: define void @_ZN5test01BD2Ev(%"struct.test0::B"* %this, i8** %vtt) unnamed_addr |
126 | // CHECK2v11: call void @_ZN5test06MemberD1Ev |
127 | // CHECK2v11: call void @_ZN5test04BaseD2Ev |
128 | |
129 | // CHECK2-LABEL: define void @_ZN5test01BD1Ev(%"struct.test0::B"* %this) unnamed_addr |
130 | // CHECK2: invoke void @_ZN5test06MemberD1Ev |
131 | // CHECK2: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] |
132 | // CHECK2: invoke void @_ZN5test04BaseD2Ev |
133 | // CHECK2: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] |
134 | // CHECK2: invoke void @_ZN5test05VBaseD2Ev |
135 | // CHECK2: unwind label [[VBASE_UNWIND:%[a-zA-Z0-9.]+]] |
136 | |
137 | // CHECK2v11-LABEL: define void @_ZN5test01BD1Ev(%"struct.test0::B"* %this) unnamed_addr |
138 | // CHECK2v11: call void @_ZN5test06MemberD1Ev |
139 | // CHECK2v11: call void @_ZN5test04BaseD2Ev |
140 | // CHECK2v11: call void @_ZN5test05VBaseD2Ev |
141 | } |
142 | |
143 | // Test base-class aliasing. |
144 | namespace test1 { |
145 | struct A { ~A(); char ***m; }; // non-trivial destructor |
146 | struct B { ~B(); }; // non-trivial destructor |
147 | struct Empty { }; // trivial destructor, empty |
148 | struct NonEmpty { int x; }; // trivial destructor, non-empty |
149 | |
150 | // There must be a definition in this translation unit for the alias |
151 | // optimization to apply. |
152 | A::~A() { delete m; } |
153 | |
154 | struct M : A { ~M(); }; |
155 | M::~M() {} |
156 | // CHECK3: @_ZN5test11MD2Ev = unnamed_addr alias {{.*}} @_ZN5test11AD2Ev |
157 | |
158 | struct N : A, Empty { ~N(); }; |
159 | N::~N() {} |
160 | // CHECK3: @_ZN5test11ND2Ev = unnamed_addr alias {{.*}} @_ZN5test11AD2Ev |
161 | |
162 | struct O : Empty, A { ~O(); }; |
163 | O::~O() {} |
164 | // CHECK3: @_ZN5test11OD2Ev = unnamed_addr alias {{.*}} @_ZN5test11AD2Ev |
165 | |
166 | struct P : NonEmpty, A { ~P(); }; |
167 | P::~P() {} // CHECK3-LABEL: define void @_ZN5test11PD2Ev(%"struct.test1::P"* %this) unnamed_addr |
168 | |
169 | struct Q : A, B { ~Q(); }; |
170 | Q::~Q() {} // CHECK3-LABEL: define void @_ZN5test11QD2Ev(%"struct.test1::Q"* %this) unnamed_addr |
171 | |
172 | struct R : A { ~R(); }; |
173 | R::~R() { A a; } // CHECK3-LABEL: define void @_ZN5test11RD2Ev(%"struct.test1::R"* %this) unnamed_addr |
174 | |
175 | struct S : A { ~S(); int x; }; |
176 | S::~S() {} |
177 | // CHECK4: @_ZN5test11SD2Ev = unnamed_addr alias {{.*}}, bitcast {{.*}} @_ZN5test11AD2Ev |
178 | |
179 | struct T : A { ~T(); B x; }; |
180 | T::~T() {} // CHECK4-LABEL: define void @_ZN5test11TD2Ev(%"struct.test1::T"* %this) unnamed_addr |
181 | |
182 | // The VTT parameter prevents this. We could still make this work |
183 | // for calling conventions that are safe against extra parameters. |
184 | struct U : A, virtual B { ~U(); }; |
185 | U::~U() {} // CHECK4-LABEL: define void @_ZN5test11UD2Ev(%"struct.test1::U"* %this, i8** %vtt) unnamed_addr |
186 | } |
187 | |
188 | // PR6471 |
189 | namespace test2 { |
190 | struct A { ~A(); char ***m; }; |
191 | struct B : A { ~B(); }; |
192 | |
193 | B::~B() {} |
194 | // CHECK4-LABEL: define void @_ZN5test21BD2Ev(%"struct.test2::B"* %this) unnamed_addr |
195 | // CHECK4: call void @_ZN5test21AD2Ev |
196 | } |
197 | |
198 | // PR7142 |
199 | namespace test3 { |
200 | struct A { virtual ~A(); }; |
201 | struct B { virtual ~B(); }; |
202 | namespace { // internal linkage => deferred |
203 | struct C : A, B {}; // ~B() in D requires a this-adjustment thunk |
204 | struct D : C {}; // D::~D() is an alias to C::~C() |
205 | } |
206 | |
207 | void test() { |
208 | new D; // Force emission of D's vtable |
209 | } |
210 | |
211 | // CHECK4-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(%"struct.test3::(anonymous namespace)::C"* %this) unnamed_addr |
212 | // CHECK4v03: invoke void @_ZN5test31BD2Ev( |
213 | // CHECK4v11: call void @_ZN5test31BD2Ev( |
214 | // CHECK4: call void @_ZN5test31AD2Ev( |
215 | // CHECK4: ret void |
216 | |
217 | // CHECK4-LABEL: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::(anonymous namespace)::D"* %this) unnamed_addr |
218 | // CHECK4v03-SAME: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) |
219 | // CHECK4v03: invoke void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev |
220 | // CHECK4v11: call void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev |
221 | // CHECK4: call void @_ZdlPv({{.*}}) [[NUW:#[0-9]+]] |
222 | // CHECK4: ret void |
223 | // CHECK4v03: landingpad { i8*, i32 } |
224 | // CHECK4v03-NEXT: cleanup |
225 | // CHECK4v03: call void @_ZdlPv({{.*}}) [[NUW]] |
226 | // CHECK4v03: resume { i8*, i32 } |
227 | // CHECK4v11-NOT: landingpad |
228 | |
229 | // CHECK4-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD1Ev( |
230 | // CHECK4: getelementptr inbounds i8, i8* {{.*}}, i64 -8 |
231 | // CHECK4: call void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev |
232 | // CHECK4: ret void |
233 | |
234 | // CHECK4-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD0Ev( |
235 | // CHECK4: getelementptr inbounds i8, i8* {{.*}}, i64 -8 |
236 | // CHECK4: call void @_ZN5test312_GLOBAL__N_11DD0Ev( |
237 | // CHECK4: ret void |
238 | |
239 | // CHECK4-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev(%"struct.test3::(anonymous namespace)::C"* %this) unnamed_addr |
240 | // CHECK4v03-SAME: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) |
241 | // CHECK4v03: invoke void @_ZN5test312_GLOBAL__N_11CD2Ev( |
242 | // CHECK4v11: call void @_ZN5test312_GLOBAL__N_11CD2Ev( |
243 | // CHECK4: call void @_ZdlPv({{.*}}) [[NUW]] |
244 | // CHECK4: ret void |
245 | // CHECK4v03: landingpad { i8*, i32 } |
246 | // CHECK4v03-NEXT: cleanup |
247 | // CHECK4v03: call void @_ZdlPv({{.*}}) [[NUW]] |
248 | // CHECK4v03: resume { i8*, i32 } |
249 | |
250 | // CHECK4-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev( |
251 | // CHECK4: getelementptr inbounds i8, i8* {{.*}}, i64 -8 |
252 | // CHECK4: call void @_ZN5test312_GLOBAL__N_11CD2Ev( |
253 | // CHECK4: ret void |
254 | |
255 | // CHECK4-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD0Ev( |
256 | // CHECK4: getelementptr inbounds i8, i8* {{.*}}, i64 -8 |
257 | // CHECK4: call void @_ZN5test312_GLOBAL__N_11CD0Ev( |
258 | // CHECK4: ret void |
259 | |
260 | // CHECK4-LABEL: declare void @_ZN5test31BD2Ev( |
261 | // CHECK4-LABEL: declare void @_ZN5test31AD2Ev( |
262 | |
263 | // CHECK4: attributes [[NUW]] = {{[{].*}} nounwind {{.*[}]}} |
264 | } |
265 | |
266 | namespace test4 { |
267 | struct A { ~A(); }; |
268 | |
269 | // CHECK5-LABEL: define void @_ZN5test43fooEv() |
270 | // CHECK5: call void @_ZN5test41AD1Ev |
271 | // CHECK5: ret void |
272 | void foo() { |
273 | { |
274 | A a; |
275 | goto failure; |
276 | } |
277 | |
278 | failure: |
279 | return; |
280 | } |
281 | |
282 | // CHECK5-LABEL: define void @_ZN5test43barEi( |
283 | // CHECK5: [[X:%.*]] = alloca i32 |
284 | // CHECK5-NEXT: [[A:%.*]] = alloca |
285 | // CHECK5: br label |
286 | // CHECK5: [[TMP:%.*]] = load i32, i32* [[X]] |
287 | // CHECK5-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP]], 0 |
288 | // CHECK5-NEXT: br i1 |
289 | // CHECK5: call void @_ZN5test41AD1Ev( |
290 | // CHECK5: br label |
291 | // CHECK5: [[TMP:%.*]] = load i32, i32* [[X]] |
292 | // CHECK5: [[TMP2:%.*]] = add nsw i32 [[TMP]], -1 |
293 | // CHECK5: store i32 [[TMP2]], i32* [[X]] |
294 | // CHECK5: br label |
295 | // CHECK5: ret void |
296 | void bar(int x) { |
297 | for (A a; x; ) { |
298 | x--; |
299 | } |
300 | } |
301 | } |
302 | |
303 | // PR7575 |
304 | namespace test5 { |
305 | struct A { ~A(); }; |
306 | |
307 | // CHECK5-LABEL: define void @_ZN5test53fooEv() |
308 | // CHECK5: [[ELEMS:%.*]] = alloca [5 x [[A:%.*]]], align |
309 | // CHECK5v03-NEXT: [[EXN:%.*]] = alloca i8* |
310 | // CHECK5v03-NEXT: [[SEL:%.*]] = alloca i32 |
311 | // CHECK5-NEXT: [[PELEMS:%.*]] = bitcast [5 x [[A]]]* [[ELEMS]] to i8* |
312 | // CHECK5-NEXT: call void @llvm.lifetime.start.p0i8(i64 5, i8* [[PELEMS]]) |
313 | // CHECK5-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [5 x [[A]]], [5 x [[A]]]* [[ELEMS]], i32 0, i32 0 |
314 | // CHECK5-NEXT: [[END:%.*]] = getelementptr inbounds [[A]], [[A]]* [[BEGIN]], i64 5 |
315 | // CHECK5-NEXT: br label |
316 | // CHECK5: [[POST:%.*]] = phi [[A]]* [ [[END]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ] |
317 | // CHECK5-NEXT: [[ELT]] = getelementptr inbounds [[A]], [[A]]* [[POST]], i64 -1 |
318 | // CHECK5v03-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[ELT]]) |
319 | // CHECK5v11-NEXT: call void @_ZN5test51AD1Ev([[A]]* [[ELT]]) |
320 | // CHECK5: [[T0:%.*]] = icmp eq [[A]]* [[ELT]], [[BEGIN]] |
321 | // CHECK5-NEXT: br i1 [[T0]], |
322 | // CHECK5: call void @llvm.lifetime.end |
323 | // CHECK5-NEXT: ret void |
324 | // lpad |
325 | // CHECK5v03: [[EMPTY:%.*]] = icmp eq [[A]]* [[BEGIN]], [[ELT]] |
326 | // CHECK5v03-NEXT: br i1 [[EMPTY]] |
327 | // CHECK5v03: [[AFTER:%.*]] = phi [[A]]* [ [[ELT]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] |
328 | // CHECK5v03-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]], [[A]]* [[AFTER]], i64 -1 |
329 | // CHECK5v03-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[CUR]]) |
330 | // CHECK5v03: [[DONE:%.*]] = icmp eq [[A]]* [[CUR]], [[BEGIN]] |
331 | // CHECK5v03-NEXT: br i1 [[DONE]], |
332 | // CHECK5v11-NOT: landingpad |
333 | // CHECK5v11: } |
334 | void foo() { |
335 | A elems[5]; |
336 | } |
337 | } |
338 | |
339 | namespace test6 { |
340 | void opaque(); |
341 | |
342 | struct A { ~A(); }; |
343 | template <unsigned> struct B { B(); ~B(); int _; }; |
344 | struct C : B<0>, B<1>, virtual B<2>, virtual B<3> { |
345 | A x, y, z; |
346 | |
347 | C(); |
348 | ~C(); |
349 | }; |
350 | |
351 | C::C() { opaque(); } |
352 | // CHECK5-LABEL: define void @_ZN5test61CC1Ev(%"struct.test6::C"* %this) unnamed_addr |
353 | // CHECK5: call void @_ZN5test61BILj2EEC2Ev |
354 | // CHECK5: invoke void @_ZN5test61BILj3EEC2Ev |
355 | // CHECK5: invoke void @_ZN5test61BILj0EEC2Ev |
356 | // CHECK5: invoke void @_ZN5test61BILj1EEC2Ev |
357 | // CHECK5: invoke void @_ZN5test66opaqueEv |
358 | // CHECK5: ret void |
359 | // FIXME: way too much EH cleanup code follows |
360 | |
361 | C::~C() { opaque(); } |
362 | // CHECK5-LABEL: define void @_ZN5test61CD2Ev(%"struct.test6::C"* %this, i8** %vtt) unnamed_addr |
363 | // CHECK5: invoke void @_ZN5test66opaqueEv |
364 | // CHECK5v03: invoke void @_ZN5test61AD1Ev |
365 | // CHECK5v03: invoke void @_ZN5test61AD1Ev |
366 | // CHECK5v03: invoke void @_ZN5test61AD1Ev |
367 | // CHECK5v03: invoke void @_ZN5test61BILj1EED2Ev |
368 | // CHECK5v11: call void @_ZN5test61AD1Ev |
369 | // CHECK5v11: call void @_ZN5test61AD1Ev |
370 | // CHECK5v11: call void @_ZN5test61AD1Ev |
371 | // CHECK5v11: call void @_ZN5test61BILj1EED2Ev |
372 | // CHECK5: call void @_ZN5test61BILj0EED2Ev |
373 | // CHECK5: ret void |
374 | // CHECK5v03: invoke void @_ZN5test61AD1Ev |
375 | // CHECK5v03: invoke void @_ZN5test61AD1Ev |
376 | // CHECK5v03: invoke void @_ZN5test61AD1Ev |
377 | // CHECK5v03: invoke void @_ZN5test61BILj1EED2Ev |
378 | // CHECK5v03: invoke void @_ZN5test61BILj0EED2Ev |
379 | |
380 | // CHECK5-LABEL: define void @_ZN5test61CD1Ev(%"struct.test6::C"* %this) unnamed_addr |
381 | // CHECK5v03: invoke void @_ZN5test61CD2Ev |
382 | // CHECK5v03: invoke void @_ZN5test61BILj3EED2Ev |
383 | // CHECK5v03: call void @_ZN5test61BILj2EED2Ev |
384 | // CHECK5v03: ret void |
385 | // CHECK5v03: invoke void @_ZN5test61BILj3EED2Ev |
386 | // CHECK5v03: invoke void @_ZN5test61BILj2EED2Ev |
387 | |
388 | // CHECK5v11: call void @_ZN5test61CD2Ev |
389 | // CHECK5v11: call void @_ZN5test61BILj3EED2Ev |
390 | // CHECK5v11: call void @_ZN5test61BILj2EED2Ev |
391 | // CHECK5v11: ret void |
392 | } |
393 | |
394 | // PR 9197 |
395 | namespace test7 { |
396 | struct D { ~D(); }; |
397 | |
398 | struct A { ~A(); }; |
399 | A::~A() { } |
400 | |
401 | struct B : public A { |
402 | ~B(); |
403 | D arr[1]; |
404 | }; |
405 | |
406 | // Verify that this doesn't get emitted as an alias |
407 | // CHECK5-LABEL: define void @_ZN5test71BD2Ev( |
408 | // CHECK5v03: invoke void @_ZN5test71DD1Ev( |
409 | // CHECK5v11: call void @_ZN5test71DD1Ev( |
410 | // CHECK5: call void @_ZN5test71AD2Ev( |
411 | B::~B() {} |
412 | } |
413 | |
414 | // PR10467 |
415 | namespace test8 { |
416 | struct A { A(); ~A(); }; |
417 | |
418 | void die() __attribute__((noreturn)); |
419 | void test() { |
420 | A x; |
421 | while (1) { |
422 | A y; |
423 | goto l; |
424 | } |
425 | l: die(); |
426 | } |
427 | |
428 | // CHECK5-LABEL: define void @_ZN5test84testEv() |
429 | // CHECK5: [[X:%.*]] = alloca [[A:%.*]], align 1 |
430 | // CHECK5-NEXT: [[Y:%.*]] = alloca [[A:%.*]], align 1 |
431 | // CHECK5: call void @_ZN5test81AC1Ev([[A]]* [[X]]) |
432 | // CHECK5-NEXT: br label |
433 | // CHECK5: invoke void @_ZN5test81AC1Ev([[A]]* [[Y]]) |
434 | // CHECK5v03: invoke void @_ZN5test81AD1Ev([[A]]* [[Y]]) |
435 | // CHECK5v11: call void @_ZN5test81AD1Ev([[A]]* [[Y]]) |
436 | // CHECK5-NOT: switch |
437 | // CHECK5: invoke void @_ZN5test83dieEv() |
438 | // CHECK5: unreachable |
439 | } |
440 | |
441 | // PR12710 |
442 | namespace test9 { |
443 | struct ArgType { |
444 | ~ArgType(); |
445 | }; |
446 | template<typename T> |
447 | void f1(const ArgType& = ArgType()); |
448 | void f2(); |
449 | void bar() { |
450 | f1<int>(); |
451 | f2(); |
452 | } |
453 | // CHECK5: call void @_ZN5test97ArgTypeD1Ev(%"struct.test9::ArgType"* % |
454 | // CHECK5: call void @_ZN5test92f2Ev() |
455 | } |
456 | |
457 | namespace test10 { |
458 | // We used to crash trying to replace _ZN6test106OptionD1Ev with |
459 | // _ZN6test106OptionD2Ev twice. |
460 | struct Option { |
461 | virtual ~Option() {} |
462 | }; |
463 | template <class DataType> class opt : public Option {}; |
464 | template class opt<int>; |
465 | // CHECK5-LABEL: define zeroext i1 @_ZN6test1016handleOccurrenceEv( |
466 | bool handleOccurrence() { |
467 | // CHECK5: call void @_ZN6test106OptionD2Ev( |
468 | Option x; |
469 | return true; |
470 | } |
471 | } |
472 | |
473 | #if __cplusplus >= 201103L |
474 | namespace test11 { |
475 | |
476 | // Check that lifetime.end is emitted in the landing pad. |
477 | |
478 | // CHECK6-LABEL: define void @_ZN6test1115testLifetimeEndEi( |
479 | // CHECK6: entry: |
480 | // CHECK6: [[T1:%[a-z0-9]+]] = alloca %"struct.test11::S1" |
481 | // CHECK6: [[T2:%[a-z0-9]+]] = alloca %"struct.test11::S1" |
482 | // CHECK6: [[T3:%[a-z0-9]+]] = alloca %"struct.test11::S1" |
483 | |
484 | // CHECK6: {{^}}invoke.cont |
485 | // CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T1]]) |
486 | // CHECK6: [[BC1:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T1]] to i8* |
487 | // CHECK6: call void @llvm.lifetime.end.p0i8(i64 32, i8* [[BC1]]) |
488 | // CHECK6: {{^}}lpad |
489 | // CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T1]]) |
490 | // CHECK6: [[BC2:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T1]] to i8* |
491 | // CHECK6: call void @llvm.lifetime.end.p0i8(i64 32, i8* [[BC2]]) |
492 | |
493 | // CHECK6: {{^}}invoke.cont |
494 | // CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T2]]) |
495 | // CHECK6: [[BC3:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T2]] to i8* |
496 | // CHECK6: call void @llvm.lifetime.end.p0i8(i64 32, i8* [[BC3]]) |
497 | // CHECK6: {{^}}lpad |
498 | // CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T2]]) |
499 | // CHECK6: [[BC4:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T2]] to i8* |
500 | // CHECK6: call void @llvm.lifetime.end.p0i8(i64 32, i8* [[BC4]]) |
501 | |
502 | // CHECK6: {{^}}invoke.cont |
503 | // CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T3]]) |
504 | // CHECK6: [[BC5:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T3]] to i8* |
505 | // CHECK6: call void @llvm.lifetime.end.p0i8(i64 32, i8* [[BC5]]) |
506 | // CHECK6: {{^}}lpad |
507 | // CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T3]]) |
508 | // CHECK6: [[BC6:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T3]] to i8* |
509 | // CHECK6: call void @llvm.lifetime.end.p0i8(i64 32, i8* [[BC6]]) |
510 | |
511 | struct S1 { |
512 | ~S1(); |
513 | int a[8]; |
514 | }; |
515 | |
516 | void func1(S1 &) noexcept(false); |
517 | |
518 | void testLifetimeEnd(int n) { |
519 | if (n < 10) { |
520 | S1 t1; |
521 | func1(t1); |
522 | } else if (n < 100) { |
523 | S1 t2; |
524 | func1(t2); |
525 | } else if (n < 1000) { |
526 | S1 t3; |
527 | func1(t3); |
528 | } |
529 | } |
530 | |
531 | } |
532 | #endif |
533 | |