blob: ba60385ab6f33fc0f2d1b3f96a427d8963d5d42b [file] [log] [blame]
Anders Carlssond63fed42010-03-24 00:41:37 +00001// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
John McCall279b5eb2010-08-12 23:36:15 +00002// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -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.
91namespace {
92
93struct A {
94 virtual void f();
95};
96
97struct B {
98 virtual void f();
99};
100
101struct C : A, B {
102 virtual void c();
103
104 virtual void f();
105};
106
Anders Carlssond63fed42010-03-24 00:41:37 +0000107void C::f() { }
108
109}
110
111// Force C::f to be used.
112void f() {
113 C c;
114
115 c.f();
116}
Anders Carlssonada087c2010-03-27 20:50:27 +0000117
118namespace Test5 {
119
120// Check that the thunk for 'B::f' gets the same linkage as the function itself.
121struct A {
122 virtual void f();
123};
124
125struct B : virtual A {
126 virtual void f() { }
127};
128
129void f(B b) {
130 b.f();
131}
132}
133
Douglas Gregorcb359df2010-05-20 05:54:35 +0000134namespace Test6 {
135 struct X {
136 X();
137 X(const X&);
138 X &operator=(const X&);
139 ~X();
140 };
Anders Carlssonada087c2010-03-27 20:50:27 +0000141
Douglas Gregorcb359df2010-05-20 05:54:35 +0000142 struct P {
143 P();
144 P(const P&);
145 ~P();
146 X first;
147 X second;
148 };
149
150 P getP();
151
152 struct Base1 {
153 int i;
154
155 virtual X f() { return X(); }
156 };
157
158 struct Base2 {
159 float real;
160
161 virtual X f() { return X(); }
162 };
163
164 struct Thunks : Base1, Base2 {
165 long l;
166
167 virtual X f();
168 };
169
170 // CHECK: define void @_ZThn16_N5Test66Thunks1fEv
171 // CHECK-NOT: memcpy
172 // CHECK: {{call void @_ZN5Test66Thunks1fEv.*sret}}
173 // CHECK: ret void
174 X Thunks::f() { return X(); }
175}
176
Douglas Gregor663218b2010-05-21 17:55:12 +0000177namespace Test7 {
178 // PR7188
179 struct X {
180 X();
181 X(const X&);
182 X &operator=(const X&);
183 ~X();
184 };
185
186 struct Small { short s; };
187 struct Large {
188 char array[1024];
189 };
190
191 class A {
192 protected:
193 virtual void foo() = 0;
194 };
195
196 class B : public A {
197 protected:
198 virtual void bar() = 0;
199 };
200
201 class C : public A {
202 protected:
203 virtual void baz(X, X&, _Complex float, Small, Small&, Large) = 0;
204 };
205
206 class D : public B,
207 public C {
208
209 void foo() {}
210 void bar() {}
211 void baz(X, X&, _Complex float, Small, Small&, Large);
212 };
213
214 void D::baz(X, X&, _Complex float, Small, Small&, Large) { }
215
216 // CHECK: define void @_ZThn8_N5Test71D3bazENS_1XERS1_CfNS_5SmallERS4_NS_5LargeE(
217 // CHECK-NOT: memcpy
218 // CHECK: ret void
219 void testD() { D d; }
220}
221
John McCall27360712010-05-26 22:34:26 +0000222namespace Test8 {
223 struct NonPOD { ~NonPOD(); int x, y, z; };
224 struct A { virtual void foo(); };
225 struct B { virtual void bar(NonPOD); };
226 struct C : A, B { virtual void bar(NonPOD); static void helper(NonPOD); };
227
228 // CHECK: define void @_ZN5Test81C6helperENS_6NonPODE([[NONPODTYPE:%.*]]*
229 void C::helper(NonPOD var) {}
230
231 // CHECK: define void @_ZThn8_N5Test81C3barENS_6NonPODE(
232 // CHECK-NOT: load [[NONPODTYPE]]*
233 // CHECK-NOT: memcpy
234 // CHECK: ret void
235 void C::bar(NonPOD var) {}
236}
237
John McCalle2132352010-06-02 21:22:02 +0000238// PR7241: Emitting thunks for a method shouldn't require the vtable for
239// that class to be emitted.
240namespace Test9 {
241 struct A { virtual ~A() { } };
242 struct B : A { virtual void test() const {} };
243 struct C : B { C(); ~C(); };
244 struct D : C { D() {} };
245 void test() {
246 D d;
247 }
248}
249
John McCall65005532010-08-04 23:46:35 +0000250namespace Test10 {
251 struct A { virtual void foo(); };
252 struct B { virtual void foo(); };
253 struct C : A, B { void foo() {} };
254
John McCall279b5eb2010-08-12 23:36:15 +0000255 // CHECK-HIDDEN: define linkonce_odr void @_ZN6Test101C3fooEv
256 // CHECK-HIDDEN: define linkonce_odr hidden void @_ZThn8_N6Test101C3fooEv
John McCall65005532010-08-04 23:46:35 +0000257
258 void test() {
259 C c;
260 }
261}
262
John McCall27360712010-05-26 22:34:26 +0000263/**** The following has to go at the end of the file ****/
264
Douglas Gregorcb359df2010-05-20 05:54:35 +0000265// This is from Test5:
John McCall279b5eb2010-08-12 23:36:15 +0000266// CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
Douglas Gregorcb359df2010-05-20 05:54:35 +0000267// CHECK: define internal void @_ZThn8_N12_GLOBAL__N_11C1fEv(