Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -fdump-vtable-layouts -o %t.ll > %t
      2 // RUN: FileCheck --check-prefix=EMITS-VFTABLE %s < %t.ll
      3 // RUN: FileCheck --check-prefix=NO-VFTABLE %s < %t.ll
      4 // RUN: FileCheck %s < %t
      5 
      6 struct 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 };
     21 A a;
     22 // EMITS-VFTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*]
     23 void use(A *obj) { obj->f(); }
     24 
     25 struct 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 };
     41 B b;
     42 // EMITS-VFTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*]
     43 void use(B *obj) { obj->f(); }
     44 
     45 struct 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 };
     56 void C::f() {}
     57 // NO-VFTABLE-NOT: @"\01??_7C@@6B@"
     58 void use(C *obj) { obj->f(); }
     59 
     60 struct 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 };
     71 D d;
     72 // EMITS-VFTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*]
     73 void use(D *obj) { obj->f(); }
     74 
     75 struct 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 key
     87   // methods.
     88   virtual ~E();
     89   virtual void i();
     90 };
     91 void E::i() {}
     92 // NO-VFTABLE-NOT: @"\01??_7E@@6B@"
     93 void use(E *obj) { obj->i(); }
     94 
     95 struct 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 };
    109 F f;
    110 // EMITS-VFTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*]
    111 void use(F *obj) { obj->i(); }
    112 
    113 struct 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 };
    130 void G::j() {}
    131 // NO-VFTABLE-NOT: @"\01??_7G@@6B@"
    132 void use(G *obj) { obj->j(); }
    133 
    134 // Test that the usual Itanium-style key method does not emit a vtable.
    135 struct H {
    136   virtual void f();
    137 };
    138 void H::f() {}
    139 // NO-VFTABLE-NOT: @"\01??_7H@@6B@"
    140 
    141 struct Empty { };
    142 
    143 struct 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 
    151 I i;
    152 void use(I *obj) { obj->f(); }
    153 
    154 struct 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 
    170 J j;
    171 void use(J *obj) { obj->foo(42); }
    172 
    173 struct 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 
    189 K k;
    190 void use(K *obj) { obj->foo(42.0f); }
    191 
    192 struct 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 in
    205   // 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 
    212 L l;
    213 void use(L *obj) { obj->foo(42.0f); }
    214 
    215 struct 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 
    237 M m;
    238 void use(M *obj) { obj->foo(42.0f); }
    239 
    240 struct 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 
    252 N n;
    253 void use(N *obj) { obj->operator+(42); }
    254 
    255 struct O { virtual A *f(); };
    256 struct P : O { virtual B *f(); };
    257 P p;
    258 void use(O *obj) { obj->f(); }
    259 void 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 
    266 struct 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 
    276 Q q;
    277 void use(Q *obj) { obj->foo(42); }
    278 
    279 // Inherited non-virtual overloads don't participate in the ordering.
    280 struct 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 
    290 R r;
    291 void use(R *obj) { obj->foo(42l); }
    292 
    293 struct 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: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)]
    299 };
    300 
    301 S::S() {}
    302 
    303 struct T {
    304   struct U {};
    305 };
    306 struct 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 
    316 V::V() {}
    317