brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.0 KiB · 62289e4 Raw
303 lines · cpp
1// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t2// RUN: FileCheck %s < %t3// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll4 5namespace test1 {6struct A {7  virtual void f();8};9 10struct B {11  virtual void g();12  // Add an extra virtual method so it's easier to check for the absence of thunks.13  virtual void h();14};15 16struct X : A, B {17  // CHECK-LABEL: VFTable for 'test1::A' in 'test1::X' (1 entry)18  // CHECK-NEXT:   0 | void test1::X::f()19 20  // CHECK-LABEL: VFTable for 'test1::B' in 'test1::X' (2 entries)21  // CHECK-NEXT:   0 | void test1::B::g()22  // CHECK-NEXT:   1 | void test1::B::h()23 24  // CHECK-LABEL: VFTable indices for 'test1::X' (1 entry)25  // CHECK-NEXT:   0 | void test1::X::f()26 27  // MANGLING-DAG: @"??_7X@test1@@6BA@1@@"28  // MANGLING-DAG: @"??_7X@test1@@6BB@1@@"29 30  // Overrides only the left child's method (A::f), needs no thunks.31  virtual void f();32} x;33 34void build_vftable(X *obj) { obj->f(); }35}36 37namespace test2 {38struct A {39  virtual void f();40};41 42struct B {43  virtual void g();44  virtual void h();45};46 47struct X : A, B {48  // CHECK-LABEL: VFTable for 'test2::A' in 'test2::X' (1 entry)49  // CHECK-NEXT:   0 | void test2::A::f()50 51  // CHECK-LABEL: VFTable for 'test2::B' in 'test2::X' (2 entries)52  // CHECK-NEXT:   0 | void test2::X::g()53  // CHECK-NEXT:   1 | void test2::B::h()54 55  // CHECK-LABEL: VFTable indices for 'test2::X' (1 entry).56  // CHECK-NEXT:   via vfptr at offset 457  // CHECK-NEXT:   0 | void test2::X::g()58 59  // Overrides only the right child's method (B::g), needs this adjustment but60  // not thunks.61  virtual void g();62};63 64void build_vftable(X *obj) { obj->g(); }65}66 67namespace test3 {68struct A {69  virtual void f();70};71 72struct B {73  virtual void g();74  virtual void h();75};76 77struct X : A, B {78  // CHECK-LABEL: VFTable for 'test3::A' in 'test3::X' (2 entries)79  // CHECK-NEXT:   0 | void test3::A::f()80  // CHECK-NEXT:   1 | void test3::X::i()81 82  // CHECK-LABEL: VFTable for 'test3::B' in 'test3::X' (2 entries)83  // CHECK-NEXT:   0 | void test3::B::g()84  // CHECK-NEXT:   1 | void test3::B::h()85 86  // CHECK-LABEL: VFTable indices for 'test3::X' (1 entry).87  // CHECK-NEXT:   1 | void test3::X::i()88 89  // Only adds a new method.90  virtual void i();91};92 93void build_vftable(X *obj) { obj->i(); }94}95 96namespace test4 {97struct A {98  virtual void f();99};100 101struct Empty { };  // Doesn't have a vftable!102 103// Only the right base has a vftable, so it's laid out before the left one!104struct X : Empty, A {105  // CHECK-LABEL: VFTable for 'test4::A' in 'test4::X' (1 entry)106  // CHECK-NEXT:   0 | void test4::X::f()107 108  // CHECK-LABEL: VFTable indices for 'test4::X' (1 entry).109  // CHECK-NEXT:   0 | void test4::X::f()110 111  // MANGLING-DAG: @"??_7X@test4@@6B@"112 113  virtual void f();114} x;115 116void build_vftable(X *obj) { obj->f(); }117}118 119namespace test5 {120struct A {121  virtual void f();122};123 124struct B {125  virtual void g();126  virtual void h();127};128 129struct C : A, B {130  virtual void f();131};132 133struct X : C {134  // CHECK-LABEL: VFTable for 'test5::A' in 'test5::C' in 'test5::X' (1 entry).135  // CHECK-NEXT:   0 | void test5::X::f()136 137  // CHECK-LABEL: VFTable for 'test5::B' in 'test5::C' in 'test5::X' (2 entries).138  // CHECK-NEXT:   0 | void test5::B::g()139  // CHECK-NEXT:   1 | void test5::B::h()140 141  // CHECK-LABEL: VFTable indices for 'test5::X' (1 entry).142  // CHECK-NEXT:   0 | void test5::X::f()143 144  // MANGLING-DAG: @"??_7X@test5@@6BA@1@@"145  // MANGLING-DAG: @"??_7X@test5@@6BB@1@@"146 147  // Overrides both C::f and A::f.148  virtual void f();149} x;150 151void build_vftable(X *obj) { obj->f(); }152}153 154namespace test6 {155struct A {156  virtual void f();157};158 159struct B {160  virtual void g();161  virtual void h();162};163 164struct C : A, B {165  virtual void g();166};167 168struct X : C {169  // CHECK-LABEL: VFTable for 'test6::A' in 'test6::C' in 'test6::X' (1 entry).170  // CHECK-NEXT:   0 | void test6::A::f()171 172  // CHECK-LABEL: VFTable for 'test6::B' in 'test6::C' in 'test6::X' (2 entries).173  // CHECK-NEXT:   0 | void test6::X::g()174  // CHECK-NEXT:   1 | void test6::B::h()175 176  // CHECK-LABEL: VFTable indices for 'test6::X' (1 entry).177  // CHECK-NEXT:   via vfptr at offset 4178  // CHECK-NEXT:   0 | void test6::X::g()179 180  // Overrides both C::g and B::g.181  virtual void g();182};183 184void build_vftable(X *obj) { obj->g(); }185}186 187namespace test7 {188struct A {189  virtual void f();190};191 192struct B {193  virtual void g();194  virtual void h();195};196 197struct C : A, B {198  // Only adds a new method.199  virtual void i();200};201 202struct X : C {203  // CHECK-LABEL: VFTable for 'test7::A' in 'test7::C' in 'test7::X' (2 entries).204  // CHECK-NEXT:   0 | void test7::A::f()205  // CHECK-NEXT:   1 | void test7::C::i()206 207  // CHECK-LABEL: VFTable for 'test7::B' in 'test7::C' in 'test7::X' (2 entries).208  // CHECK-NEXT:   0 | void test7::X::g()209  // CHECK-NEXT:   1 | void test7::B::h()210 211  // CHECK-LABEL: VFTable indices for 'test7::X' (1 entry).212  // CHECK-NEXT:   via vfptr at offset 4213  // CHECK-NEXT:   0 | void test7::X::g()214 215  // Overrides grandparent's B::g.216  virtual void g();217};218 219void build_vftable(X *obj) { obj->g(); }220}221 222namespace test8 {223struct A {224  virtual void f();225};226 227struct B : A {228  virtual void g();229};230 231// There are two 'A' subobjects in this class.232struct X : A, B {233  // CHECK-LABEL: VFTable for 'test8::A' in 'test8::X' (2 entries).234  // CHECK-NEXT:   0 | void test8::A::f()235  // CHECK-NEXT:   1 | void test8::X::h()236 237  // CHECK-LABEL: VFTable for 'test8::A' in 'test8::B' in 'test8::X' (2 entries).238  // CHECK-NEXT:   0 | void test8::A::f()239  // CHECK-NEXT:   1 | void test8::B::g()240 241  // CHECK-LABEL: VFTable indices for 'test8::X' (1 entry).242  // CHECK-NEXT:   1 | void test8::X::h()243 244  // MANGLING-DAG: @"??_7X@test8@@6BA@1@@"245  // MANGLING-DAG: @"??_7X@test8@@6BB@1@@"246 247  virtual void h();248} x;249 250void build_vftable(X *obj) { obj->h(); }251}252 253namespace test9 {254struct A {255  virtual void f();256};257 258struct B {259  virtual void g();260  virtual void h();261};262 263struct C : A, B {264  // Overrides only the left child's method (A::f).265  virtual void f();266};267 268struct D : A, B {269  // Overrides only the right child's method (B::g).270  virtual void g();271};272 273// 2-level structure with repeating subobject types, but no thunks needed.274struct X : C, D {275  // CHECK-LABEL: VFTable for 'test9::A' in 'test9::C' in 'test9::X' (2 entries)276  // CHECK-NEXT:   0 | void test9::C::f()277  // CHECK-NEXT:   1 | void test9::X::z()278 279  // CHECK-LABEL: VFTable for 'test9::B' in 'test9::C' in 'test9::X' (2 entries)280  // CHECK-NEXT:   0 | void test9::B::g()281  // CHECK-NEXT:   1 | void test9::B::h()282 283  // CHECK-LABEL: VFTable for 'test9::A' in 'test9::D' in 'test9::X' (1 entry)284  // CHECK-NEXT:   0 | void test9::A::f()285 286  // CHECK-LABEL: VFTable for 'test9::B' in 'test9::D' in 'test9::X' (2 entries)287  // CHECK-NEXT:   0 | void test9::D::g()288  // CHECK-NEXT:   1 | void test9::B::h()289 290  // CHECK-LABEL: VFTable indices for 'test9::X' (1 entry).291  // CHECK-NEXT:   1 | void test9::X::z()292 293  // MANGLING-DAG: @"??_7X@test9@@6BA@1@C@1@@"294  // MANGLING-DAG: @"??_7X@test9@@6BA@1@D@1@@"295  // MANGLING-DAG: @"??_7X@test9@@6BB@1@C@1@@"296  // MANGLING-DAG: @"??_7X@test9@@6BB@1@D@1@@"297 298  virtual void z();299} x;300 301void build_vftable(test9::X *obj) { obj->z(); }302}303