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