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