blob: 6e58830c6aef46c9eba3adf56920c3d23fcf86b4 [file] [log] [blame]
Rafael Espindola022301b2012-09-21 20:39:32 +00001// 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 -fhidden-weak-vtables -emit-llvm -o - | FileCheck -check-prefix=HIDDEN %s
Anders Carlssond63fed42010-03-24 00:41:37 +00003
4namespace Test1 {
5
6// Check that we emit a non-virtual thunk for C::f.
7
8struct A {
9 virtual void f();
10};
11
12struct B {
13 virtual void f();
14};
15
16struct C : A, B {
17 virtual void c();
18
19 virtual void f();
20};
21
Anders Carlssonada087c2010-03-27 20:50:27 +000022// CHECK: define void @_ZThn8_N5Test11C1fEv(
Anders Carlssond63fed42010-03-24 00:41:37 +000023void C::f() { }
24
25}
26
27namespace Test2 {
28
29// Check that we emit a thunk for B::f since it's overriding a virtual base.
30
31struct A {
32 virtual void f();
33};
34
35struct B : virtual A {
36 virtual void b();
37 virtual void f();
38};
39
Anders Carlssonada087c2010-03-27 20:50:27 +000040// CHECK: define void @_ZTv0_n24_N5Test21B1fEv(
Anders Carlssond63fed42010-03-24 00:41:37 +000041void B::f() { }
42
43}
44
45namespace Test3 {
46
47// Check that we emit a covariant thunk for B::f.
48
49struct V1 { };
50struct V2 : virtual V1 { };
51
52struct A {
53 virtual V1 *f();
54};
55
56struct B : A {
57 virtual void b();
58
59 virtual V2 *f();
60};
61
Anders Carlssonada087c2010-03-27 20:50:27 +000062// CHECK: define %{{.*}}* @_ZTch0_v0_n24_N5Test31B1fEv(
Anders Carlssond63fed42010-03-24 00:41:37 +000063V2 *B::f() { return 0; }
64
65}
66
67namespace Test4 {
68
69// Check that the thunk for 'C::f' has the same visibility as the function itself.
70
71struct A {
72 virtual void f();
73};
74
75struct B {
76 virtual void f();
77};
78
79struct __attribute__((visibility("protected"))) C : A, B {
80 virtual void c();
81
82 virtual void f();
83};
84
Anders Carlssonada087c2010-03-27 20:50:27 +000085// CHECK: define protected void @_ZThn8_N5Test41C1fEv(
Anders Carlssond63fed42010-03-24 00:41:37 +000086void C::f() { }
87
88}
89
90// Check that the thunk gets internal linkage.
John McCall15e310a2011-02-19 02:53:41 +000091namespace Test4B {
92 struct A {
93 virtual void f();
94 };
Anders Carlssond63fed42010-03-24 00:41:37 +000095
John McCall15e310a2011-02-19 02:53:41 +000096 struct B {
97 virtual void f();
98 };
Anders Carlssond63fed42010-03-24 00:41:37 +000099
John McCall15e310a2011-02-19 02:53:41 +0000100 namespace {
101 struct C : A, B {
102 virtual void c();
103 virtual void f();
104 };
105 }
106 void C::c() {}
107 void C::f() {}
Anders Carlssond63fed42010-03-24 00:41:37 +0000108
John McCall15e310a2011-02-19 02:53:41 +0000109 // Force C::f to be used.
110 void f() {
111 C c;
112 c.f();
113 }
Anders Carlssond63fed42010-03-24 00:41:37 +0000114}
Anders Carlssonada087c2010-03-27 20:50:27 +0000115
116namespace Test5 {
117
118// Check that the thunk for 'B::f' gets the same linkage as the function itself.
119struct A {
120 virtual void f();
121};
122
123struct B : virtual A {
124 virtual void f() { }
125};
126
127void f(B b) {
128 b.f();
129}
130}
131
Douglas Gregorcb359df2010-05-20 05:54:35 +0000132namespace Test6 {
133 struct X {
134 X();
135 X(const X&);
136 X &operator=(const X&);
137 ~X();
138 };
Anders Carlssonada087c2010-03-27 20:50:27 +0000139
Douglas Gregorcb359df2010-05-20 05:54:35 +0000140 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
Douglas Gregor663218b2010-05-21 17:55:12 +0000175namespace 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
John McCall27360712010-05-26 22:34:26 +0000220namespace 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
John McCalle2132352010-06-02 21:22:02 +0000236// PR7241: Emitting thunks for a method shouldn't require the vtable for
237// that class to be emitted.
238namespace 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
John McCall65005532010-08-04 23:46:35 +0000248namespace Test10 {
249 struct A { virtual void foo(); };
250 struct B { virtual void foo(); };
251 struct C : A, B { void foo() {} };
252
John McCall279b5eb2010-08-12 23:36:15 +0000253 // CHECK-HIDDEN: define linkonce_odr void @_ZN6Test101C3fooEv
254 // CHECK-HIDDEN: define linkonce_odr hidden void @_ZThn8_N6Test101C3fooEv
John McCall65005532010-08-04 23:46:35 +0000255
256 void test() {
257 C c;
258 }
259}
260
John McCall4e3b17c2010-11-09 01:18:05 +0000261// PR7611
262namespace 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
Eli Friedman7dcdf5b2011-05-06 17:27:27 +0000268 // C::f itself.
269 // CHECK: define {{.*}} @_ZN6Test111C1fEv(
270
John McCall4e3b17c2010-11-09 01:18:05 +0000271 // 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
John McCall4e3b17c2010-11-09 01:18:05 +0000275 // 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
Eli Friedman7dcdf5b2011-05-06 17:27:27 +0000280// Varargs thunk test.
281namespace 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
Eli Friedman82bad6b2012-09-14 01:45:09 +0000304// PR13832
305namespace Test13 {
306 struct B1 {
307 virtual B1 &foo1();
308 };
309 struct Pad1 {
310 virtual ~Pad1();
311 };
312 struct Proxy1 : Pad1, B1 {
313 virtual ~Proxy1();
314 };
315 struct D : virtual Proxy1 {
316 virtual ~D();
317 virtual D &foo1();
318 };
319 D& D::foo1() {
320 return *this;
321 }
322 // CHECK: define {{.*}} @_ZTcvn8_n32_v8_n24_N6Test131D4foo1Ev
323 // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
324 // CHECK: getelementptr inbounds i8* {{.*}}, i64 -32
325 // CHECK: getelementptr inbounds i8* {{.*}}, i64 -24
326 // CHECK: getelementptr inbounds i8* {{.*}}, i64 8
327 // CHECK: ret %"struct.Test13::D"*
328}
329
Rafael Espindola022301b2012-09-21 20:39:32 +0000330namespace Test14 {
331 class A {
332 virtual void f();
333 };
334 class B {
335 virtual void f();
336 };
337 class C : public A, public B {
338 virtual void f();
339 };
340 void C::f() {
341 }
Bill Wendling89924572013-02-27 00:06:04 +0000342 // CHECK: define void @_ZThn8_N6Test141C1fEv({{.*}}) unnamed_addr [[NUW:#[0-9]+]]
Rafael Espindola022301b2012-09-21 20:39:32 +0000343}
344
John McCall27360712010-05-26 22:34:26 +0000345/**** The following has to go at the end of the file ****/
346
Douglas Gregorcb359df2010-05-20 05:54:35 +0000347// This is from Test5:
John McCall279b5eb2010-08-12 23:36:15 +0000348// CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
John McCall15e310a2011-02-19 02:53:41 +0000349// CHECK: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
Bill Wendlingf7a9da02013-02-20 07:22:19 +0000350
Bill Wendling89924572013-02-27 00:06:04 +0000351// CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} }