vtable-layout.cpp revision c7b631682f66b5d6144968cf75d3af895b611fc6
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