]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/CodeGenCXX/thunks.cpp
Vendor import of clang trunk r132879:
[FreeBSD/FreeBSD.git] / test / CodeGenCXX / thunks.cpp
1 // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
2 // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o - | FileCheck -check-prefix=HIDDEN %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: 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: 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: 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: 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: 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: define void @_ZThn8_N5Test81C3barENS_6NonPODE(
230   // CHECK-NOT: load [[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   // CHECK-HIDDEN: define linkonce_odr void @_ZN6Test101C3fooEv
254   // CHECK-HIDDEN: define linkonce_odr hidden void @_ZThn8_N6Test101C3fooEv
255
256   void test() {
257     C c;
258   }
259 }
260
261 // PR7611
262 namespace Test11 {
263   struct A {             virtual A* f(); };
264   struct B : virtual A { virtual A* f(); };
265   struct C : B         { virtual C* f(); };
266   C* C::f() { return 0; }
267
268   //  C::f itself.
269   // CHECK: define {{.*}} @_ZN6Test111C1fEv(
270
271   //  The this-adjustment and return-adjustment thunk required when
272   //  C::f appears in a vtable where A is at a nonzero offset from C.
273   // CHECK: define {{.*}} @_ZTcv0_n24_v0_n32_N6Test111C1fEv(
274
275   //  The return-adjustment thunk required when C::f appears in a vtable
276   //  where A is at a zero offset from C.
277   // CHECK: define {{.*}} @_ZTch0_v0_n32_N6Test111C1fEv(
278 }
279
280 // Varargs thunk test.
281 namespace Test12 {
282   struct A {
283     virtual A* f(int x, ...);
284   };
285   struct B {
286     virtual B* f(int x, ...);
287   };
288   struct C : A, B {
289     virtual void c();
290     virtual C* f(int x, ...);
291   };
292   C* C::f(int x, ...) { return this; }
293
294   // C::f
295   // CHECK: define {{.*}} @_ZN6Test121C1fEiz
296
297   // Varargs thunk; check that both the this and covariant adjustments
298   // are generated.
299   // CHECK: define {{.*}} @_ZTchn8_h8_N6Test121C1fEiz
300   // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
301   // CHECK: getelementptr inbounds i8* {{.*}}, i64 8
302 }
303
304 /**** The following has to go at the end of the file ****/
305
306 // This is from Test5:
307 // CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
308 // CHECK: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(