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