vtable-layout-abi-examples.cpp revision db4022cf95d80afd28b5fd1273f5be62c891a230
1// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm-only -fdump-vtable-layouts 2>&1 | FileCheck %s 2 3/// Examples from the Itanium C++ ABI specification. 4/// http://www.codesourcery.com/public/cxx-abi/ 5 6namespace Test1 { 7 8// This is from http://www.codesourcery.com/public/cxx-abi/cxx-vtable-ex.html 9 10// CHECK: Vtable for 'Test1::A' (5 entries). 11// CHECK-NEXT: 0 | offset_to_top (0) 12// CHECK-NEXT: 1 | Test1::A RTTI 13// CHECK-NEXT: -- (Test1::A, 0) vtable address -- 14// CHECK-NEXT: 2 | void Test1::A::f() 15// CHECK-NEXT: 3 | void Test1::A::g() 16// CHECK-NEXT: 4 | void Test1::A::h() 17struct A { 18 virtual void f (); 19 virtual void g (); 20 virtual void h (); 21 int ia; 22}; 23void A::f() {} 24 25// CHECK: Vtable for 'Test1::B' (13 entries). 26// CHECK-NEXT: 0 | vbase_offset (16) 27// CHECK-NEXT: 1 | offset_to_top (0) 28// CHECK-NEXT: 2 | Test1::B RTTI 29// CHECK-NEXT: -- (Test1::B, 0) vtable address -- 30// CHECK-NEXT: 3 | void Test1::B::f() 31// CHECK-NEXT: 4 | void Test1::B::h() 32// CHECK-NEXT: 5 | vcall_offset (-16) 33// CHECK-NEXT: 6 | vcall_offset (0) 34// CHECK-NEXT: 7 | vcall_offset (-16) 35// CHECK-NEXT: 8 | offset_to_top (-16) 36// CHECK-NEXT: 9 | Test1::B RTTI 37// CHECK-NEXT: -- (Test1::A, 16) vtable address -- 38// CHECK-NEXT: 10 | void Test1::B::f() 39// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] 40// CHECK-NEXT: 11 | void Test1::A::g() 41// CHECK-NEXT: 12 | void Test1::B::h() 42// CHECK-NEXT: [this adjustment: 0 non-virtual, -40 vcall offset offset] 43struct B: public virtual A { 44 void f (); 45 void h (); 46 int ib; 47}; 48void B::f() {} 49 50// CHECK: Vtable for 'Test1::C' (13 entries). 51// CHECK-NEXT: 0 | vbase_offset (16) 52// CHECK-NEXT: 1 | offset_to_top (0) 53// CHECK-NEXT: 2 | Test1::C RTTI 54// CHECK-NEXT: -- (Test1::C, 0) vtable address -- 55// CHECK-NEXT: 3 | void Test1::C::g() 56// CHECK-NEXT: 4 | void Test1::C::h() 57// CHECK-NEXT: 5 | vcall_offset (-16) 58// CHECK-NEXT: 6 | vcall_offset (-16) 59// CHECK-NEXT: 7 | vcall_offset (0) 60// CHECK-NEXT: 8 | offset_to_top (-16) 61// CHECK-NEXT: 9 | Test1::C RTTI 62// CHECK-NEXT: -- (Test1::A, 16) vtable address -- 63// CHECK-NEXT: 10 | void Test1::A::f() 64// CHECK-NEXT: 11 | void Test1::C::g() 65// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] 66// CHECK-NEXT: 12 | void Test1::C::h() 67// CHECK-NEXT: [this adjustment: 0 non-virtual, -40 vcall offset offset] 68struct C: public virtual A { 69 void g (); 70 void h (); 71 int ic; 72}; 73void C::g() {} 74 75// CHECK: Vtable for 'Test1::D' (18 entries). 76// CHECK-NEXT: 0 | vbase_offset (32) 77// CHECK-NEXT: 1 | offset_to_top (0) 78// CHECK-NEXT: 2 | Test1::D RTTI 79// CHECK-NEXT: -- (Test1::B, 0) vtable address -- 80// CHECK-NEXT: -- (Test1::D, 0) vtable address -- 81// CHECK-NEXT: 3 | void Test1::B::f() 82// CHECK-NEXT: 4 | void Test1::D::h() 83// CHECK-NEXT: 5 | vbase_offset (16) 84// CHECK-NEXT: 6 | offset_to_top (-16) 85// CHECK-NEXT: 7 | Test1::D RTTI 86// CHECK-NEXT: -- (Test1::C, 16) vtable address -- 87// CHECK-NEXT: 8 | void Test1::C::g() 88// CHECK-NEXT: 9 | void Test1::D::h() 89// CHECK-NEXT: [this adjustment: -16 non-virtual] 90// CHECK-NEXT: 10 | vcall_offset (-32) 91// CHECK-NEXT: 11 | vcall_offset (-16) 92// CHECK-NEXT: 12 | vcall_offset (-32) 93// CHECK-NEXT: 13 | offset_to_top (-32) 94// CHECK-NEXT: 14 | Test1::D RTTI 95// CHECK-NEXT: -- (Test1::A, 32) vtable address -- 96// CHECK-NEXT: 15 | void Test1::B::f() 97// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] 98// CHECK-NEXT: 16 | void Test1::C::g() 99// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] 100// CHECK-NEXT: 17 | void Test1::D::h() 101// CHECK-NEXT: [this adjustment: 0 non-virtual, -40 vcall offset offset] 102struct D: public B, public C { 103 void h (); 104 int id; 105}; 106void D::h() { } 107 108struct X { 109 int ix; 110 virtual void x(); 111}; 112 113// CHECK: Vtable for 'Test1::E' (24 entries). 114// CHECK-NEXT: 0 | vbase_offset (56) 115// CHECK-NEXT: 1 | offset_to_top (0) 116// CHECK-NEXT: 2 | Test1::E RTTI 117// CHECK-NEXT: -- (Test1::E, 0) vtable address -- 118// CHECK-NEXT: -- (Test1::X, 0) vtable address -- 119// CHECK-NEXT: 3 | void Test1::X::x() 120// CHECK-NEXT: 4 | void Test1::E::f() 121// CHECK-NEXT: 5 | void Test1::E::h() 122// CHECK-NEXT: 6 | vbase_offset (40) 123// CHECK-NEXT: 7 | offset_to_top (-16) 124// CHECK-NEXT: 8 | Test1::E RTTI 125// CHECK-NEXT: -- (Test1::B, 16) vtable address -- 126// CHECK-NEXT: -- (Test1::D, 16) vtable address -- 127// CHECK-NEXT: 9 | void Test1::E::f() 128// CHECK-NEXT: [this adjustment: -16 non-virtual] 129// CHECK-NEXT: 10 | void Test1::E::h() 130// CHECK-NEXT: [this adjustment: -16 non-virtual] 131// CHECK-NEXT: 11 | vbase_offset (24) 132// CHECK-NEXT: 12 | offset_to_top (-32) 133// CHECK-NEXT: 13 | Test1::E RTTI 134// CHECK-NEXT: -- (Test1::C, 32) vtable address -- 135// CHECK-NEXT: 14 | void Test1::C::g() 136// CHECK-NEXT: 15 | void Test1::E::h() 137// CHECK-NEXT: [this adjustment: -32 non-virtual] 138// CHECK-NEXT: 16 | vcall_offset (-56) 139// CHECK-NEXT: 17 | vcall_offset (-24) 140// CHECK-NEXT: 18 | vcall_offset (-56) 141// CHECK-NEXT: 19 | offset_to_top (-56) 142// CHECK-NEXT: 20 | Test1::E RTTI 143// CHECK-NEXT: -- (Test1::A, 56) vtable address -- 144// CHECK-NEXT: 21 | void Test1::E::f() 145// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] 146// CHECK-NEXT: 22 | void Test1::C::g() 147// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] 148// CHECK-NEXT: 23 | void Test1::E::h() 149// CHECK-NEXT: [this adjustment: 0 non-virtual, -40 vcall offset offset] 150struct E : X, D { 151 int ie; 152 void f(); 153 void h (); 154}; 155void E::f() { } 156 157} 158 159namespace Test2 { 160 161// From http://www.codesourcery.com/public/cxx-abi/abi.html#class-types. 162 163struct A { virtual void f(); }; 164struct B : virtual public A { int i; }; 165struct C : virtual public A { int j; }; 166 167// CHECK: Vtable for 'Test2::D' (11 entries). 168// CHECK-NEXT: 0 | vbase_offset (0) 169// CHECK-NEXT: 1 | vcall_offset (0) 170// CHECK-NEXT: 2 | offset_to_top (0) 171// CHECK-NEXT: 3 | Test2::D RTTI 172// CHECK-NEXT: -- (Test2::A, 0) vtable address -- 173// CHECK-NEXT: -- (Test2::B, 0) vtable address -- 174// CHECK-NEXT: -- (Test2::D, 0) vtable address -- 175// CHECK-NEXT: 4 | void Test2::A::f() 176// CHECK-NEXT: 5 | void Test2::D::d() 177// CHECK-NEXT: 6 | vbase_offset (-16) 178// CHECK-NEXT: 7 | vcall_offset (-16) 179// CHECK-NEXT: 8 | offset_to_top (-16) 180// CHECK-NEXT: 9 | Test2::D RTTI 181// CHECK-NEXT: -- (Test2::A, 16) vtable address -- 182// CHECK-NEXT: -- (Test2::C, 16) vtable address -- 183// CHECK-NEXT: 10 | [unused] void Test2::A::f() 184struct D : public B, public C { 185 virtual void d(); 186}; 187void D::d() { } 188 189} 190 191namespace Test3 { 192 193// From http://www.codesourcery.com/public/cxx-abi/abi-examples.html#vtable-ctor 194 195struct V1 { 196 int v1; 197 virtual void f(); 198}; 199 200struct V2 : virtual V1 { 201 int v2; 202 virtual void f(); 203}; 204 205// CHECK: Vtable for 'Test3::C' (14 entries). 206// CHECK-NEXT: 0 | vbase_offset (32) 207// CHECK-NEXT: 1 | vbase_offset (16) 208// CHECK-NEXT: 2 | offset_to_top (0) 209// CHECK-NEXT: 3 | Test3::C RTTI 210// CHECK-NEXT: -- (Test3::C, 0) vtable address -- 211// CHECK-NEXT: 4 | void Test3::C::f() 212// CHECK-NEXT: 5 | vcall_offset (-16) 213// CHECK-NEXT: 6 | offset_to_top (-16) 214// CHECK-NEXT: 7 | Test3::C RTTI 215// CHECK-NEXT: -- (Test3::V1, 16) vtable address -- 216// CHECK-NEXT: 8 | void Test3::C::f() 217// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] 218// CHECK-NEXT: 9 | vcall_offset (-32) 219// CHECK-NEXT: 10 | vbase_offset (-16) 220// CHECK-NEXT: 11 | offset_to_top (-32) 221// CHECK-NEXT: 12 | Test3::C RTTI 222// CHECK-NEXT: -- (Test3::V2, 32) vtable address -- 223// CHECK-NEXT: 13 | void Test3::C::f() 224// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] 225 226// CHECK: Construction vtable for ('Test3::V2', 32) in 'Test3::C' (9 entries). 227// CHECK-NEXT: 0 | vcall_offset (0) 228// CHECK-NEXT: 1 | vbase_offset (-16) 229// CHECK-NEXT: 2 | offset_to_top (0) 230// CHECK-NEXT: 3 | Test3::V2 RTTI 231// CHECK-NEXT: -- (Test3::V2, 32) vtable address -- 232// CHECK-NEXT: 4 | void Test3::V2::f() 233// CHECK-NEXT: 5 | vcall_offset (16) 234// CHECK-NEXT: 6 | offset_to_top (16) 235// CHECK-NEXT: 7 | Test3::V2 RTTI 236// CHECK-NEXT: -- (Test3::V1, 16) vtable address -- 237// CHECK-NEXT: 8 | void Test3::V2::f() 238// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] 239struct C : virtual V1, virtual V2 { 240 int c; 241 virtual void f(); 242}; 243void C::f() { } 244 245struct B { 246 int b; 247}; 248 249// CHECK: Vtable for 'Test3::D' (15 entries). 250// CHECK-NEXT: 0 | vbase_offset (40) 251// CHECK-NEXT: 1 | vbase_offset (24) 252// CHECK-NEXT: 2 | offset_to_top (0) 253// CHECK-NEXT: 3 | Test3::D RTTI 254// CHECK-NEXT: -- (Test3::C, 0) vtable address -- 255// CHECK-NEXT: -- (Test3::D, 0) vtable address -- 256// CHECK-NEXT: 4 | void Test3::C::f() 257// CHECK-NEXT: 5 | void Test3::D::g() 258// CHECK-NEXT: 6 | vcall_offset (-24) 259// CHECK-NEXT: 7 | offset_to_top (-24) 260// CHECK-NEXT: 8 | Test3::D RTTI 261// CHECK-NEXT: -- (Test3::V1, 24) vtable address -- 262// CHECK-NEXT: 9 | void Test3::C::f() 263// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] 264// CHECK-NEXT: 10 | vcall_offset (-40) 265// CHECK-NEXT: 11 | vbase_offset (-16) 266// CHECK-NEXT: 12 | offset_to_top (-40) 267// CHECK-NEXT: 13 | Test3::D RTTI 268// CHECK-NEXT: -- (Test3::V2, 40) vtable address -- 269// CHECK-NEXT: 14 | void Test3::C::f() 270// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] 271 272// CHECK: Construction vtable for ('Test3::C', 0) in 'Test3::D' (14 entries). 273// CHECK-NEXT: 0 | vbase_offset (40) 274// CHECK-NEXT: 1 | vbase_offset (24) 275// CHECK-NEXT: 2 | offset_to_top (0) 276// CHECK-NEXT: 3 | Test3::C RTTI 277// CHECK-NEXT: -- (Test3::C, 0) vtable address -- 278// CHECK-NEXT: 4 | void Test3::C::f() 279// CHECK-NEXT: 5 | vcall_offset (-24) 280// CHECK-NEXT: 6 | offset_to_top (-24) 281// CHECK-NEXT: 7 | Test3::C RTTI 282// CHECK-NEXT: -- (Test3::V1, 24) vtable address -- 283// CHECK-NEXT: 8 | void Test3::C::f() 284// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] 285// CHECK-NEXT: 9 | vcall_offset (-40) 286// CHECK-NEXT: 10 | vbase_offset (-16) 287// CHECK-NEXT: 11 | offset_to_top (-40) 288// CHECK-NEXT: 12 | Test3::C RTTI 289// CHECK-NEXT: -- (Test3::V2, 40) vtable address -- 290// CHECK-NEXT: 13 | void Test3::C::f() 291// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] 292 293// CHECK: Construction vtable for ('Test3::V2', 40) in 'Test3::D' (9 entries). 294// CHECK-NEXT: 0 | vcall_offset (0) 295// CHECK-NEXT: 1 | vbase_offset (-16) 296// CHECK-NEXT: 2 | offset_to_top (0) 297// CHECK-NEXT: 3 | Test3::V2 RTTI 298// CHECK-NEXT: -- (Test3::V2, 40) vtable address -- 299// CHECK-NEXT: 4 | void Test3::V2::f() 300// CHECK-NEXT: 5 | vcall_offset (16) 301// CHECK-NEXT: 6 | offset_to_top (16) 302// CHECK-NEXT: 7 | Test3::V2 RTTI 303// CHECK-NEXT: -- (Test3::V1, 24) vtable address -- 304// CHECK-NEXT: 8 | void Test3::V2::f() 305// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] 306struct D : B, C { 307 int d; 308 virtual void g(); 309}; 310void D::g() { } 311 312} 313