]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/CodeGenCXX/destructors.cpp
Vendor import of clang release_34 branch r197841 (effectively, 3.4 RC3):
[FreeBSD/FreeBSD.git] / test / CodeGenCXX / destructors.cpp
1 // RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -mconstructor-aliases -fcxx-exceptions -fexceptions -O1 -disable-llvm-optzns | FileCheck %s
2
3 // CHECK-DAG: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev
4 // CHECK-DAG: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev
5 // CHECK-DAG: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev
6 // CHECK-DAG: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev
7 // CHECK-DAG: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev
8
9 struct A {
10   int a;
11   
12   ~A();
13 };
14
15 // Base with non-trivial destructor
16 struct B : A {
17   ~B();
18 };
19
20 B::~B() { }
21
22 // Field with non-trivial destructor
23 struct C {
24   A a;
25   
26   ~C();
27 };
28
29 C::~C() { }
30
31 namespace PR7526 {
32   extern void foo();
33   struct allocator {
34     ~allocator() throw();
35   };
36
37   struct allocator_derived : allocator { };
38
39   // CHECK-LABEL: define void @_ZN6PR75263fooEv()
40   // CHECK: call void {{.*}} @_ZN6PR75269allocatorD2Ev
41
42   // CHECK-LABEL: define void @_ZN6PR75269allocatorD2Ev(%"struct.PR7526::allocator"* %this) unnamed_addr
43   // CHECK: call void @__cxa_call_unexpected
44   allocator::~allocator() throw() { foo(); }
45
46   void foo() {
47     allocator_derived ad;
48   }
49 }
50
51 // PR5084
52 template<typename T>
53 class A1 {
54   ~A1();
55 };
56
57 template<> A1<char>::~A1();
58
59 // PR5529
60 namespace PR5529 {
61   struct A {
62     ~A();
63   };
64   
65   A::~A() { }
66   struct B : A {
67     virtual ~B();
68   };
69   
70   B::~B()  {}
71 }
72
73 // FIXME: there's a known problem in the codegen here where, if one
74 // destructor throws, the remaining destructors aren't run.  Fix it,
75 // then make this code check for it.
76 namespace test0 {
77   void foo();
78   struct VBase { ~VBase(); };
79   struct Base { ~Base(); };
80   struct Member { ~Member(); };
81
82   struct A : Base {
83     Member M;
84     ~A();
85   };
86
87   // The function-try-block won't suppress -mconstructor-aliases here.
88   A::~A() try { } catch (int i) {}
89
90 // complete destructor alias tested above
91
92 // CHECK-LABEL: define void @_ZN5test01AD2Ev(%"struct.test0::A"* %this) unnamed_addr
93 // CHECK: invoke void @_ZN5test06MemberD1Ev
94 // CHECK:   unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]]
95 // CHECK: invoke void @_ZN5test04BaseD2Ev
96 // CHECK:   unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]]
97
98   struct B : Base, virtual VBase {
99     Member M;
100     ~B();
101   };
102   B::~B() try { } catch (int i) {}
103   // It will suppress the delegation optimization here, though.
104
105 // CHECK-LABEL: define void @_ZN5test01BD1Ev(%"struct.test0::B"* %this) unnamed_addr
106 // CHECK: invoke void @_ZN5test06MemberD1Ev
107 // CHECK:   unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]]
108 // CHECK: invoke void @_ZN5test04BaseD2Ev
109 // CHECK:   unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]]
110 // CHECK: invoke void @_ZN5test05VBaseD2Ev
111 // CHECK:   unwind label [[VBASE_UNWIND:%[a-zA-Z0-9.]+]]
112
113 // CHECK-LABEL: define void @_ZN5test01BD2Ev(%"struct.test0::B"* %this, i8** %vtt) unnamed_addr
114 // CHECK: invoke void @_ZN5test06MemberD1Ev
115 // CHECK:   unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]]
116 // CHECK: invoke void @_ZN5test04BaseD2Ev
117 // CHECK:   unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]]
118 }
119
120 // Test base-class aliasing.
121 namespace test1 {
122   struct A { ~A(); char ***m; }; // non-trivial destructor
123   struct B { ~B(); }; // non-trivial destructor
124   struct Empty { }; // trivial destructor, empty
125   struct NonEmpty { int x; }; // trivial destructor, non-empty
126
127   // There must be a definition in this translation unit for the alias
128   // optimization to apply.
129   A::~A() { delete m; }
130
131   struct M : A { ~M(); };
132   M::~M() {} // alias tested above
133
134   struct N : A, Empty { ~N(); };
135   N::~N() {} // alias tested above
136
137   struct O : Empty, A { ~O(); };
138   O::~O() {} // alias tested above
139
140   struct P : NonEmpty, A { ~P(); };
141   P::~P() {} // CHECK-LABEL: define void @_ZN5test11PD2Ev(%"struct.test1::P"* %this) unnamed_addr
142
143   struct Q : A, B { ~Q(); };
144   Q::~Q() {} // CHECK-LABEL: define void @_ZN5test11QD2Ev(%"struct.test1::Q"* %this) unnamed_addr
145
146   struct R : A { ~R(); };
147   R::~R() { A a; } // CHECK-LABEL: define void @_ZN5test11RD2Ev(%"struct.test1::R"* %this) unnamed_addr
148
149   struct S : A { ~S(); int x; };
150   S::~S() {} // alias tested above
151
152   struct T : A { ~T(); B x; };
153   T::~T() {} // CHECK-LABEL: define void @_ZN5test11TD2Ev(%"struct.test1::T"* %this) unnamed_addr
154
155   // The VTT parameter prevents this.  We could still make this work
156   // for calling conventions that are safe against extra parameters.
157   struct U : A, virtual B { ~U(); };
158   U::~U() {} // CHECK-LABEL: define void @_ZN5test11UD2Ev(%"struct.test1::U"* %this, i8** %vtt) unnamed_addr
159 }
160
161 // PR6471
162 namespace test2 {
163   struct A { ~A(); char ***m; };
164   struct B : A { ~B(); };
165
166   B::~B() {}
167   // CHECK-LABEL: define void @_ZN5test21BD2Ev(%"struct.test2::B"* %this) unnamed_addr
168   // CHECK: call void @_ZN5test21AD2Ev
169 }
170
171 // PR7142
172 namespace test3 {
173   struct A { virtual ~A(); };
174   struct B { virtual ~B(); };
175   namespace { // internal linkage => deferred
176     struct C : A, B {}; // ~B() in D requires a this-adjustment thunk
177     struct D : C {};    // D::~D() is an alias to C::~C()
178   }
179
180   void test() {
181     new D; // Force emission of D's vtable
182   }
183 }
184
185 namespace test4 {
186   struct A { ~A(); };
187
188   // CHECK-LABEL: define void @_ZN5test43fooEv()
189   // CHECK: call void @_ZN5test41AD1Ev
190   // CHECK: ret void
191   void foo() {
192     {
193       A a;
194       goto failure;
195     }
196
197   failure:
198     return;
199   }
200
201   // CHECK-LABEL: define void @_ZN5test43barEi(
202   // CHECK:      [[X:%.*]] = alloca i32
203   // CHECK-NEXT: [[A:%.*]] = alloca
204   // CHECK:      br label
205   // CHECK:      [[TMP:%.*]] = load i32* [[X]]
206   // CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP]], 0
207   // CHECK-NEXT: br i1
208   // CHECK:      call void @_ZN5test41AD1Ev(
209   // CHECK:      br label
210   // CHECK:      [[TMP:%.*]] = load i32* [[X]]
211   // CHECK:      [[TMP2:%.*]] = add nsw i32 [[TMP]], -1
212   // CHECK:      store i32 [[TMP2]], i32* [[X]]
213   // CHECK:      br label
214   // CHECK:      ret void
215   void bar(int x) {
216     for (A a; x; ) {
217       x--;
218     }
219   }
220 }
221
222 // PR7575
223 namespace test5 {
224   struct A { ~A(); };
225
226   // CHECK-LABEL: define void @_ZN5test53fooEv()
227   // CHECK:      [[ELEMS:%.*]] = alloca [5 x [[A:%.*]]], align
228   // CHECK-NEXT: [[EXN:%.*]] = alloca i8*
229   // CHECK-NEXT: [[SEL:%.*]] = alloca i32
230   // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [5 x [[A]]]* [[ELEMS]], i32 0, i32 0
231   // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A]]* [[BEGIN]], i64 5
232   // CHECK-NEXT: br label
233   // CHECK:      [[POST:%.*]] = phi [[A]]* [ [[END]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ]
234   // CHECK-NEXT: [[ELT]] = getelementptr inbounds [[A]]* [[POST]], i64 -1
235   // CHECK-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[ELT]])
236   // CHECK:      [[T0:%.*]] = icmp eq [[A]]* [[ELT]], [[BEGIN]]
237   // CHECK-NEXT: br i1 [[T0]],
238   // CHECK:      ret void
239   // lpad
240   // CHECK:      [[EMPTY:%.*]] = icmp eq [[A]]* [[BEGIN]], [[ELT]]
241   // CHECK-NEXT: br i1 [[EMPTY]]
242   // CHECK:      [[AFTER:%.*]] = phi [[A]]* [ [[ELT]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
243   // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]]* [[AFTER]], i64 -1
244   // CHECK-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[CUR]])
245   // CHECK:      [[DONE:%.*]] = icmp eq [[A]]* [[CUR]], [[BEGIN]]
246   // CHECK-NEXT: br i1 [[DONE]],
247   void foo() {
248     A elems[5];
249   }
250 }
251
252 namespace test6 {
253   void opaque();
254
255   struct A { ~A(); };
256   template <unsigned> struct B { B(); ~B(); int _; };
257   struct C : B<0>, B<1>, virtual B<2>, virtual B<3> {
258     A x, y, z;
259
260     C();
261     ~C();
262   };
263
264   C::C() { opaque(); }
265   // CHECK-LABEL: define void @_ZN5test61CC1Ev(%"struct.test6::C"* %this) unnamed_addr
266   // CHECK:   call void @_ZN5test61BILj2EEC2Ev
267   // CHECK:   invoke void @_ZN5test61BILj3EEC2Ev
268   // CHECK:   invoke void @_ZN5test61BILj0EEC2Ev
269   // CHECK:   invoke void @_ZN5test61BILj1EEC2Ev
270   // CHECK:   invoke void @_ZN5test66opaqueEv
271   // CHECK:   ret void
272   // FIXME: way too much EH cleanup code follows
273
274   C::~C() { opaque(); }
275   // CHECK-LABEL: define void @_ZN5test61CD1Ev(%"struct.test6::C"* %this) unnamed_addr
276   // CHECK:   invoke void @_ZN5test61CD2Ev
277   // CHECK:   invoke void @_ZN5test61BILj3EED2Ev
278   // CHECK:   call void @_ZN5test61BILj2EED2Ev
279   // CHECK:   ret void
280   // CHECK:   invoke void @_ZN5test61BILj3EED2Ev
281   // CHECK:   invoke void @_ZN5test61BILj2EED2Ev
282
283   // CHECK-LABEL: define void @_ZN5test61CD2Ev(%"struct.test6::C"* %this, i8** %vtt) unnamed_addr
284   // CHECK:   invoke void @_ZN5test66opaqueEv
285   // CHECK:   invoke void @_ZN5test61AD1Ev
286   // CHECK:   invoke void @_ZN5test61AD1Ev
287   // CHECK:   invoke void @_ZN5test61AD1Ev
288   // CHECK:   invoke void @_ZN5test61BILj1EED2Ev
289   // CHECK:   call void @_ZN5test61BILj0EED2Ev
290   // CHECK:   ret void
291   // CHECK:   invoke void @_ZN5test61AD1Ev
292   // CHECK:   invoke void @_ZN5test61AD1Ev
293   // CHECK:   invoke void @_ZN5test61AD1Ev
294   // CHECK:   invoke void @_ZN5test61BILj1EED2Ev
295   // CHECK:   invoke void @_ZN5test61BILj0EED2Ev
296 }
297
298 // PR 9197
299 namespace test7 {
300   struct D { ~D(); };
301
302   struct A { ~A(); };
303   A::~A() { }
304
305   struct B : public A {
306     ~B();
307     D arr[1];
308   };
309
310   // Verify that this doesn't get emitted as an alias
311   // CHECK-LABEL: define void @_ZN5test71BD2Ev(
312   // CHECK:   invoke void @_ZN5test71DD1Ev(
313   // CHECK:   call void @_ZN5test71AD2Ev(
314   B::~B() {}
315 }
316
317 // PR10467
318 namespace test8 {
319   struct A { A(); ~A(); };
320
321   void die() __attribute__((noreturn));
322   void test() {
323     A x;
324     while (1) {
325       A y;
326       goto l;
327     }
328   l: die();
329   }
330
331   // CHECK-LABEL:    define void @_ZN5test84testEv()
332   // CHECK:      [[X:%.*]] = alloca [[A:%.*]], align 1
333   // CHECK-NEXT: [[Y:%.*]] = alloca [[A:%.*]], align 1
334   // CHECK:      call void @_ZN5test81AC1Ev([[A]]* [[X]])
335   // CHECK-NEXT: br label
336   // CHECK:      invoke void @_ZN5test81AC1Ev([[A]]* [[Y]])
337   // CHECK:      invoke void @_ZN5test81AD1Ev([[A]]* [[Y]])
338   // CHECK-NOT:  switch
339   // CHECK:      invoke void @_ZN5test83dieEv()
340   // CHECK:      unreachable
341 }
342
343 // PR12710
344 namespace test9 {
345   struct ArgType {
346     ~ArgType();
347   };
348   template<typename T>
349   void f1(const ArgType& = ArgType());
350   void f2();
351   void bar() {
352     f1<int>();
353     f2();
354   }
355   // CHECK: call void @_ZN5test97ArgTypeD1Ev(%"struct.test9::ArgType"* %
356   // CHECK: call void @_ZN5test92f2Ev()
357 }
358
359 namespace test10 {
360   // We used to crash trying to replace _ZN6test106OptionD1Ev with
361   // _ZN6test106OptionD2Ev twice.
362   struct Option {
363     virtual ~Option() {}
364   };
365   template <class DataType> class opt : public Option {};
366   template class opt<int>;
367   // CHECK-LABEL: define zeroext i1 @_ZN6test1016handleOccurrenceEv(
368   bool handleOccurrence() {
369     // CHECK: call void @_ZN6test106OptionD2Ev(
370     Option x;
371     return true;
372   }
373 }
374
375 // Checks from test3:
376
377   // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::<anonymous namespace>::D"* %this) unnamed_addr
378   // CHECK: invoke void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
379   // CHECK: call void @_ZdlPv({{.*}}) [[NUW:#[0-9]+]]
380   // CHECK: ret void
381   // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
382   // CHECK-NEXT: cleanup
383   // CHECK: call void @_ZdlPv({{.*}}) [[NUW]]
384   // CHECK: resume { i8*, i32 }
385
386   // CHECK-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD1Ev(
387   // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
388   // CHECK: call void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
389   // CHECK: ret void
390
391   // CHECK-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD0Ev(
392   // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
393   // CHECK: call void @_ZN5test312_GLOBAL__N_11DD0Ev(
394   // CHECK: ret void
395
396   // CHECK-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev(
397   // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
398   // CHECK: call void @_ZN5test312_GLOBAL__N_11CD2Ev(
399   // CHECK: ret void
400
401   // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(%"struct.test3::<anonymous namespace>::C"* %this) unnamed_addr
402   // CHECK: invoke void @_ZN5test31BD2Ev(
403   // CHECK: call void @_ZN5test31AD2Ev(
404   // CHECK: ret void
405
406   // CHECK: declare void @_ZN5test31BD2Ev(
407   // CHECK: declare void @_ZN5test31AD2Ev(
408
409   // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev(%"struct.test3::<anonymous namespace>::C"* %this) unnamed_addr
410   // CHECK: invoke void @_ZN5test312_GLOBAL__N_11CD2Ev(
411   // CHECK: call void @_ZdlPv({{.*}}) [[NUW]]
412   // CHECK: ret void
413   // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
414   // CHECK-NEXT: cleanup
415   // CHECK: call void @_ZdlPv({{.*}}) [[NUW]]
416   // CHECK: resume { i8*, i32 }
417
418   // CHECK-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD0Ev(
419   // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
420   // CHECK: call void @_ZN5test312_GLOBAL__N_11CD0Ev(
421   // CHECK: ret void
422
423   // CHECK: attributes [[NUW]] = {{[{].*}} nounwind {{.*[}]}}