vtable-layout.cpp revision 2ef9d6bbd3ae2cf53318bb8fabc4fa6cc0743aff
1// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm-only -fdump-vtable-layouts 2>&1 | FileCheck %s 2 3// For now, just verify this doesn't crash. 4namespace test0 { 5 struct Obj {}; 6 7 struct Base { virtual const Obj *foo() = 0; }; 8 struct Derived : Base { virtual Obj *foo() { return new Obj(); } }; 9 10 void test(Derived *D) { D->foo(); } 11} 12 13namespace Test1 { 14// CHECK: Vtable for 'Test1::A' (3 entries). 15// CHECK-NEXT: 0 | offset_to_top (0) 16// CHECK-NEXT: 1 | Test1::A RTTI 17// CHECK-NEXT: -- (Test1::A, 0) vtable address -- 18// CHECK-NEXT: 2 | void Test1::A::f() 19struct A { 20 virtual void f(); 21}; 22void A::f() { } 23 24} 25 26namespace Test2 { 27 28// This is a smoke test of the vtable dumper. 29// CHECK: Vtable for 'Test2::A' (9 entries). 30// CHECK-NEXT: 0 | offset_to_top (0) 31// CHECK-NEXT: 1 | Test2::A RTTI 32// CHECK-NEXT: -- (Test2::A, 0) vtable address -- 33// CHECK-NEXT: 2 | void Test2::A::f() 34// CHECK-NEXT: 3 | void Test2::A::f() const 35// CHECK-NEXT: 4 | Test2::A *Test2::A::g(int) 36// CHECK-NEXT: 5 | Test2::A::~A() [complete] 37// CHECK-NEXT: 6 | Test2::A::~A() [deleting] 38// CHECK-NEXT: 7 | void Test2::A::h() 39// CHECK-NEXT: 8 | Test2::A &Test2::A::operator=(Test2::A const &) 40struct A { 41 virtual void f(); 42 virtual void f() const; 43 44 virtual A* g(int a); 45 virtual ~A(); 46 virtual void h(); 47 virtual A& operator=(const A&); 48}; 49void A::f() { } 50 51// Another simple vtable dumper test. 52 53// CHECK: Vtable for 'Test2::B' (6 entries). 54// CHECK-NEXT: 0 | offset_to_top (0) 55// CHECK-NEXT: 1 | Test2::B RTTI 56// CHECK-NEXT: -- (Test2::B, 0) vtable address -- 57// CHECK-NEXT: 2 | void Test2::B::f() 58// CHECK-NEXT: 3 | void Test2::B::g() [pure] 59// CHECK-NEXT: 4 | Test2::B::~B() [complete] [pure] 60// CHECK-NEXT: 5 | Test2::B::~B() [deleting] [pure] 61struct B { 62 virtual void f(); 63 virtual void g() = 0; 64 virtual ~B() = 0; 65}; 66void B::f() { } 67 68} 69 70namespace Test3 { 71 72// If a function in a derived class overrides a function in a primary base, 73// then the function should not have an entry in the derived class (unless the return 74// value requires adjusting). 75 76// CHECK: Vtable for 'Test3::A' (3 entries). 77// CHECK-NEXT: 0 | offset_to_top (0) 78// CHECK-NEXT: 1 | Test3::A RTTI 79// CHECK-NEXT: -- (Test3::A, 0) vtable address -- 80// CHECK-NEXT: 2 | void Test3::A::f() 81struct A { 82 virtual void f(); 83}; 84void A::f() { } 85 86// CHECK: Vtable for 'Test3::B' (4 entries). 87// CHECK-NEXT: 0 | offset_to_top (0) 88// CHECK-NEXT: 1 | Test3::B RTTI 89// CHECK-NEXT: -- (Test3::A, 0) vtable address -- 90// CHECK-NEXT: -- (Test3::B, 0) vtable address -- 91// CHECK-NEXT: 2 | void Test3::B::f() 92// CHECK-NEXT: 3 | void Test3::B::g() 93struct B : A { 94 virtual void f(); 95 virtual void g(); 96}; 97void B::f() { } 98 99// CHECK: Vtable for 'Test3::C' (5 entries). 100// CHECK-NEXT: 0 | offset_to_top (0) 101// CHECK-NEXT: 1 | Test3::C RTTI 102// CHECK-NEXT: -- (Test3::A, 0) vtable address -- 103// CHECK-NEXT: -- (Test3::C, 0) vtable address -- 104// CHECK-NEXT: 2 | void Test3::A::f() 105// CHECK-NEXT: 3 | void Test3::C::g() 106// CHECK-NEXT: 4 | void Test3::C::h() 107struct C : A { 108 virtual void g(); 109 virtual void h(); 110}; 111void C::g() { } 112 113// CHECK: Vtable for 'Test3::D' (5 entries). 114// CHECK-NEXT: 0 | offset_to_top (0) 115// CHECK-NEXT: 1 | Test3::D RTTI 116// CHECK-NEXT: -- (Test3::A, 0) vtable address -- 117// CHECK-NEXT: -- (Test3::B, 0) vtable address -- 118// CHECK-NEXT: -- (Test3::D, 0) vtable address -- 119// CHECK-NEXT: 2 | void Test3::D::f() 120// CHECK-NEXT: 3 | void Test3::D::g() 121// CHECK-NEXT: 4 | void Test3::D::h() 122struct D : B { 123 virtual void f(); 124 virtual void g(); 125 virtual void h(); 126}; 127 128void D::f() { } 129} 130 131namespace Test4 { 132 133// Test non-virtual result adjustments. 134 135struct R1 { int r1; }; 136struct R2 { int r2; }; 137struct R3 : R1, R2 { int r3; }; 138 139struct A { 140 virtual R2 *f(); 141}; 142 143// CHECK: Vtable for 'Test4::B' (4 entries). 144// CHECK-NEXT: 0 | offset_to_top (0) 145// CHECK-NEXT: 1 | Test4::B RTTI 146// CHECK-NEXT: -- (Test4::A, 0) vtable address -- 147// CHECK-NEXT: -- (Test4::B, 0) vtable address -- 148// CHECK-NEXT: 2 | Test4::R3 *Test4::B::f() 149// CHECK-NEXT: [return adjustment: 4 non-virtual] 150// CHECK-NEXT: 3 | Test4::R3 *Test4::B::f() 151 152struct B : A { 153 virtual R3 *f(); 154}; 155R3 *B::f() { return 0; } 156 157// Test virtual result adjustments. 158struct V1 { int v1; }; 159struct V2 : virtual V1 { int v1; }; 160 161struct C { 162 virtual V1 *f(); 163}; 164 165// CHECK: Vtable for 'Test4::D' (4 entries). 166// CHECK-NEXT: 0 | offset_to_top (0) 167// CHECK-NEXT: 1 | Test4::D RTTI 168// CHECK-NEXT: -- (Test4::C, 0) vtable address -- 169// CHECK-NEXT: -- (Test4::D, 0) vtable address -- 170// CHECK-NEXT: 2 | Test4::V2 *Test4::D::f() 171// CHECK-NEXT: [return adjustment: 0 non-virtual, -24 vbase offset offset] 172// CHECK-NEXT: 3 | Test4::V2 *Test4::D::f() 173struct D : C { 174 virtual V2 *f(); 175}; 176V2 *D::f() { return 0; }; 177 178// Virtual result adjustments with an additional non-virtual adjustment. 179struct V3 : virtual R3 { int r3; }; 180 181// CHECK: Vtable for 'Test4::E' (4 entries). 182// CHECK-NEXT: 0 | offset_to_top (0) 183// CHECK-NEXT: 1 | Test4::E RTTI 184// CHECK-NEXT: -- (Test4::A, 0) vtable address -- 185// CHECK-NEXT: -- (Test4::E, 0) vtable address -- 186// CHECK-NEXT: 2 | Test4::V3 *Test4::E::f() 187// CHECK-NEXT: [return adjustment: 4 non-virtual, -24 vbase offset offset] 188// CHECK-NEXT: 3 | Test4::V3 *Test4::E::f() 189 190struct E : A { 191 virtual V3 *f(); 192}; 193V3 *E::f() { return 0;} 194 195// Test that a pure virtual member doesn't get a thunk. 196 197// CHECK: Vtable for 'Test4::F' (5 entries). 198// CHECK-NEXT: 0 | offset_to_top (0) 199// CHECK-NEXT: 1 | Test4::F RTTI 200// CHECK-NEXT: -- (Test4::A, 0) vtable address -- 201// CHECK-NEXT: -- (Test4::F, 0) vtable address -- 202// CHECK-NEXT: 2 | Test4::R3 *Test4::F::f() [pure] 203// CHECK-NEXT: 3 | void Test4::F::g() 204// CHECK-NEXT: 4 | Test4::R3 *Test4::F::f() [pure] 205struct F : A { 206 virtual void g(); 207 virtual R3 *f() = 0; 208}; 209void F::g() { } 210 211} 212 213namespace Test5 { 214 215// Simple secondary vtables without 'this' pointer adjustments. 216struct A { 217 virtual void f(); 218 virtual void g(); 219 int a; 220}; 221 222struct B1 : A { 223 virtual void f(); 224 int b1; 225}; 226 227struct B2 : A { 228 virtual void g(); 229 int b2; 230}; 231 232// CHECK: Vtable for 'Test5::C' (9 entries). 233// CHECK-NEXT: 0 | offset_to_top (0) 234// CHECK-NEXT: 1 | Test5::C RTTI 235// CHECK-NEXT: -- (Test5::A, 0) vtable address -- 236// CHECK-NEXT: -- (Test5::B1, 0) vtable address -- 237// CHECK-NEXT: -- (Test5::C, 0) vtable address -- 238// CHECK-NEXT: 2 | void Test5::B1::f() 239// CHECK-NEXT: 3 | void Test5::A::g() 240// CHECK-NEXT: 4 | void Test5::C::h() 241// CHECK-NEXT: 5 | offset_to_top (-16) 242// CHECK-NEXT: 6 | Test5::C RTTI 243// CHECK-NEXT: -- (Test5::A, 16) vtable address -- 244// CHECK-NEXT: -- (Test5::B2, 16) vtable address -- 245// CHECK-NEXT: 7 | void Test5::A::f() 246// CHECK-NEXT: 8 | void Test5::B2::g() 247struct C : B1, B2 { 248 virtual void h(); 249}; 250void C::h() { } 251} 252 253namespace Test6 { 254 255// Simple non-virtual 'this' pointer adjustments. 256struct A1 { 257 virtual void f(); 258 int a; 259}; 260 261struct A2 { 262 virtual void f(); 263 int a; 264}; 265 266// CHECK: Vtable for 'Test6::C' (6 entries). 267// CHECK-NEXT: 0 | offset_to_top (0) 268// CHECK-NEXT: 1 | Test6::C RTTI 269// CHECK-NEXT: -- (Test6::A1, 0) vtable address -- 270// CHECK-NEXT: -- (Test6::C, 0) vtable address -- 271// CHECK-NEXT: 2 | void Test6::C::f() 272// CHECK-NEXT: 3 | offset_to_top (-16) 273// CHECK-NEXT: 4 | Test6::C RTTI 274// CHECK-NEXT: -- (Test6::A2, 16) vtable address -- 275// CHECK-NEXT: 5 | void Test6::C::f() 276// CHECK-NEXT: [this adjustment: -16 non-virtual] 277struct C : A1, A2 { 278 virtual void f(); 279}; 280void C::f() { } 281 282} 283 284namespace Test7 { 285 286// Test that the D::f overrider for A::f have different 'this' pointer 287// adjustments in the two A base subobjects. 288 289struct A { 290 virtual void f(); 291 int a; 292}; 293 294struct B1 : A { }; 295struct B2 : A { }; 296 297struct C { virtual void c(); }; 298 299// CHECK: Vtable for 'Test7::D' (10 entries). 300// CHECK-NEXT: 0 | offset_to_top (0) 301// CHECK-NEXT: 1 | Test7::D RTTI 302// CHECK-NEXT: -- (Test7::C, 0) vtable address -- 303// CHECK-NEXT: -- (Test7::D, 0) vtable address -- 304// CHECK-NEXT: 2 | void Test7::C::c() 305// CHECK-NEXT: 3 | void Test7::D::f() 306// CHECK-NEXT: 4 | offset_to_top (-8) 307// CHECK-NEXT: 5 | Test7::D RTTI 308// CHECK-NEXT: -- (Test7::A, 8) vtable address -- 309// CHECK-NEXT: -- (Test7::B1, 8) vtable address -- 310// CHECK-NEXT: 6 | void Test7::D::f() 311// CHECK-NEXT: [this adjustment: -8 non-virtual] 312// CHECK-NEXT: 7 | offset_to_top (-24) 313// CHECK-NEXT: 8 | Test7::D RTTI 314// CHECK-NEXT: -- (Test7::A, 24) vtable address -- 315// CHECK-NEXT: -- (Test7::B2, 24) vtable address -- 316// CHECK-NEXT: 9 | void Test7::D::f() 317// CHECK-NEXT: [this adjustment: -24 non-virtual] 318struct D : C, B1, B2 { 319 virtual void f(); 320}; 321void D::f() { } 322 323} 324 325namespace Test8 { 326 327// Test that we don't try to layout vtables for classes that don't have 328// virtual bases or virtual member functions. 329 330struct A { }; 331 332// CHECK: Vtable for 'Test8::B' (3 entries). 333// CHECK-NEXT: 0 | offset_to_top (0) 334// CHECK-NEXT: 1 | Test8::B RTTI 335// CHECK-NEXT: -- (Test8::B, 0) vtable address -- 336// CHECK-NEXT: 2 | void Test8::B::f() 337struct B : A { 338 virtual void f(); 339}; 340void B::f() { } 341 342} 343 344namespace Test9 { 345 346// Simple test of vbase offsets. 347 348struct A1 { int a1; }; 349struct A2 { int a2; }; 350 351// CHECK: Vtable for 'Test9::B' (5 entries). 352// CHECK-NEXT: 0 | vbase_offset (16) 353// CHECK-NEXT: 1 | vbase_offset (12) 354// CHECK-NEXT: 2 | offset_to_top (0) 355// CHECK-NEXT: 3 | Test9::B RTTI 356// CHECK-NEXT: -- (Test9::B, 0) vtable address -- 357// CHECK-NEXT: 4 | void Test9::B::f() 358struct B : virtual A1, virtual A2 { 359 int b; 360 361 virtual void f(); 362}; 363 364 365void B::f() { } 366 367} 368 369namespace Test10 { 370 371// Test for a bug where we would not emit secondary vtables for bases 372// of a primary base. 373struct A1 { virtual void a1(); }; 374struct A2 { virtual void a2(); }; 375 376// CHECK: Vtable for 'Test10::C' (7 entries). 377// CHECK-NEXT: 0 | offset_to_top (0) 378// CHECK-NEXT: 1 | Test10::C RTTI 379// CHECK-NEXT: -- (Test10::A1, 0) vtable address -- 380// CHECK-NEXT: -- (Test10::B, 0) vtable address -- 381// CHECK-NEXT: -- (Test10::C, 0) vtable address -- 382// CHECK-NEXT: 2 | void Test10::A1::a1() 383// CHECK-NEXT: 3 | void Test10::C::f() 384// CHECK-NEXT: 4 | offset_to_top (-8) 385// CHECK-NEXT: 5 | Test10::C RTTI 386// CHECK-NEXT: -- (Test10::A2, 8) vtable address -- 387// CHECK-NEXT: 6 | void Test10::A2::a2() 388struct B : A1, A2 { 389 int b; 390}; 391 392struct C : B { 393 virtual void f(); 394}; 395void C::f() { } 396 397} 398 399namespace Test11 { 400 401// Very simple test of vtables for virtual bases. 402struct A1 { int a; }; 403struct A2 { int b; }; 404 405struct B : A1, virtual A2 { 406 int b; 407}; 408 409// CHECK: Vtable for 'Test11::C' (8 entries). 410// CHECK-NEXT: 0 | vbase_offset (24) 411// CHECK-NEXT: 1 | vbase_offset (8) 412// CHECK-NEXT: 2 | offset_to_top (0) 413// CHECK-NEXT: 3 | Test11::C RTTI 414// CHECK-NEXT: -- (Test11::C, 0) vtable address -- 415// CHECK-NEXT: 4 | void Test11::C::f() 416// CHECK-NEXT: 5 | vbase_offset (16) 417// CHECK-NEXT: 6 | offset_to_top (-8) 418// CHECK-NEXT: 7 | Test11::C RTTI 419struct C : virtual B { 420 virtual void f(); 421}; 422void C::f() { } 423 424} 425 426namespace Test12 { 427 428// Test that the right vcall offsets are generated in the right order. 429 430// CHECK: Vtable for 'Test12::B' (19 entries). 431// CHECK-NEXT: 0 | vbase_offset (8) 432// CHECK-NEXT: 1 | offset_to_top (0) 433// CHECK-NEXT: 2 | Test12::B RTTI 434// CHECK-NEXT: -- (Test12::B, 0) vtable address -- 435// CHECK-NEXT: 3 | void Test12::B::f() 436// CHECK-NEXT: 4 | void Test12::B::a() 437// CHECK-NEXT: 5 | vcall_offset (32) 438// CHECK-NEXT: 6 | vcall_offset (16) 439// CHECK-NEXT: 7 | vcall_offset (-8) 440// CHECK-NEXT: 8 | vcall_offset (0) 441// CHECK-NEXT: 9 | offset_to_top (-8) 442// CHECK-NEXT: 10 | Test12::B RTTI 443// CHECK-NEXT: -- (Test12::A, 8) vtable address -- 444// CHECK-NEXT: -- (Test12::A1, 8) vtable address -- 445// CHECK-NEXT: 11 | void Test12::A1::a1() 446// CHECK-NEXT: 12 | void Test12::B::a() 447// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] 448// CHECK-NEXT: 13 | offset_to_top (-24) 449// CHECK-NEXT: 14 | Test12::B RTTI 450// CHECK-NEXT: -- (Test12::A2, 24) vtable address -- 451// CHECK-NEXT: 15 | void Test12::A2::a2() 452// CHECK-NEXT: 16 | offset_to_top (-40) 453// CHECK-NEXT: 17 | Test12::B RTTI 454// CHECK-NEXT: -- (Test12::A3, 40) vtable address -- 455// CHECK-NEXT: 18 | void Test12::A3::a3() 456struct A1 { 457 virtual void a1(); 458 int a; 459}; 460 461struct A2 { 462 virtual void a2(); 463 int a; 464}; 465 466struct A3 { 467 virtual void a3(); 468 int a; 469}; 470 471struct A : A1, A2, A3 { 472 virtual void a(); 473 int i; 474}; 475 476struct B : virtual A { 477 virtual void f(); 478 479 virtual void a(); 480}; 481void B::f() { } 482 483} 484 485namespace Test13 { 486 487// Test that we don't try to emit a vtable for 'A' twice. 488struct A { 489 virtual void f(); 490}; 491 492struct B : virtual A { 493 virtual void f(); 494}; 495 496// CHECK: Vtable for 'Test13::C' (6 entries). 497// CHECK-NEXT: 0 | vbase_offset (0) 498// CHECK-NEXT: 1 | vbase_offset (0) 499// CHECK-NEXT: 2 | vcall_offset (0) 500// CHECK-NEXT: 3 | offset_to_top (0) 501// CHECK-NEXT: 4 | Test13::C RTTI 502// CHECK-NEXT: -- (Test13::A, 0) vtable address -- 503// CHECK-NEXT: -- (Test13::B, 0) vtable address -- 504// CHECK-NEXT: -- (Test13::C, 0) vtable address -- 505// CHECK-NEXT: 5 | void Test13::C::f() 506struct C : virtual B, virtual A { 507 virtual void f(); 508}; 509void C::f() { } 510 511} 512 513namespace Test14 { 514 515// Verify that we handle A being a non-virtual base of B, which is a virtual base. 516 517struct A { 518 virtual void f(); 519}; 520 521struct B : A { }; 522 523struct C : virtual B { }; 524 525// CHECK: Vtable for 'Test14::D' (5 entries). 526// CHECK-NEXT: 0 | vbase_offset (0) 527// CHECK-NEXT: 1 | vcall_offset (0) 528// CHECK-NEXT: 2 | offset_to_top (0) 529// CHECK-NEXT: 3 | Test14::D RTTI 530// CHECK-NEXT: -- (Test14::A, 0) vtable address -- 531// CHECK-NEXT: -- (Test14::B, 0) vtable address -- 532// CHECK-NEXT: -- (Test14::C, 0) vtable address -- 533// CHECK-NEXT: -- (Test14::D, 0) vtable address -- 534// CHECK-NEXT: 4 | void Test14::D::f() 535struct D : C, virtual B { 536 virtual void f(); 537}; 538void D::f() { } 539 540} 541 542namespace Test15 { 543 544// Test that we don't emit an extra vtable for B since it's a primary base of C. 545struct A { virtual void a(); }; 546struct B { virtual void b(); }; 547 548struct C : virtual B { }; 549 550// CHECK: Vtable for 'Test15::D' (11 entries). 551// CHECK-NEXT: 0 | vbase_offset (8) 552// CHECK-NEXT: 1 | vbase_offset (8) 553// CHECK-NEXT: 2 | offset_to_top (0) 554// CHECK-NEXT: 3 | Test15::D RTTI 555// CHECK-NEXT: -- (Test15::A, 0) vtable address -- 556// CHECK-NEXT: -- (Test15::D, 0) vtable address -- 557// CHECK-NEXT: 4 | void Test15::A::a() 558// CHECK-NEXT: 5 | void Test15::D::f() 559// CHECK-NEXT: 6 | vbase_offset (0) 560// CHECK-NEXT: 7 | vcall_offset (0) 561// CHECK-NEXT: 8 | offset_to_top (-8) 562// CHECK-NEXT: 9 | Test15::D RTTI 563// CHECK-NEXT: -- (Test15::B, 8) vtable address -- 564// CHECK-NEXT: -- (Test15::C, 8) vtable address -- 565// CHECK-NEXT: 10 | void Test15::B::b() 566struct D : A, virtual B, virtual C { 567 virtual void f(); 568}; 569void D::f() { } 570 571} 572 573namespace Test16 { 574 575// Test that destructors share vcall offsets. 576 577struct A { virtual ~A(); }; 578struct B { virtual ~B(); }; 579 580struct C : A, B { virtual ~C(); }; 581 582// CHECK: Vtable for 'Test16::D' (15 entries). 583// CHECK-NEXT: 0 | vbase_offset (8) 584// CHECK-NEXT: 1 | offset_to_top (0) 585// CHECK-NEXT: 2 | Test16::D RTTI 586// CHECK-NEXT: -- (Test16::D, 0) vtable address -- 587// CHECK-NEXT: 3 | void Test16::D::f() 588// CHECK-NEXT: 4 | Test16::D::~D() [complete] 589// CHECK-NEXT: 5 | Test16::D::~D() [deleting] 590// CHECK-NEXT: 6 | vcall_offset (-8) 591// CHECK-NEXT: 7 | offset_to_top (-8) 592// CHECK-NEXT: 8 | Test16::D RTTI 593// CHECK-NEXT: -- (Test16::A, 8) vtable address -- 594// CHECK-NEXT: -- (Test16::C, 8) vtable address -- 595// CHECK-NEXT: 9 | Test16::D::~D() [complete] 596// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] 597// CHECK-NEXT: 10 | Test16::D::~D() [deleting] 598// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] 599// CHECK-NEXT: 11 | offset_to_top (-16) 600// CHECK-NEXT: 12 | Test16::D RTTI 601// CHECK-NEXT: -- (Test16::B, 16) vtable address -- 602// CHECK-NEXT: 13 | Test16::D::~D() [complete] 603// CHECK-NEXT: [this adjustment: -8 non-virtual, -24 vcall offset offset] 604// CHECK-NEXT: 14 | Test16::D::~D() [deleting] 605// CHECK-NEXT: [this adjustment: -8 non-virtual, -24 vcall offset offset] 606struct D : virtual C { 607 virtual void f(); 608}; 609void D::f() { } 610 611} 612 613namespace Test17 { 614 615// Test that we don't mark E::f in the C-in-E vtable as unused. 616struct A { virtual void f(); }; 617struct B : virtual A { virtual void f(); }; 618struct C : virtual A { virtual void f(); }; 619struct D : virtual B, virtual C { virtual void f(); }; 620 621// CHECK: Vtable for 'Test17::E' (13 entries). 622// CHECK-NEXT: 0 | vbase_offset (0) 623// CHECK-NEXT: 1 | vbase_offset (8) 624// CHECK-NEXT: 2 | vbase_offset (0) 625// CHECK-NEXT: 3 | vbase_offset (0) 626// CHECK-NEXT: 4 | vcall_offset (0) 627// CHECK-NEXT: 5 | offset_to_top (0) 628// CHECK-NEXT: 6 | Test17::E RTTI 629// CHECK-NEXT: -- (Test17::A, 0) vtable address -- 630// CHECK-NEXT: -- (Test17::B, 0) vtable address -- 631// CHECK-NEXT: -- (Test17::D, 0) vtable address -- 632// CHECK-NEXT: -- (Test17::E, 0) vtable address -- 633// CHECK-NEXT: 7 | void Test17::E::f() 634// CHECK-NEXT: 8 | vbase_offset (-8) 635// CHECK-NEXT: 9 | vcall_offset (-8) 636// CHECK-NEXT: 10 | offset_to_top (-8) 637// CHECK-NEXT: 11 | Test17::E RTTI 638// CHECK-NEXT: -- (Test17::A, 8) vtable address -- 639// CHECK-NEXT: -- (Test17::C, 8) vtable address -- 640// CHECK-NEXT: 12 | void Test17::E::f() 641// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] 642class E : virtual D { 643 virtual void f(); 644}; 645void E::f() {} 646 647} 648 649namespace Test18 { 650 651// Test that we compute the right 'this' adjustment offsets. 652 653struct A { 654 virtual void f(); 655 virtual void g(); 656}; 657 658struct B : virtual A { 659 virtual void f(); 660}; 661 662struct C : A, B { 663 virtual void g(); 664}; 665 666// CHECK: Vtable for 'Test18::D' (24 entries). 667// CHECK-NEXT: 0 | vbase_offset (8) 668// CHECK-NEXT: 1 | vbase_offset (0) 669// CHECK-NEXT: 2 | vbase_offset (0) 670// CHECK-NEXT: 3 | vcall_offset (8) 671// CHECK-NEXT: 4 | vcall_offset (0) 672// CHECK-NEXT: 5 | offset_to_top (0) 673// CHECK-NEXT: 6 | Test18::D RTTI 674// CHECK-NEXT: -- (Test18::A, 0) vtable address -- 675// CHECK-NEXT: -- (Test18::B, 0) vtable address -- 676// CHECK-NEXT: -- (Test18::D, 0) vtable address -- 677// CHECK-NEXT: 7 | void Test18::D::f() 678// CHECK-NEXT: 8 | void Test18::C::g() 679// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] 680// CHECK-NEXT: 9 | void Test18::D::h() 681// CHECK-NEXT: 10 | vcall_offset (0) 682// CHECK-NEXT: 11 | vcall_offset (-8) 683// CHECK-NEXT: 12 | vbase_offset (-8) 684// CHECK-NEXT: 13 | offset_to_top (-8) 685// CHECK-NEXT: 14 | Test18::D RTTI 686// CHECK-NEXT: -- (Test18::A, 8) vtable address -- 687// CHECK-NEXT: -- (Test18::C, 8) vtable address -- 688// CHECK-NEXT: 15 | void Test18::D::f() 689// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] 690// CHECK-NEXT: 16 | void Test18::C::g() 691// CHECK-NEXT: 17 | vbase_offset (-16) 692// CHECK-NEXT: 18 | vcall_offset (-8) 693// CHECK-NEXT: 19 | vcall_offset (-16) 694// CHECK-NEXT: 20 | offset_to_top (-16) 695// CHECK-NEXT: 21 | Test18::D RTTI 696// CHECK-NEXT: -- (Test18::A, 16) vtable address -- 697// CHECK-NEXT: -- (Test18::B, 16) vtable address -- 698// CHECK-NEXT: 22 | void Test18::D::f() 699// CHECK-NEXT: [this adjustment: -8 non-virtual, -32 vcall offset offset] 700// CHECK-NEXT: 23 | [unused] void Test18::C::g() 701struct D : virtual B, virtual C, virtual A 702{ 703 virtual void f(); 704 virtual void h(); 705}; 706void D::f() {} 707 708}