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