1 // 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 7 8 namespace Test1 { 9 10 // Check that we emit a non-virtual thunk for C::f. 11 12 struct A { 13 virtual void f(); 14 }; 15 16 struct B { 17 virtual void f(); 18 }; 19 20 struct C : A, B { 21 virtual void c(); 22 23 virtual void f(); 24 }; 25 26 // CHECK-LABEL: define void @_ZThn8_N5Test11C1fEv( 27 void C::f() { } 28 29 } 30 31 namespace Test2 { 32 33 // Check that we emit a thunk for B::f since it's overriding a virtual base. 34 35 struct A { 36 virtual void f(); 37 }; 38 39 struct B : virtual A { 40 virtual void b(); 41 virtual void f(); 42 }; 43 44 // CHECK-LABEL: define void @_ZTv0_n24_N5Test21B1fEv( 45 void B::f() { } 46 47 } 48 49 namespace Test3 { 50 51 // Check that we emit a covariant thunk for B::f. 52 53 struct V1 { }; 54 struct V2 : virtual V1 { }; 55 56 struct A { 57 virtual V1 *f(); 58 }; 59 60 struct B : A { 61 virtual void b(); 62 63 virtual V2 *f(); 64 }; 65 66 // CHECK: define %{{.*}}* @_ZTch0_v0_n24_N5Test31B1fEv( 67 V2 *B::f() { return 0; } 68 69 } 70 71 namespace Test4 { 72 73 // Check that the thunk for 'C::f' has the same visibility as the function itself. 74 75 struct A { 76 virtual void f(); 77 }; 78 79 struct B { 80 virtual void f(); 81 }; 82 83 struct __attribute__((visibility("protected"))) C : A, B { 84 virtual void c(); 85 86 virtual void f(); 87 }; 88 89 // CHECK-LABEL: define protected void @_ZThn8_N5Test41C1fEv( 90 void C::f() { } 91 92 } 93 94 // Check that the thunk gets internal linkage. 95 namespace Test4B { 96 struct A { 97 virtual void f(); 98 }; 99 100 struct B { 101 virtual void f(); 102 }; 103 104 namespace { 105 struct C : A, B { 106 virtual void c(); 107 virtual void f(); 108 }; 109 } 110 void C::c() {} 111 void C::f() {} 112 113 // Force C::f to be used. 114 void f() { 115 C c; 116 c.f(); 117 } 118 } 119 120 namespace Test5 { 121 122 // Check that the thunk for 'B::f' gets the same linkage as the function itself. 123 struct A { 124 virtual void f(); 125 }; 126 127 struct B : virtual A { 128 virtual void f() { } 129 }; 130 131 void f(B b) { 132 b.f(); 133 } 134 } 135 136 namespace Test6 { 137 struct X { 138 X(); 139 X(const X&); 140 X &operator=(const X&); 141 ~X(); 142 }; 143 144 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 172 // CHECK-LABEL: define void @_ZThn16_N5Test66Thunks1fEv 173 // CHECK-NOT: memcpy 174 // CHECK: {{call void @_ZN5Test66Thunks1fEv.*sret}} 175 // CHECK: ret void 176 X Thunks::f() { return X(); } 177 } 178 179 namespace 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 218 // CHECK-LABEL: define void @_ZThn8_N5Test71D3bazENS_1XERS1_CfNS_5SmallERS4_NS_5LargeE( 219 // CHECK-NOT: memcpy 220 // CHECK: ret void 221 void testD() { D d; } 222 } 223 224 namespace 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 233 // CHECK-LABEL: define void @_ZThn8_N5Test81C3barENS_6NonPODE( 234 // CHECK-NOT: load [[NONPODTYPE]], [[NONPODTYPE]]* 235 // CHECK-NOT: memcpy 236 // CHECK: ret void 237 void C::bar(NonPOD var) {} 238 } 239 240 // PR7241: Emitting thunks for a method shouldn't require the vtable for 241 // that class to be emitted. 242 namespace 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 252 namespace Test10 { 253 struct A { virtual void foo(); }; 254 struct B { virtual void foo(); }; 255 struct C : A, B { void foo() {} }; 256 257 // Test later. 258 void test() { 259 C c; 260 } 261 } 262 263 // PR7611 264 namespace 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 270 // C::f itself. 271 // CHECK: define {{.*}} @_ZN6Test111C1fEv( 272 273 // 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 277 // 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 282 // Varargs thunk test. 283 namespace 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 302 // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -8 303 // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 8 304 } 305 306 // PR13832 307 namespace 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 325 // 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 329 // CHECK: ret %"struct.Test13::D"* 330 } 331 332 namespace 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 } 344 // CHECK: define void @_ZThn8_N6Test141C1fEv({{.*}}) unnamed_addr [[NUW:#[0-9]+]] 345 } 346 347 // Varargs non-covariant thunk test. 348 // PR18098 349 namespace 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 368 namespace Test16 { 369 struct A { 370 virtual ~A(); 371 }; 372 struct B { 373 virtual void foo(); 374 }; 375 struct C : public A, public B { 376 void foo() {} 377 }; 378 struct D : public C { 379 ~D(); 380 }; 381 D::~D() {} 382 // CHECK: define linkonce_odr void @_ZThn8_N6Test161C3fooEv({{.*}}) {{.*}} comdat 383 } 384 385 /**** The following has to go at the end of the file ****/ 386 387 // checking without opt 388 // CHECK-NONOPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv( 389 // CHECK-NONOPT-NOT: comdat 390 391 // This is from Test5: 392 // CHECK-NONOPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv 393 394 // This is from Test10: 395 // 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 407 408 // CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} } 409