brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.5 KiB · b0bf927 Raw
317 lines · cpp
1// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -fdump-vtable-layouts -o %t.ll > %t2// RUN: FileCheck --check-prefix=EMITS-VFTABLE %s < %t.ll3// RUN: FileCheck --check-prefix=NO-VFTABLE %s < %t.ll4// RUN: FileCheck %s < %t5 6struct A {7  // CHECK-LABEL: VFTable for 'A' (3 entries)8  // CHECK-NEXT: 0 | void A::f()9  // CHECK-NEXT: 1 | void A::g()10  // CHECK-NEXT: 2 | void A::h()11  // CHECK-LABEL: VFTable indices for 'A' (3 entries)12  // CHECK-NEXT: 0 | void A::f()13  // CHECK-NEXT: 1 | void A::g()14  // CHECK-NEXT: 2 | void A::h()15 16  virtual void f();17  virtual void g();18  virtual void h();19  int ia;20};21A a;22// EMITS-VFTABLE-DAG: @"??_7A@@6B@" = linkonce_odr unnamed_addr constant { [3 x ptr] }23void use(A *obj) { obj->f(); }24 25struct B : A {26  // CHECK-LABEL: VFTable for 'A' in 'B' (5 entries)27  // CHECK-NEXT: 0 | void B::f()28  // CHECK-NEXT: 1 | void A::g()29  // CHECK-NEXT: 2 | void A::h()30  // CHECK-NEXT: 3 | void B::i()31  // CHECK-NEXT: 4 | void B::j()32  // CHECK-LABEL: VFTable indices for 'B' (3 entries)33  // CHECK-NEXT: 0 | void B::f()34  // CHECK-NEXT: 3 | void B::i()35  // CHECK-NEXT: 4 | void B::j()36 37  virtual void f();  // overrides A::f()38  virtual void i();39  virtual void j();40};41B b;42// EMITS-VFTABLE-DAG: @"??_7B@@6B@" = linkonce_odr unnamed_addr constant { [5 x ptr] }43void use(B *obj) { obj->f(); }44 45struct C {46  // CHECK-LABEL: VFTable for 'C' (2 entries)47  // CHECK-NEXT: 0 | C::~C() [scalar deleting]48  // CHECK-NEXT: 1 | void C::f()49  // CHECK-LABEL: VFTable indices for 'C' (2 entries).50  // CHECK-NEXT: 0 | C::~C() [scalar deleting]51  // CHECK-NEXT: 1 | void C::f()52 53  virtual ~C();54  virtual void f();55};56void C::f() {}57// NO-VFTABLE-NOT: @"??_7C@@6B@"58void use(C *obj) { obj->f(); }59 60struct D {61  // CHECK-LABEL: VFTable for 'D' (2 entries)62  // CHECK-NEXT: 0 | void D::f()63  // CHECK-NEXT: 1 | D::~D() [scalar deleting]64  // CHECK-LABEL: VFTable indices for 'D' (2 entries)65  // CHECK-NEXT: 0 | void D::f()66  // CHECK-NEXT: 1 | D::~D() [scalar deleting]67 68  virtual void f();69  virtual ~D();70};71D d;72// EMITS-VFTABLE-DAG: @"??_7D@@6B@" = linkonce_odr unnamed_addr constant { [2 x ptr] }73void use(D *obj) { obj->f(); }74 75struct E : A {76  // CHECK-LABEL: VFTable for 'A' in 'E' (5 entries)77  // CHECK-NEXT: 0 | void A::f()78  // CHECK-NEXT: 1 | void A::g()79  // CHECK-NEXT: 2 | void A::h()80  // CHECK-NEXT: 3 | E::~E() [scalar deleting]81  // CHECK-NEXT: 4 | void E::i()82  // CHECK-LABEL: VFTable indices for 'E' (2 entries).83  // CHECK-NEXT: 3 | E::~E() [scalar deleting]84  // CHECK-NEXT: 4 | void E::i()85 86  // ~E would be the key method, but it isn't used, and MS ABI has no key87  // methods.88  virtual ~E();89  virtual void i();90};91void E::i() {}92// NO-VFTABLE-NOT: @"??_7E@@6B@"93void use(E *obj) { obj->i(); }94 95struct F : A {96  // CHECK-LABEL: VFTable for 'A' in 'F' (5 entries)97  // CHECK-NEXT: 0 | void A::f()98  // CHECK-NEXT: 1 | void A::g()99  // CHECK-NEXT: 2 | void A::h()100  // CHECK-NEXT: 3 | void F::i()101  // CHECK-NEXT: 4 | F::~F() [scalar deleting]102  // CHECK-LABEL: VFTable indices for 'F' (2 entries).103  // CHECK-NEXT: 3 | void F::i()104  // CHECK-NEXT: 4 | F::~F() [scalar deleting]105 106  virtual void i();107  virtual ~F();108};109F f;110// EMITS-VFTABLE-DAG: @"??_7F@@6B@" = linkonce_odr unnamed_addr constant { [5 x ptr] }111void use(F *obj) { obj->i(); }112 113struct G : E {114  // CHECK-LABEL: VFTable for 'A' in 'E' in 'G' (6 entries)115  // CHECK-NEXT: 0 | void G::f()116  // CHECK-NEXT: 1 | void A::g()117  // CHECK-NEXT: 2 | void A::h()118  // CHECK-NEXT: 3 | G::~G() [scalar deleting]119  // CHECK-NEXT: 4 | void E::i()120  // CHECK-NEXT: 5 | void G::j()121  // CHECK-LABEL: VFTable indices for 'G' (3 entries).122  // CHECK-NEXT: 0 | void G::f()123  // CHECK-NEXT: 3 | G::~G() [scalar deleting]124  // CHECK-NEXT: 5 | void G::j()125 126  virtual void f();  // overrides A::f()127  virtual ~G();128  virtual void j();129};130void G::j() {}131// NO-VFTABLE-NOT: @"??_7G@@6B@"132void use(G *obj) { obj->j(); }133 134// Test that the usual Itanium-style key method does not emit a vtable.135struct H {136  virtual void f();137};138void H::f() {}139// NO-VFTABLE-NOT: @"??_7H@@6B@"140 141struct Empty { };142 143struct I : Empty {144  // CHECK-LABEL: VFTable for 'I' (2 entries)145  // CHECK-NEXT: 0 | void I::f()146  // CHECK-NEXT: 1 | void I::g()147  virtual void f();148  virtual void g();149};150 151I i;152void use(I *obj) { obj->f(); }153 154struct J {155  // CHECK-LABEL: VFTable for 'J' (6 entries)156  // CHECK-NEXT: 0 | void J::foo(long)157  // CHECK-NEXT: 1 | void J::foo(int)158  // CHECK-NEXT: 2 | void J::foo(short)159  // CHECK-NEXT: 3 | void J::bar(long)160  // CHECK-NEXT: 4 | void J::bar(int)161  // CHECK-NEXT: 5 | void J::bar(short)162  virtual void foo(short);163  virtual void bar(short);164  virtual void foo(int);165  virtual void bar(int);166  virtual void foo(long);167  virtual void bar(long);168};169 170J j;171void use(J *obj) { obj->foo(42); }172 173struct K : J {174  // CHECK-LABEL: VFTable for 'J' in 'K' (9 entries)175  // CHECK-NEXT: 0 | void J::foo(long)176  // CHECK-NEXT: 1 | void J::foo(int)177  // CHECK-NEXT: 2 | void J::foo(short)178  // CHECK-NEXT: 3 | void J::bar(long)179  // CHECK-NEXT: 4 | void J::bar(int)180  // CHECK-NEXT: 5 | void J::bar(short)181  // CHECK-NEXT: 6 | void K::bar(double)182  // CHECK-NEXT: 7 | void K::bar(float)183  // CHECK-NEXT: 8 | void K::foo(float)184  virtual void bar(float);185  virtual void foo(float);186  virtual void bar(double);187};188 189K k;190void use(K *obj) { obj->foo(42.0f); }191 192struct L : J {193  // CHECK-LABEL: VFTable for 'J' in 'L' (9 entries)194  // CHECK-NEXT: 0 | void J::foo(long)195  // CHECK-NEXT: 1 | void L::foo(int)196  // CHECK-NEXT: 2 | void J::foo(short)197  // CHECK-NEXT: 3 | void J::bar(long)198  // CHECK-NEXT: 4 | void J::bar(int)199  // CHECK-NEXT: 5 | void J::bar(short)200  // CHECK-NEXT: 6 | void L::foo(float)201  // CHECK-NEXT: 7 | void L::bar(double)202  // CHECK-NEXT: 8 | void L::bar(float)203 204  // This case is interesting. Since the J::foo(int) override is the first method in205  // the class, foo(float) precedes the bar(double) and bar(float) in the vftable.206  virtual void foo(int);207  virtual void bar(float);208  virtual void foo(float);209  virtual void bar(double);210};211 212L l;213void use(L *obj) { obj->foo(42.0f); }214 215struct M : J {216  // CHECK-LABEL: VFTable for 'J' in 'M' (11 entries)217  // CHECK-NEXT:  0 | void J::foo(long)218  // CHECK-NEXT:  1 | void M::foo(int)219  // CHECK-NEXT:  2 | void J::foo(short)220  // CHECK-NEXT:  3 | void J::bar(long)221  // CHECK-NEXT:  4 | void J::bar(int)222  // CHECK-NEXT:  5 | void J::bar(short)223  // CHECK-NEXT:  6 | void M::foo(float)224  // CHECK-NEXT:  7 | void M::spam(long)225  // CHECK-NEXT:  8 | void M::spam(int)226  // CHECK-NEXT:  9 | void M::bar(double)227  // CHECK-NEXT: 10 | void M::bar(float)228 229  virtual void foo(int);230  virtual void spam(int);231  virtual void bar(float);232  virtual void bar(double);233  virtual void foo(float);234  virtual void spam(long);235};236 237M m;238void use(M *obj) { obj->foo(42.0f); }239 240struct N {241  // CHECK-LABEL: VFTable for 'N' (4 entries)242  // CHECK-NEXT: 0 | void N::operator+(int)243  // CHECK-NEXT: 1 | void N::operator+(short)244  // CHECK-NEXT: 2 | void N::operator*(int)245  // CHECK-NEXT: 3 | void N::operator*(short)246  virtual void operator+(short);247  virtual void operator*(short);248  virtual void operator+(int);249  virtual void operator*(int);250};251 252N n;253void use(N *obj) { obj->operator+(42); }254 255struct O { virtual A *f(); };256struct P : O { virtual B *f(); };257P p;258void use(O *obj) { obj->f(); }259void use(P *obj) { obj->f(); }260// CHECK-LABEL: VFTable for 'O' (1 entry)261// CHECK-NEXT: 0 | A *O::f()262 263// CHECK-LABEL: VFTable for 'O' in 'P' (1 entry)264// CHECK-NEXT: 0 | B *P::f()265 266struct Q {267  // CHECK-LABEL: VFTable for 'Q' (2 entries)268  // CHECK-NEXT: 0 | void Q::foo(int)269  // CHECK-NEXT: 1 | void Q::bar(int)270  void foo(short);271  void bar(short);272  virtual void bar(int);273  virtual void foo(int);274};275 276Q q;277void use(Q *obj) { obj->foo(42); }278 279// Inherited non-virtual overloads don't participate in the ordering.280struct R : Q {281  // CHECK-LABEL: VFTable for 'Q' in 'R' (4 entries)282  // CHECK-NEXT: 0 | void Q::foo(int)283  // CHECK-NEXT: 1 | void Q::bar(int)284  // CHECK-NEXT: 2 | void R::bar(long)285  // CHECK-NEXT: 3 | void R::foo(long)286  virtual void bar(long);287  virtual void foo(long);288};289 290R r;291void use(R *obj) { obj->foo(42l); }292 293struct S {294  // CHECK-LABEL: VFTable for 'S' (1 entry).295  // CHECK-NEXT:   0 | void S::f() [deleted]296  virtual void f() = delete;297  S();298  // EMITS-VFTABLE-DAG: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @_purecall] }299};300 301S::S() {}302 303struct T {304  struct U {};305};306struct V : T {307  // CHECK-LABEL: VFTable for 'V' (2 entries).308  // CHECK-NEXT:   0 | void V::U()309  // CHECK-NEXT:   1 | void V::f()310  using T::U;311  virtual void f();312  virtual void U();313  V();314};315 316V::V() {}317