]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/CodeGenCXX/thunks.cpp
Vendor import of clang trunk r238337:
[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
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(
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(
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(
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(
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   }
106   void C::c() {}
107   void C::f() {}
108
109   // Force C::f to be used.
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 {
124   virtual void f() { }
125 };
126
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
153     virtual X f() { return X(); }
154   };
155
156   struct Base2 {
157     float real;
158
159     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
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
207     void foo() {}
208     void bar() {}
209     void baz(X, X&, _Complex float, Small, Small&, Large);
210   };
211
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
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:%.*]]*
227   void C::helper(NonPOD var) {}
228
229   // CHECK-LABEL: define void @_ZThn8_N5Test81C3barENS_6NonPODE(
230   // CHECK-NOT: load [[NONPODTYPE]], [[NONPODTYPE]]*
231   // CHECK-NOT: memcpy
232   // CHECK: ret void
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 {
239   struct A { virtual ~A() { } };
240   struct B : A { virtual void test() const {} };
241   struct C : B { C(); ~C(); };
242   struct D : C { D() {} };
243   void test() {
244     D d;
245   }
246 }
247
248 namespace Test10 {
249   struct A { virtual void foo(); };
250   struct B { virtual void foo(); };
251   struct C : A, B { void foo() {} };
252
253   // Test later.
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(); };
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   };
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, i8* {{.*}}, i64 -8
299   // CHECK: getelementptr inbounds i8, 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   };
317   D& D::foo1() {
318     return *this;
319   }
320   // CHECK: define {{.*}} @_ZTcvn8_n32_v8_n24_N6Test131D4foo1Ev
321   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -8
322   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -32
323   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -24
324   // CHECK: getelementptr inbounds i8, 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   };
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   };
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 Test5:
367 // CHECK-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
368 // CHECK-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
369
370 // This is from Test10:
371 // CHECK-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
372 // CHECK-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
373
374 // CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} }