destructors.cpp revision f1549f66a8216a78112286e3978cea2c29d6334c
1// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -mconstructor-aliases -fexceptions | FileCheck %s
2
3// CHECK: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev
4// CHECK: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev
5// CHECK: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev
6// CHECK: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev
7// CHECK: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev
8
9// CHECK: @_ZN5test312_GLOBAL__N_11DD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11DD2Ev
10// CHECK: @_ZN5test312_GLOBAL__N_11DD2Ev = alias internal bitcast {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
11// CHECK: @_ZN5test312_GLOBAL__N_11CD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
12
13struct A {
14  int a;
15
16  ~A();
17};
18
19// Base with non-trivial destructor
20struct B : A {
21  ~B();
22};
23
24B::~B() { }
25
26// Field with non-trivial destructor
27struct C {
28  A a;
29
30  ~C();
31};
32
33C::~C() { }
34
35namespace PR7526 {
36  extern void foo();
37  struct allocator {
38    ~allocator() throw();
39  };
40
41  struct allocator_derived : allocator { };
42
43  // CHECK: define void @_ZN6PR75269allocatorD2Ev
44  // CHECK: call void @__cxa_call_unexpected
45  allocator::~allocator() throw() { foo(); }
46
47  // CHECK: define linkonce_odr void @_ZN6PR752617allocator_derivedD1Ev
48  // CHECK: call void @__cxa_call_unexpected
49  void foo() {
50    allocator_derived ad;
51  }
52}
53
54// PR5084
55template<typename T>
56class A1 {
57  ~A1();
58};
59
60template<> A1<char>::~A1();
61
62// PR5529
63namespace PR5529 {
64  struct A {
65    ~A();
66  };
67
68  A::~A() { }
69  struct B : A {
70    virtual ~B();
71  };
72
73  B::~B()  {}
74}
75
76// FIXME: there's a known problem in the codegen here where, if one
77// destructor throws, the remaining destructors aren't run.  Fix it,
78// then make this code check for it.
79namespace test0 {
80  void foo();
81  struct VBase { ~VBase(); };
82  struct Base { ~Base(); };
83  struct Member { ~Member(); };
84
85  struct A : Base {
86    Member M;
87    ~A();
88  };
89
90  // The function-try-block won't suppress -mconstructor-aliases here.
91  A::~A() try { } catch (int i) {}
92
93// complete destructor alias tested above
94
95// CHECK: define void @_ZN5test01AD2Ev
96// CHECK: invoke void @_ZN5test06MemberD1Ev
97// CHECK:   unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]]
98// CHECK: invoke void @_ZN5test04BaseD2Ev
99// CHECK:   unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]]
100
101  struct B : Base, virtual VBase {
102    Member M;
103    ~B();
104  };
105  B::~B() try { } catch (int i) {}
106  // It will suppress the delegation optimization here, though.
107
108// CHECK: define void @_ZN5test01BD1Ev
109// CHECK: invoke void @_ZN5test06MemberD1Ev
110// CHECK:   unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]]
111// CHECK: invoke void @_ZN5test04BaseD2Ev
112// CHECK:   unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]]
113// CHECK: invoke void @_ZN5test05VBaseD2Ev
114// CHECK:   unwind label [[VBASE_UNWIND:%[a-zA-Z0-9.]+]]
115
116// CHECK: define void @_ZN5test01BD2Ev
117// CHECK: invoke void @_ZN5test06MemberD1Ev
118// CHECK:   unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]]
119// CHECK: invoke void @_ZN5test04BaseD2Ev
120// CHECK:   unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]]
121}
122
123// Test base-class aliasing.
124namespace test1 {
125  struct A { ~A(); char ***m; }; // non-trivial destructor
126  struct B { ~B(); }; // non-trivial destructor
127  struct Empty { }; // trivial destructor, empty
128  struct NonEmpty { int x; }; // trivial destructor, non-empty
129
130  // There must be a definition in this translation unit for the alias
131  // optimization to apply.
132  A::~A() { delete m; }
133
134  struct M : A { ~M(); };
135  M::~M() {} // alias tested above
136
137  struct N : A, Empty { ~N(); };
138  N::~N() {} // alias tested above
139
140  struct O : Empty, A { ~O(); };
141  O::~O() {} // alias tested above
142
143  struct P : NonEmpty, A { ~P(); };
144  P::~P() {} // CHECK: define void @_ZN5test11PD2Ev
145
146  struct Q : A, B { ~Q(); };
147  Q::~Q() {} // CHECK: define void @_ZN5test11QD2Ev
148
149  struct R : A { ~R(); };
150  R::~R() { A a; } // CHECK: define void @_ZN5test11RD2Ev
151
152  struct S : A { ~S(); int x; };
153  S::~S() {} // alias tested above
154
155  struct T : A { ~T(); B x; };
156  T::~T() {} // CHECK: define void @_ZN5test11TD2Ev
157
158  // The VTT parameter prevents this.  We could still make this work
159  // for calling conventions that are safe against extra parameters.
160  struct U : A, virtual B { ~U(); };
161  U::~U() {} // CHECK: define void @_ZN5test11UD2Ev
162}
163
164// PR6471
165namespace test2 {
166  struct A { ~A(); char ***m; };
167  struct B : A { ~B(); };
168
169  B::~B() {}
170  // CHECK: define void @_ZN5test21BD2Ev
171  // CHECK: call void @_ZN5test21AD2Ev
172}
173
174// PR7142
175namespace test3 {
176  struct A { virtual ~A(); };
177  struct B { virtual ~B(); };
178  namespace { // internal linkage => deferred
179    struct C : A, B {}; // ~B() in D requires a this-adjustment thunk
180    struct D : C {};    // D::~D() is an alias to C::~C()
181  }
182
183  void test() {
184    new D; // Force emission of D's vtable
185  }
186
187  // Checked at top of file:
188  // @_ZN5test312_GLOBAL__N_11CD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
189
190  // More checks at end of file.
191
192}
193
194namespace test4 {
195  struct A { ~A(); };
196
197  // CHECK: define void @_ZN5test43fooEv()
198  // CHECK: call void @_ZN5test41AD1Ev
199  // CHECK: ret void
200  void foo() {
201    {
202      A a;
203      goto failure;
204    }
205
206  failure:
207    return;
208  }
209
210  // CHECK: define void @_ZN5test43barEi(
211  // CHECK:      [[X:%.*]] = alloca i32
212  // CHECK-NEXT: [[A:%.*]] = alloca
213  // CHECK:      br label
214  // CHECK:      [[TMP:%.*]] = load i32* [[X]]
215  // CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP]], 0
216  // CHECK-NEXT: br i1
217  // CHECK:      call void @_ZN5test41AD1Ev(
218  // CHECK:      br label
219  // CHECK:      [[TMP:%.*]] = load i32* [[X]]
220  // CHECK:      [[TMP2:%.*]] = add nsw i32 [[TMP]], -1
221  // CHECK:      store i32 [[TMP2]], i32* [[X]]
222  // CHECK:      br label
223  // CHECK:      ret void
224  void bar(int x) {
225    for (A a; x; ) {
226      x--;
227    }
228  }
229}
230
231// Checks from test3:
232
233  // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(
234  // CHECK: call void @_ZN5test31BD2Ev(
235  // CHECK: call void @_ZN5test31AD2Ev(
236  // CHECK: ret void
237
238  // CHECK: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(
239  // CHECK: invoke void @_ZN5test312_GLOBAL__N_11DD1Ev(
240  // CHECK: call void @_ZdlPv(
241  // CHECK: ret void
242  // CHECK: call i8* @llvm.eh.exception(
243  // CHECK: invoke void @_ZdlPv
244  // CHECK: call void @_Unwind_Resume_or_Rethrow
245  // CHECK: call i8* @llvm.eh.exception(
246  // CHECK: call void @_ZSt9terminatev(
247
248  // Checked at top of file:
249  // @_ZN5test312_GLOBAL__N_11DD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11DD2Ev
250  // @_ZN5test312_GLOBAL__N_11DD2Ev = alias internal bitcast {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
251
252  // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD1Ev(
253  // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
254  // CHECK: call void @_ZN5test312_GLOBAL__N_11DD1Ev(
255  // CHECK: ret void
256
257  // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD0Ev(
258  // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
259  // CHECK: call void @_ZN5test312_GLOBAL__N_11DD0Ev(
260  // CHECK: ret void
261
262  // CHECK: declare void @_ZN5test31BD2Ev(
263  // CHECK: declare void @_ZN5test31AD2Ev(
264
265  // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev(
266  // CHECK: invoke void @_ZN5test312_GLOBAL__N_11CD1Ev(
267  // CHECK: call void @_ZdlPv(
268  // CHECK: ret void
269  // CHECK: call i8* @llvm.eh.exception()
270  // CHECK: invoke void @_ZdlPv(
271  // CHECK: call void @_Unwind_Resume_or_Rethrow(
272  // CHECK: call i8* @llvm.eh.exception()
273  // CHECK: call void @_ZSt9terminatev()
274
275  // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev(
276  // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
277  // CHECK: call void @_ZN5test312_GLOBAL__N_11CD1Ev(
278  // CHECK: ret void
279
280  // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD0Ev(
281  // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
282  // CHECK: call void @_ZN5test312_GLOBAL__N_11CD0Ev(
283  // CHECK: ret void
284