blob: 3a598b90afe13612d0edd387771afd20985b50cd [file] [log] [blame]
Pirama Arumuga Nainar87d948e2016-03-03 15:49:35 -08001// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t
2// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t.opt -O1 -disable-llvm-optzns
3// RUN: FileCheck %s < %t
4// RUN: FileCheck %s < %t.opt
5// RUN: FileCheck --check-prefix=CHECK-NONOPT %s < %t
6// RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt
Anders Carlssond63fed42010-03-24 00:41:37 +00007
8namespace Test1 {
9
10// Check that we emit a non-virtual thunk for C::f.
11
12struct A {
13 virtual void f();
14};
15
16struct B {
17 virtual void f();
18};
19
20struct C : A, B {
21 virtual void c();
22
23 virtual void f();
24};
25
Stephen Lin93ab6bf2013-08-15 06:47:53 +000026// CHECK-LABEL: define void @_ZThn8_N5Test11C1fEv(
Anders Carlssond63fed42010-03-24 00:41:37 +000027void C::f() { }
28
29}
30
31namespace Test2 {
32
33// Check that we emit a thunk for B::f since it's overriding a virtual base.
34
35struct A {
36 virtual void f();
37};
38
39struct B : virtual A {
40 virtual void b();
41 virtual void f();
42};
43
Stephen Lin93ab6bf2013-08-15 06:47:53 +000044// CHECK-LABEL: define void @_ZTv0_n24_N5Test21B1fEv(
Anders Carlssond63fed42010-03-24 00:41:37 +000045void B::f() { }
46
47}
48
49namespace Test3 {
50
51// Check that we emit a covariant thunk for B::f.
52
53struct V1 { };
54struct V2 : virtual V1 { };
55
56struct A {
57 virtual V1 *f();
58};
59
60struct B : A {
61 virtual void b();
62
63 virtual V2 *f();
64};
65
Anders Carlssonada087c2010-03-27 20:50:27 +000066// CHECK: define %{{.*}}* @_ZTch0_v0_n24_N5Test31B1fEv(
Anders Carlssond63fed42010-03-24 00:41:37 +000067V2 *B::f() { return 0; }
68
69}
70
71namespace Test4 {
72
73// Check that the thunk for 'C::f' has the same visibility as the function itself.
74
75struct A {
76 virtual void f();
77};
78
79struct B {
80 virtual void f();
81};
82
83struct __attribute__((visibility("protected"))) C : A, B {
84 virtual void c();
85
86 virtual void f();
87};
88
Stephen Lin93ab6bf2013-08-15 06:47:53 +000089// CHECK-LABEL: define protected void @_ZThn8_N5Test41C1fEv(
Anders Carlssond63fed42010-03-24 00:41:37 +000090void C::f() { }
91
92}
93
94// Check that the thunk gets internal linkage.
John McCall15e310a2011-02-19 02:53:41 +000095namespace Test4B {
96 struct A {
97 virtual void f();
98 };
Anders Carlssond63fed42010-03-24 00:41:37 +000099
John McCall15e310a2011-02-19 02:53:41 +0000100 struct B {
101 virtual void f();
102 };
Anders Carlssond63fed42010-03-24 00:41:37 +0000103
John McCall15e310a2011-02-19 02:53:41 +0000104 namespace {
105 struct C : A, B {
106 virtual void c();
107 virtual void f();
108 };
109 }
110 void C::c() {}
111 void C::f() {}
Anders Carlssond63fed42010-03-24 00:41:37 +0000112
John McCall15e310a2011-02-19 02:53:41 +0000113 // Force C::f to be used.
114 void f() {
115 C c;
116 c.f();
117 }
Anders Carlssond63fed42010-03-24 00:41:37 +0000118}
Anders Carlssonada087c2010-03-27 20:50:27 +0000119
120namespace Test5 {
121
122// Check that the thunk for 'B::f' gets the same linkage as the function itself.
123struct A {
124 virtual void f();
125};
126
127struct B : virtual A {
128 virtual void f() { }
129};
130
131void f(B b) {
132 b.f();
133}
134}
135
Douglas Gregorcb359df2010-05-20 05:54:35 +0000136namespace Test6 {
137 struct X {
138 X();
139 X(const X&);
140 X &operator=(const X&);
141 ~X();
142 };
Anders Carlssonada087c2010-03-27 20:50:27 +0000143
Douglas Gregorcb359df2010-05-20 05:54:35 +0000144 struct P {
145 P();
146 P(const P&);
147 ~P();
148 X first;
149 X second;
150 };
151
152 P getP();
153
154 struct Base1 {
155 int i;
156
157 virtual X f() { return X(); }
158 };
159
160 struct Base2 {
161 float real;
162
163 virtual X f() { return X(); }
164 };
165
166 struct Thunks : Base1, Base2 {
167 long l;
168
169 virtual X f();
170 };
171
Stephen Lin93ab6bf2013-08-15 06:47:53 +0000172 // CHECK-LABEL: define void @_ZThn16_N5Test66Thunks1fEv
Douglas Gregorcb359df2010-05-20 05:54:35 +0000173 // CHECK-NOT: memcpy
174 // CHECK: {{call void @_ZN5Test66Thunks1fEv.*sret}}
175 // CHECK: ret void
176 X Thunks::f() { return X(); }
177}
178
Douglas Gregor663218b2010-05-21 17:55:12 +0000179namespace Test7 {
180 // PR7188
181 struct X {
182 X();
183 X(const X&);
184 X &operator=(const X&);
185 ~X();
186 };
187
188 struct Small { short s; };
189 struct Large {
190 char array[1024];
191 };
192
193 class A {
194 protected:
195 virtual void foo() = 0;
196 };
197
198 class B : public A {
199 protected:
200 virtual void bar() = 0;
201 };
202
203 class C : public A {
204 protected:
205 virtual void baz(X, X&, _Complex float, Small, Small&, Large) = 0;
206 };
207
208 class D : public B,
209 public C {
210
211 void foo() {}
212 void bar() {}
213 void baz(X, X&, _Complex float, Small, Small&, Large);
214 };
215
216 void D::baz(X, X&, _Complex float, Small, Small&, Large) { }
217
Stephen Lin93ab6bf2013-08-15 06:47:53 +0000218 // CHECK-LABEL: define void @_ZThn8_N5Test71D3bazENS_1XERS1_CfNS_5SmallERS4_NS_5LargeE(
Douglas Gregor663218b2010-05-21 17:55:12 +0000219 // CHECK-NOT: memcpy
220 // CHECK: ret void
221 void testD() { D d; }
222}
223
John McCall27360712010-05-26 22:34:26 +0000224namespace Test8 {
225 struct NonPOD { ~NonPOD(); int x, y, z; };
226 struct A { virtual void foo(); };
227 struct B { virtual void bar(NonPOD); };
228 struct C : A, B { virtual void bar(NonPOD); static void helper(NonPOD); };
229
230 // CHECK: define void @_ZN5Test81C6helperENS_6NonPODE([[NONPODTYPE:%.*]]*
231 void C::helper(NonPOD var) {}
232
Stephen Lin93ab6bf2013-08-15 06:47:53 +0000233 // CHECK-LABEL: define void @_ZThn8_N5Test81C3barENS_6NonPODE(
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -0700234 // CHECK-NOT: load [[NONPODTYPE]], [[NONPODTYPE]]*
John McCall27360712010-05-26 22:34:26 +0000235 // CHECK-NOT: memcpy
236 // CHECK: ret void
237 void C::bar(NonPOD var) {}
238}
239
John McCalle2132352010-06-02 21:22:02 +0000240// PR7241: Emitting thunks for a method shouldn't require the vtable for
241// that class to be emitted.
242namespace Test9 {
243 struct A { virtual ~A() { } };
244 struct B : A { virtual void test() const {} };
245 struct C : B { C(); ~C(); };
246 struct D : C { D() {} };
247 void test() {
248 D d;
249 }
250}
251
John McCall65005532010-08-04 23:46:35 +0000252namespace Test10 {
253 struct A { virtual void foo(); };
254 struct B { virtual void foo(); };
255 struct C : A, B { void foo() {} };
256
Stephen Hines651f13c2014-04-23 16:59:28 -0700257 // Test later.
John McCall65005532010-08-04 23:46:35 +0000258 void test() {
259 C c;
260 }
261}
262
John McCall4e3b17c2010-11-09 01:18:05 +0000263// PR7611
264namespace Test11 {
265 struct A { virtual A* f(); };
266 struct B : virtual A { virtual A* f(); };
267 struct C : B { virtual C* f(); };
268 C* C::f() { return 0; }
269
Eli Friedman7dcdf5b2011-05-06 17:27:27 +0000270 // C::f itself.
271 // CHECK: define {{.*}} @_ZN6Test111C1fEv(
272
John McCall4e3b17c2010-11-09 01:18:05 +0000273 // The this-adjustment and return-adjustment thunk required when
274 // C::f appears in a vtable where A is at a nonzero offset from C.
275 // CHECK: define {{.*}} @_ZTcv0_n24_v0_n32_N6Test111C1fEv(
276
John McCall4e3b17c2010-11-09 01:18:05 +0000277 // The return-adjustment thunk required when C::f appears in a vtable
278 // where A is at a zero offset from C.
279 // CHECK: define {{.*}} @_ZTch0_v0_n32_N6Test111C1fEv(
280}
281
Eli Friedman7dcdf5b2011-05-06 17:27:27 +0000282// Varargs thunk test.
283namespace Test12 {
284 struct A {
285 virtual A* f(int x, ...);
286 };
287 struct B {
288 virtual B* f(int x, ...);
289 };
290 struct C : A, B {
291 virtual void c();
292 virtual C* f(int x, ...);
293 };
294 C* C::f(int x, ...) { return this; }
295
296 // C::f
297 // CHECK: define {{.*}} @_ZN6Test121C1fEiz
298
299 // Varargs thunk; check that both the this and covariant adjustments
300 // are generated.
301 // CHECK: define {{.*}} @_ZTchn8_h8_N6Test121C1fEiz
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -0700302 // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -8
303 // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 8
Eli Friedman7dcdf5b2011-05-06 17:27:27 +0000304}
305
Eli Friedman82bad6b2012-09-14 01:45:09 +0000306// PR13832
307namespace Test13 {
308 struct B1 {
309 virtual B1 &foo1();
310 };
311 struct Pad1 {
312 virtual ~Pad1();
313 };
314 struct Proxy1 : Pad1, B1 {
315 virtual ~Proxy1();
316 };
317 struct D : virtual Proxy1 {
318 virtual ~D();
319 virtual D &foo1();
320 };
321 D& D::foo1() {
322 return *this;
323 }
324 // CHECK: define {{.*}} @_ZTcvn8_n32_v8_n24_N6Test131D4foo1Ev
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -0700325 // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -8
326 // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -32
327 // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -24
328 // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 8
Eli Friedman82bad6b2012-09-14 01:45:09 +0000329 // CHECK: ret %"struct.Test13::D"*
330}
331
Rafael Espindola022301b2012-09-21 20:39:32 +0000332namespace Test14 {
333 class A {
334 virtual void f();
335 };
336 class B {
337 virtual void f();
338 };
339 class C : public A, public B {
340 virtual void f();
341 };
342 void C::f() {
343 }
Bill Wendling89924572013-02-27 00:06:04 +0000344 // CHECK: define void @_ZThn8_N6Test141C1fEv({{.*}}) unnamed_addr [[NUW:#[0-9]+]]
Rafael Espindola022301b2012-09-21 20:39:32 +0000345}
346
Bill Wendling8e3eec52013-12-07 21:19:02 +0000347// Varargs non-covariant thunk test.
348// PR18098
349namespace Test15 {
350 struct A {
351 virtual ~A();
352 };
353 struct B {
354 virtual void f(int x, ...);
355 };
356 struct C : A, B {
357 virtual void c();
358 virtual void f(int x, ...);
359 };
360 void C::c() {}
361
362 // C::c
363 // CHECK: declare void @_ZN6Test151C1fEiz
364 // non-virtual thunk to C::f
365 // CHECK: declare void @_ZThn8_N6Test151C1fEiz
366}
367
Pirama Arumuga Nainar87d948e2016-03-03 15:49:35 -0800368namespace Test16 {
369struct A {
370 virtual ~A();
371};
372struct B {
373 virtual void foo();
374};
375struct C : public A, public B {
376 void foo() {}
377};
378struct D : public C {
379 ~D();
380};
381D::~D() {}
382// CHECK: define linkonce_odr void @_ZThn8_N6Test161C3fooEv({{.*}}) {{.*}} comdat
383}
384
John McCall27360712010-05-26 22:34:26 +0000385/**** The following has to go at the end of the file ****/
386
Pirama Arumuga Nainar87d948e2016-03-03 15:49:35 -0800387// checking without opt
388// CHECK-NONOPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
389// CHECK-NONOPT-NOT: comdat
390
Stephen Hines0e2c34f2015-03-23 12:09:02 -0700391// This is from Test5:
Pirama Arumuga Nainar87d948e2016-03-03 15:49:35 -0800392// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
Stephen Hines0e2c34f2015-03-23 12:09:02 -0700393
Stephen Hines651f13c2014-04-23 16:59:28 -0700394// This is from Test10:
Pirama Arumuga Nainar87d948e2016-03-03 15:49:35 -0800395// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
396// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
397
398// Checking with opt
399// CHECK-OPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(%"struct.Test4B::(anonymous namespace)::C"* %this) unnamed_addr #0 align 2
400
401// This is from Test5:
402// CHECK-OPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
403
404// This is from Test10:
405// CHECK-OPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
406// CHECK-OPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
Stephen Hines651f13c2014-04-23 16:59:28 -0700407
Bill Wendling89924572013-02-27 00:06:04 +0000408// CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} }