1 // RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t
2 // RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t.opt -O1 -disable-llvm-optzns
3 // RUN: FileCheck %s < %t
4 // RUN: FileCheck %s < %t.opt
5 // RUN: FileCheck --check-prefix=CHECK-NONOPT %s < %t
6 // RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt
7
8 namespace Test1 {
9
10 // Check that we emit a non-virtual thunk for C::f.
11
12 struct A {
13 virtual void f();
14 };
15
16 struct B {
17 virtual void f();
18 };
19
20 struct C : A, B {
21 virtual void c();
22
23 virtual void f();
24 };
25
26 // CHECK-LABEL: define void @_ZThn8_N5Test11C1fEv(
f()27 void C::f() { }
28
29 }
30
31 namespace Test2 {
32
33 // Check that we emit a thunk for B::f since it's overriding a virtual base.
34
35 struct A {
36 virtual void f();
37 };
38
39 struct B : virtual A {
40 virtual void b();
41 virtual void f();
42 };
43
44 // CHECK-LABEL: define void @_ZTv0_n24_N5Test21B1fEv(
f()45 void B::f() { }
46
47 }
48
49 namespace Test3 {
50
51 // Check that we emit a covariant thunk for B::f.
52
53 struct V1 { };
54 struct V2 : virtual V1 { };
55
56 struct A {
57 virtual V1 *f();
58 };
59
60 struct B : A {
61 virtual void b();
62
63 virtual V2 *f();
64 };
65
66 // CHECK: define %{{.*}}* @_ZTch0_v0_n24_N5Test31B1fEv(
f()67 V2 *B::f() { return 0; }
68
69 }
70
71 namespace Test4 {
72
73 // Check that the thunk for 'C::f' has the same visibility as the function itself.
74
75 struct A {
76 virtual void f();
77 };
78
79 struct B {
80 virtual void f();
81 };
82
83 struct __attribute__((visibility("protected"))) C : A, B {
84 virtual void c();
85
86 virtual void f();
87 };
88
89 // CHECK-LABEL: define protected void @_ZThn8_N5Test41C1fEv(
f()90 void C::f() { }
91
92 }
93
94 // Check that the thunk gets internal linkage.
95 namespace Test4B {
96 struct A {
97 virtual void f();
98 };
99
100 struct B {
101 virtual void f();
102 };
103
104 namespace {
105 struct C : A, B {
106 virtual void c();
107 virtual void f();
108 };
109 }
c()110 void C::c() {}
f()111 void C::f() {}
112
113 // Force C::f to be used.
f()114 void f() {
115 C c;
116 c.f();
117 }
118 }
119
120 namespace Test5 {
121
122 // Check that the thunk for 'B::f' gets the same linkage as the function itself.
123 struct A {
124 virtual void f();
125 };
126
127 struct B : virtual A {
fTest5::B128 virtual void f() { }
129 };
130
f(B b)131 void f(B b) {
132 b.f();
133 }
134 }
135
136 namespace Test6 {
137 struct X {
138 X();
139 X(const X&);
140 X &operator=(const X&);
141 ~X();
142 };
143
144 struct P {
145 P();
146 P(const P&);
147 ~P();
148 X first;
149 X second;
150 };
151
152 P getP();
153
154 struct Base1 {
155 int i;
156
fTest6::Base1157 virtual X f() { return X(); }
158 };
159
160 struct Base2 {
161 float real;
162
fTest6::Base2163 virtual X f() { return X(); }
164 };
165
166 struct Thunks : Base1, Base2 {
167 long l;
168
169 virtual X f();
170 };
171
172 // CHECK-LABEL: define void @_ZThn16_N5Test66Thunks1fEv
173 // CHECK-NOT: memcpy
174 // CHECK: {{call void @_ZN5Test66Thunks1fEv.*sret}}
175 // CHECK: ret void
f()176 X Thunks::f() { return X(); }
177 }
178
179 namespace Test7 {
180 // PR7188
181 struct X {
182 X();
183 X(const X&);
184 X &operator=(const X&);
185 ~X();
186 };
187
188 struct Small { short s; };
189 struct Large {
190 char array[1024];
191 };
192
193 class A {
194 protected:
195 virtual void foo() = 0;
196 };
197
198 class B : public A {
199 protected:
200 virtual void bar() = 0;
201 };
202
203 class C : public A {
204 protected:
205 virtual void baz(X, X&, _Complex float, Small, Small&, Large) = 0;
206 };
207
208 class D : public B,
209 public C {
210
foo()211 void foo() {}
bar()212 void bar() {}
213 void baz(X, X&, _Complex float, Small, Small&, Large);
214 };
215
baz(X,X &,_Complex float,Small,Small &,Large)216 void D::baz(X, X&, _Complex float, Small, Small&, Large) { }
217
218 // CHECK-LABEL: define void @_ZThn8_N5Test71D3bazENS_1XERS1_CfNS_5SmallERS4_NS_5LargeE(
219 // CHECK-NOT: memcpy
220 // CHECK: ret void
testD()221 void testD() { D d; }
222 }
223
224 namespace Test8 {
225 struct NonPOD { ~NonPOD(); int x, y, z; };
226 struct A { virtual void foo(); };
227 struct B { virtual void bar(NonPOD); };
228 struct C : A, B { virtual void bar(NonPOD); static void helper(NonPOD); };
229
230 // CHECK: define void @_ZN5Test81C6helperENS_6NonPODE([[NONPODTYPE:%.*]]*
helper(NonPOD var)231 void C::helper(NonPOD var) {}
232
233 // CHECK-LABEL: define void @_ZThn8_N5Test81C3barENS_6NonPODE(
234 // CHECK-NOT: load [[NONPODTYPE]], [[NONPODTYPE]]*
235 // CHECK-NOT: memcpy
236 // CHECK: ret void
bar(NonPOD var)237 void C::bar(NonPOD var) {}
238 }
239
240 // PR7241: Emitting thunks for a method shouldn't require the vtable for
241 // that class to be emitted.
242 namespace Test9 {
~ATest9::A243 struct A { virtual ~A() { } };
testTest9::B244 struct B : A { virtual void test() const {} };
245 struct C : B { C(); ~C(); };
DTest9::D246 struct D : C { D() {} };
test()247 void test() {
248 D d;
249 }
250 }
251
252 namespace Test10 {
253 struct A { virtual void foo(); };
254 struct B { virtual void foo(); };
fooTest10::C255 struct C : A, B { void foo() {} };
256
257 // Test later.
test()258 void test() {
259 C c;
260 }
261 }
262
263 // PR7611
264 namespace Test11 {
265 struct A { virtual A* f(); };
266 struct B : virtual A { virtual A* f(); };
267 struct C : B { virtual C* f(); };
f()268 C* C::f() { return 0; }
269
270 // C::f itself.
271 // CHECK: define {{.*}} @_ZN6Test111C1fEv(
272
273 // The this-adjustment and return-adjustment thunk required when
274 // C::f appears in a vtable where A is at a nonzero offset from C.
275 // CHECK: define {{.*}} @_ZTcv0_n24_v0_n32_N6Test111C1fEv(
276
277 // The return-adjustment thunk required when C::f appears in a vtable
278 // where A is at a zero offset from C.
279 // CHECK: define {{.*}} @_ZTch0_v0_n32_N6Test111C1fEv(
280 }
281
282 // Varargs thunk test.
283 namespace Test12 {
284 struct A {
285 virtual A* f(int x, ...);
286 };
287 struct B {
288 virtual B* f(int x, ...);
289 };
290 struct C : A, B {
291 virtual void c();
292 virtual C* f(int x, ...);
293 };
f(int x,...)294 C* C::f(int x, ...) { return this; }
295
296 // C::f
297 // CHECK: define {{.*}} @_ZN6Test121C1fEiz
298
299 // Varargs thunk; check that both the this and covariant adjustments
300 // are generated.
301 // CHECK: define {{.*}} @_ZTchn8_h8_N6Test121C1fEiz
302 // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -8
303 // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 8
304 }
305
306 // PR13832
307 namespace Test13 {
308 struct B1 {
309 virtual B1 &foo1();
310 };
311 struct Pad1 {
312 virtual ~Pad1();
313 };
314 struct Proxy1 : Pad1, B1 {
315 virtual ~Proxy1();
316 };
317 struct D : virtual Proxy1 {
318 virtual ~D();
319 virtual D &foo1();
320 };
foo1()321 D& D::foo1() {
322 return *this;
323 }
324 // CHECK: define {{.*}} @_ZTcvn8_n32_v8_n24_N6Test131D4foo1Ev
325 // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -8
326 // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -32
327 // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -24
328 // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 8
329 // CHECK: ret %"struct.Test13::D"*
330 }
331
332 namespace Test14 {
333 class A {
334 virtual void f();
335 };
336 class B {
337 virtual void f();
338 };
339 class C : public A, public B {
340 virtual void f();
341 };
f()342 void C::f() {
343 }
344 // CHECK: define void @_ZThn8_N6Test141C1fEv({{.*}}) unnamed_addr [[NUW:#[0-9]+]]
345 }
346
347 // Varargs non-covariant thunk test.
348 // PR18098
349 namespace Test15 {
350 struct A {
351 virtual ~A();
352 };
353 struct B {
354 virtual void f(int x, ...);
355 };
356 struct C : A, B {
357 virtual void c();
358 virtual void f(int x, ...);
359 };
c()360 void C::c() {}
361
362 // C::c
363 // CHECK: declare void @_ZN6Test151C1fEiz
364 // non-virtual thunk to C::f
365 // CHECK: declare void @_ZThn8_N6Test151C1fEiz
366 }
367
368 namespace Test16 {
369 struct A {
370 virtual ~A();
371 };
372 struct B {
373 virtual void foo();
374 };
375 struct C : public A, public B {
fooTest16::C376 void foo() {}
377 };
378 struct D : public C {
379 ~D();
380 };
~D()381 D::~D() {}
382 // CHECK: define linkonce_odr void @_ZThn8_N6Test161C3fooEv({{.*}}) {{.*}} comdat
383 }
384
385 /**** The following has to go at the end of the file ****/
386
387 // checking without opt
388 // CHECK-NONOPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
389 // CHECK-NONOPT-NOT: comdat
390
391 // This is from Test5:
392 // CHECK-NONOPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
393
394 // This is from Test10:
395 // CHECK-NONOPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
396 // CHECK-NONOPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
397
398 // Checking with opt
399 // CHECK-OPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(%"struct.Test4B::(anonymous namespace)::C"* %this) unnamed_addr #0 align 2
400
401 // This is from Test5:
402 // CHECK-OPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
403
404 // This is from Test10:
405 // CHECK-OPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
406 // CHECK-OPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
407
408 // CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} }
409