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 -fhidden-weak-vtables -emit-llvm -o - | FileCheck -check-prefix=HIDDEN %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: 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: 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: 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: 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: 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: 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 // CHECK-HIDDEN: define linkonce_odr void @_ZN6Test101C3fooEv 254 // CHECK-HIDDEN: define linkonce_odr hidden void @_ZThn8_N6Test101C3fooEv 255 256 void test() { 257 C c; 258 } 259 } 260 261 // PR7611 262 namespace Test11 { 263 struct A { virtual A* f(); }; 264 struct B : virtual A { virtual A* f(); }; 265 struct C : B { virtual C* f(); }; 266 C* C::f() { return 0; } 267 268 // C::f itself. 269 // CHECK: define {{.*}} @_ZN6Test111C1fEv( 270 271 // The this-adjustment and return-adjustment thunk required when 272 // C::f appears in a vtable where A is at a nonzero offset from C. 273 // CHECK: define {{.*}} @_ZTcv0_n24_v0_n32_N6Test111C1fEv( 274 275 // The return-adjustment thunk required when C::f appears in a vtable 276 // where A is at a zero offset from C. 277 // CHECK: define {{.*}} @_ZTch0_v0_n32_N6Test111C1fEv( 278 } 279 280 // Varargs thunk test. 281 namespace Test12 { 282 struct A { 283 virtual A* f(int x, ...); 284 }; 285 struct B { 286 virtual B* f(int x, ...); 287 }; 288 struct C : A, B { 289 virtual void c(); 290 virtual C* f(int x, ...); 291 }; 292 C* C::f(int x, ...) { return this; } 293 294 // C::f 295 // CHECK: define {{.*}} @_ZN6Test121C1fEiz 296 297 // Varargs thunk; check that both the this and covariant adjustments 298 // are generated. 299 // CHECK: define {{.*}} @_ZTchn8_h8_N6Test121C1fEiz 300 // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8 301 // CHECK: getelementptr inbounds i8* {{.*}}, i64 8 302 } 303 304 // PR13832 305 namespace Test13 { 306 struct B1 { 307 virtual B1 &foo1(); 308 }; 309 struct Pad1 { 310 virtual ~Pad1(); 311 }; 312 struct Proxy1 : Pad1, B1 { 313 virtual ~Proxy1(); 314 }; 315 struct D : virtual Proxy1 { 316 virtual ~D(); 317 virtual D &foo1(); 318 }; 319 D& D::foo1() { 320 return *this; 321 } 322 // CHECK: define {{.*}} @_ZTcvn8_n32_v8_n24_N6Test131D4foo1Ev 323 // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8 324 // CHECK: getelementptr inbounds i8* {{.*}}, i64 -32 325 // CHECK: getelementptr inbounds i8* {{.*}}, i64 -24 326 // CHECK: getelementptr inbounds i8* {{.*}}, i64 8 327 // CHECK: ret %"struct.Test13::D"* 328 } 329 330 namespace Test14 { 331 class A { 332 virtual void f(); 333 }; 334 class B { 335 virtual void f(); 336 }; 337 class C : public A, public B { 338 virtual void f(); 339 }; 340 void C::f() { 341 } 342 // CHECK: define void @_ZThn8_N6Test141C1fEv({{.*}}) unnamed_addr [[NUW:#[0-9]+]] 343 } 344 345 /**** The following has to go at the end of the file ****/ 346 347 // This is from Test5: 348 // CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv 349 // CHECK: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv( 350 351 // CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} } 352