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