destructors.cpp revision 4b662a5684d41ea4ff6b52711929e00fefb00db1
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
35// PR5084
36template<typename T>
37class A1 {
38  ~A1();
39};
40
41template<> A1<char>::~A1();
42
43// PR5529
44namespace PR5529 {
45  struct A {
46    ~A();
47  };
48
49  A::~A() { }
50  struct B : A {
51    virtual ~B();
52  };
53
54  B::~B()  {}
55}
56
57// FIXME: there's a known problem in the codegen here where, if one
58// destructor throws, the remaining destructors aren't run.  Fix it,
59// then make this code check for it.
60namespace test0 {
61  void foo();
62  struct VBase { ~VBase(); };
63  struct Base { ~Base(); };
64  struct Member { ~Member(); };
65
66  struct A : Base {
67    Member M;
68    ~A();
69  };
70
71  // The function-try-block won't suppress -mconstructor-aliases here.
72  A::~A() try { } catch (int i) {}
73
74// complete destructor alias tested above
75
76// CHECK: define void @_ZN5test01AD2Ev
77// CHECK: invoke void @_ZN5test06MemberD1Ev
78// CHECK:   unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]]
79// CHECK: invoke void @_ZN5test04BaseD2Ev
80// CHECK:   unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]]
81
82  struct B : Base, virtual VBase {
83    Member M;
84    ~B();
85  };
86  B::~B() try { } catch (int i) {}
87  // It will suppress the delegation optimization here, though.
88
89// CHECK: define void @_ZN5test01BD1Ev
90// CHECK: invoke void @_ZN5test06MemberD1Ev
91// CHECK:   unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]]
92// CHECK: invoke void @_ZN5test04BaseD2Ev
93// CHECK:   unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]]
94// CHECK: invoke void @_ZN5test05VBaseD2Ev
95// CHECK:   unwind label [[VBASE_UNWIND:%[a-zA-Z0-9.]+]]
96
97// CHECK: define void @_ZN5test01BD2Ev
98// CHECK: invoke void @_ZN5test06MemberD1Ev
99// CHECK:   unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]]
100// CHECK: invoke void @_ZN5test04BaseD2Ev
101// CHECK:   unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]]
102}
103
104// Test base-class aliasing.
105namespace test1 {
106  struct A { ~A(); char ***m; }; // non-trivial destructor
107  struct B { ~B(); }; // non-trivial destructor
108  struct Empty { }; // trivial destructor, empty
109  struct NonEmpty { int x; }; // trivial destructor, non-empty
110
111  // There must be a definition in this translation unit for the alias
112  // optimization to apply.
113  A::~A() { delete m; }
114
115  struct M : A { ~M(); };
116  M::~M() {} // alias tested above
117
118  struct N : A, Empty { ~N(); };
119  N::~N() {} // alias tested above
120
121  struct O : Empty, A { ~O(); };
122  O::~O() {} // alias tested above
123
124  struct P : NonEmpty, A { ~P(); };
125  P::~P() {} // CHECK: define void @_ZN5test11PD2Ev
126
127  struct Q : A, B { ~Q(); };
128  Q::~Q() {} // CHECK: define void @_ZN5test11QD2Ev
129
130  struct R : A { ~R(); };
131  R::~R() { A a; } // CHECK: define void @_ZN5test11RD2Ev
132
133  struct S : A { ~S(); int x; };
134  S::~S() {} // alias tested above
135
136  struct T : A { ~T(); B x; };
137  T::~T() {} // CHECK: define void @_ZN5test11TD2Ev
138
139  // The VTT parameter prevents this.  We could still make this work
140  // for calling conventions that are safe against extra parameters.
141  struct U : A, virtual B { ~U(); };
142  U::~U() {} // CHECK: define void @_ZN5test11UD2Ev
143}
144
145// PR6471
146namespace test2 {
147  struct A { ~A(); char ***m; };
148  struct B : A { ~B(); };
149
150  B::~B() {}
151  // CHECK: define void @_ZN5test21BD2Ev
152  // CHECK: call void @_ZN5test21AD2Ev
153}
154
155// PR7142
156namespace test3 {
157  struct A { virtual ~A(); };
158  struct B { virtual ~B(); };
159  namespace { // internal linkage => deferred
160    struct C : A, B {}; // ~B() in D requires a this-adjustment thunk
161    struct D : C {};    // D::~D() is an alias to C::~C()
162  }
163
164  void test() {
165    new D; // Force emission of D's vtable
166  }
167
168  // Checked at top of file:
169  // @_ZN5test312_GLOBAL__N_11CD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
170
171  // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(
172  // CHECK: call void @_ZN5test31BD2Ev(
173  // CHECK: call void @_ZN5test31AD2Ev(
174  // CHECK: ret void
175
176  // CHECK: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(
177  // CHECK: call void @_ZN5test312_GLOBAL__N_11DD1Ev(
178  // CHECK: call void @_ZdlPv(
179  // CHECK: ret void
180
181  // Checked at top of file:
182  // @_ZN5test312_GLOBAL__N_11DD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11DD2Ev
183  // @_ZN5test312_GLOBAL__N_11DD2Ev = alias internal bitcast {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
184
185  // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD1Ev(
186  // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
187  // CHECK: call void @_ZN5test312_GLOBAL__N_11DD1Ev(
188  // CHECK: ret void
189
190  // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD0Ev(
191  // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
192  // CHECK: call void @_ZN5test312_GLOBAL__N_11DD0Ev(
193  // CHECK: ret void
194
195  // CHECK: declare void @_ZN5test31BD2Ev(
196  // CHECK: declare void @_ZN5test31AD2Ev(
197
198  // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev(
199  // CHECK: call void @_ZN5test312_GLOBAL__N_11CD1Ev(
200  // CHECK: call void @_ZdlPv(
201  // CHECK: ret void
202
203  // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev(
204  // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
205  // CHECK: call void @_ZN5test312_GLOBAL__N_11CD1Ev(
206  // CHECK: ret void
207
208  // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD0Ev(
209  // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
210  // CHECK: call void @_ZN5test312_GLOBAL__N_11CD0Ev(
211  // CHECK: ret void
212}
213