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