1 // 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 -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s
3 // RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -fhidden-weak-vtables -emit-llvm -o - | FileCheck -check-prefix=CHECK-HIDDEN %s
7 // Check that we emit a non-virtual thunk for C::f.
23 // CHECK-LABEL: define void @_ZThn8_N5Test11C1fEv(
30 // Check that we emit a thunk for B::f since it's overriding a virtual base.
36 struct B : virtual A {
41 // CHECK-LABEL: define void @_ZTv0_n24_N5Test21B1fEv(
48 // Check that we emit a covariant thunk for B::f.
51 struct V2 : virtual V1 { };
63 // CHECK: define %{{.*}}* @_ZTch0_v0_n24_N5Test31B1fEv(
64 V2 *B::f() { return 0; }
70 // Check that the thunk for 'C::f' has the same visibility as the function itself.
80 struct __attribute__((visibility("protected"))) C : A, B {
86 // CHECK-LABEL: define protected void @_ZThn8_N5Test41C1fEv(
91 // Check that the thunk gets internal linkage.
110 // Force C::f to be used.
119 // Check that the thunk for 'B::f' gets the same linkage as the function itself.
124 struct B : virtual A {
137 X &operator=(const X&);
154 virtual X f() { return X(); }
160 virtual X f() { return X(); }
163 struct Thunks : Base1, Base2 {
169 // CHECK-LABEL: define void @_ZThn16_N5Test66Thunks1fEv
171 // CHECK: {{call void @_ZN5Test66Thunks1fEv.*sret}}
173 X Thunks::f() { return X(); }
181 X &operator=(const X&);
185 struct Small { short s; };
192 virtual void foo() = 0;
197 virtual void bar() = 0;
202 virtual void baz(X, X&, _Complex float, Small, Small&, Large) = 0;
210 void baz(X, X&, _Complex float, Small, Small&, Large);
213 void D::baz(X, X&, _Complex float, Small, Small&, Large) { }
215 // CHECK-LABEL: define void @_ZThn8_N5Test71D3bazENS_1XERS1_CfNS_5SmallERS4_NS_5LargeE(
218 void testD() { D d; }
222 struct NonPOD { ~NonPOD(); int x, y, z; };
223 struct A { virtual void foo(); };
224 struct B { virtual void bar(NonPOD); };
225 struct C : A, B { virtual void bar(NonPOD); static void helper(NonPOD); };
227 // CHECK: define void @_ZN5Test81C6helperENS_6NonPODE([[NONPODTYPE:%.*]]*
228 void C::helper(NonPOD var) {}
230 // CHECK-LABEL: define void @_ZThn8_N5Test81C3barENS_6NonPODE(
231 // CHECK-NOT: load [[NONPODTYPE]]*
234 void C::bar(NonPOD var) {}
237 // PR7241: Emitting thunks for a method shouldn't require the vtable for
238 // that class to be emitted.
240 struct A { virtual ~A() { } };
241 struct B : A { virtual void test() const {} };
242 struct C : B { C(); ~C(); };
243 struct D : C { D() {} };
250 struct A { virtual void foo(); };
251 struct B { virtual void foo(); };
252 struct C : A, B { void foo() {} };
254 // CHECK-HIDDEN-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
255 // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZThn8_N6Test101C3fooEv
264 struct A { virtual A* f(); };
265 struct B : virtual A { virtual A* f(); };
266 struct C : B { virtual C* f(); };
267 C* C::f() { return 0; }
270 // CHECK: define {{.*}} @_ZN6Test111C1fEv(
272 // The this-adjustment and return-adjustment thunk required when
273 // C::f appears in a vtable where A is at a nonzero offset from C.
274 // CHECK: define {{.*}} @_ZTcv0_n24_v0_n32_N6Test111C1fEv(
276 // The return-adjustment thunk required when C::f appears in a vtable
277 // where A is at a zero offset from C.
278 // CHECK: define {{.*}} @_ZTch0_v0_n32_N6Test111C1fEv(
281 // Varargs thunk test.
284 virtual A* f(int x, ...);
287 virtual B* f(int x, ...);
291 virtual C* f(int x, ...);
293 C* C::f(int x, ...) { return this; }
296 // CHECK: define {{.*}} @_ZN6Test121C1fEiz
298 // Varargs thunk; check that both the this and covariant adjustments
300 // CHECK: define {{.*}} @_ZTchn8_h8_N6Test121C1fEiz
301 // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
302 // CHECK: getelementptr inbounds i8* {{.*}}, i64 8
313 struct Proxy1 : Pad1, B1 {
316 struct D : virtual Proxy1 {
323 // CHECK: define {{.*}} @_ZTcvn8_n32_v8_n24_N6Test131D4foo1Ev
324 // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
325 // CHECK: getelementptr inbounds i8* {{.*}}, i64 -32
326 // CHECK: getelementptr inbounds i8* {{.*}}, i64 -24
327 // CHECK: getelementptr inbounds i8* {{.*}}, i64 8
328 // CHECK: ret %"struct.Test13::D"*
338 class C : public A, public B {
343 // CHECK: define void @_ZThn8_N6Test141C1fEv({{.*}}) unnamed_addr [[NUW:#[0-9]+]]
346 // Varargs non-covariant thunk test.
353 virtual void f(int x, ...);
357 virtual void f(int x, ...);
362 // CHECK: declare void @_ZN6Test151C1fEiz
363 // non-virtual thunk to C::f
364 // CHECK: declare void @_ZThn8_N6Test151C1fEiz
367 /**** The following has to go at the end of the file ****/
369 // This is from Test5:
370 // CHECK-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
371 // CHECK-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
373 // CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} }