blob: 5ab0346b0b686900d6ea774e528d7b5ebe94da0a [file] [log] [blame]
John McCallc76702c2010-05-27 01:45:30 +00001// RUN: %clang_cc1 %s -emit-llvm -o - -mconstructor-aliases -fexceptions | FileCheck %s
John McCallc0bf4622010-02-23 00:48:20 +00002
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
John McCallc76702c2010-05-27 01:45:30 +00009// 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
Anders Carlsson174754c2009-09-01 18:33:46 +000013struct 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
Douglas Gregor45132722009-10-01 20:44:19 +000033C::~C() { }
34
35// PR5084
36template<typename T>
37class A1 {
38 ~A1();
39};
40
41template<> A1<char>::~A1();
Anders Carlsson9f853df2009-11-17 04:44:12 +000042
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}
John McCall9fc6a772010-02-19 09:25:03 +000056
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
John McCallc0bf4622010-02-23 00:48:20 +000074// complete destructor alias tested above
John McCall9fc6a772010-02-19 09:25:03 +000075
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}
John McCallc0bf4622010-02-23 00:48:20 +0000103
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
John McCall9a708462010-03-03 03:40:11 +0000111 // There must be a definition in this translation unit for the alias
112 // optimization to apply.
113 A::~A() { delete m; }
114
John McCallc0bf4622010-02-23 00:48:20 +0000115 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}
John McCall9a708462010-03-03 03:40:11 +0000144
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}
John McCallc76702c2010-05-27 01:45:30 +0000154
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}