Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -fdump-vtable-layouts -o - > %t 2>&1
      2 // RUN: FileCheck --check-prefix=EMITS-VTABLE %s < %t
      3 // RUN: FileCheck --check-prefix=NO-VTABLE %s < %t
      4 // RUN: FileCheck --check-prefix=CHECK-A %s < %t
      5 // RUN: FileCheck --check-prefix=CHECK-B %s < %t
      6 // RUN: FileCheck --check-prefix=CHECK-C %s < %t
      7 // RUN: FileCheck --check-prefix=CHECK-D %s < %t
      8 // RUN: FileCheck --check-prefix=CHECK-E %s < %t
      9 // RUN: FileCheck --check-prefix=CHECK-F %s < %t
     10 // RUN: FileCheck --check-prefix=CHECK-G %s < %t
     11 // RUN: FileCheck --check-prefix=CHECK-I %s < %t
     12 
     13 // FIXME: Currently, we only test VFTableContext in the AST, but still use
     14 // VTableContext for CodeGen. We should remove the "Vtable" checks below when we
     15 // completely switch from VTableContext to VFTableContext.
     16 // Currently, the order of Vtable vs VFTable output depends on whether the
     17 // v*table info was required by a constructor or a method definition.
     18 
     19 struct A {
     20   // CHECK-A: Vtable for 'A' (3 entries)
     21   // CHECK-A-NEXT: 0 | void A::f()
     22   // CHECK-A-NEXT: 1 | void A::g()
     23   // CHECK-A-NEXT: 2 | void A::h()
     24 
     25   // CHECK-A: VFTable for 'A' (3 entries)
     26   // CHECK-A-NEXT: 0 | void A::f()
     27   // CHECK-A-NEXT: 1 | void A::g()
     28   // CHECK-A-NEXT: 2 | void A::h()
     29 
     30   virtual void f();
     31   virtual void g();
     32   virtual void h();
     33   int ia;
     34 };
     35 A a;
     36 // EMITS-VTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*]
     37 
     38 struct B : A {
     39   // CHECK-B: Vtable for 'B' (5 entries)
     40   // CHECK-B-NEXT: 0 | void B::f()
     41   // CHECK-B-NEXT: 1 | void A::g()
     42   // CHECK-B-NEXT: 2 | void A::h()
     43   // CHECK-B-NEXT: 3 | void B::i()
     44   // CHECK-B-NEXT: 4 | void B::j()
     45 
     46   // CHECK-B: VFTable for 'A' in 'B' (5 entries)
     47   // CHECK-B-NEXT: 0 | void B::f()
     48   // CHECK-B-NEXT: 1 | void A::g()
     49   // CHECK-B-NEXT: 2 | void A::h()
     50   // CHECK-B-NEXT: 3 | void B::i()
     51   // CHECK-B-NEXT: 4 | void B::j()
     52 
     53   virtual void f();  // overrides A::f()
     54   virtual void i();
     55   virtual void j();
     56 };
     57 B b;
     58 // EMITS-VTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*]
     59 
     60 struct C {
     61   // CHECK-C: VFTable for 'C' (2 entries)
     62   // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
     63   // CHECK-C-NEXT: 1 | void C::f()
     64   // CHECK-C: VFTable indices for 'C' (2 entries).
     65   // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
     66   // CHECK-C-NEXT: 1 | void C::f()
     67 
     68   // CHECK-C: Vtable for 'C' (2 entries)
     69   // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
     70   // CHECK-C-NEXT: 1 | void C::f()
     71   // CHECK-C: VTable indices for 'C' (2 entries).
     72   // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
     73   // CHECK-C-NEXT: 1 | void C::f()
     74 
     75   virtual ~C();
     76   virtual void f();
     77 };
     78 void C::f() {}
     79 // NO-VTABLE-NOT: @"\01??_7C@@6B@"
     80 
     81 struct D {
     82   // CHECK-D: Vtable for 'D' (2 entries)
     83   // CHECK-D-NEXT: 0 | void D::f()
     84   // CHECK-D-NEXT: 1 | D::~D() [scalar deleting]
     85 
     86   // CHECK-D: VFTable for 'D' (2 entries)
     87   // CHECK-D-NEXT: 0 | void D::f()
     88   // CHECK-D-NEXT: 1 | D::~D() [scalar deleting]
     89 
     90   virtual void f();
     91   virtual ~D();
     92 };
     93 D d;
     94 // EMITS-VTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*]
     95 
     96 struct E : A {
     97   // CHECK-E: VFTable for 'A' in 'E' (5 entries)
     98   // CHECK-E-NEXT: 0 | void A::f()
     99   // CHECK-E-NEXT: 1 | void A::g()
    100   // CHECK-E-NEXT: 2 | void A::h()
    101   // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
    102   // CHECK-E-NEXT: 4 | void E::i()
    103   // CHECK-E: VFTable indices for 'E' (2 entries).
    104   // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
    105   // CHECK-E-NEXT: 4 | void E::i()
    106 
    107   // CHECK-E: Vtable for 'E' (5 entries)
    108   // CHECK-E-NEXT: 0 | void A::f()
    109   // CHECK-E-NEXT: 1 | void A::g()
    110   // CHECK-E-NEXT: 2 | void A::h()
    111   // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
    112   // CHECK-E-NEXT: 4 | void E::i()
    113   // CHECK-E: VTable indices for 'E' (2 entries).
    114   // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
    115   // CHECK-E-NEXT: 4 | void E::i()
    116 
    117   // ~E would be the key method, but it isn't used, and MS ABI has no key
    118   // methods.
    119   virtual ~E();
    120   virtual void i();
    121 };
    122 void E::i() {}
    123 // NO-VTABLE-NOT: @"\01??_7E@@6B@"
    124 
    125 struct F : A {
    126   // CHECK-F: Vtable for 'F' (5 entries)
    127   // CHECK-F-NEXT: 0 | void A::f()
    128   // CHECK-F-NEXT: 1 | void A::g()
    129   // CHECK-F-NEXT: 2 | void A::h()
    130   // CHECK-F-NEXT: 3 | void F::i()
    131   // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
    132   // CHECK-F: VTable indices for 'F' (2 entries).
    133   // CHECK-F-NEXT: 3 | void F::i()
    134   // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
    135 
    136   // CHECK-F: VFTable for 'A' in 'F' (5 entries)
    137   // CHECK-F-NEXT: 0 | void A::f()
    138   // CHECK-F-NEXT: 1 | void A::g()
    139   // CHECK-F-NEXT: 2 | void A::h()
    140   // CHECK-F-NEXT: 3 | void F::i()
    141   // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
    142   // CHECK-F: VFTable indices for 'F' (2 entries).
    143   // CHECK-F-NEXT: 3 | void F::i()
    144   // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
    145 
    146   virtual void i();
    147   virtual ~F();
    148 };
    149 F f;
    150 // EMITS-VTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*]
    151 
    152 struct G : E {
    153   // CHECK-G: VFTable for 'A' in 'E' in 'G' (6 entries)
    154   // CHECK-G-NEXT: 0 | void G::f()
    155   // CHECK-G-NEXT: 1 | void A::g()
    156   // CHECK-G-NEXT: 2 | void A::h()
    157   // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
    158   // CHECK-G-NEXT: 4 | void E::i()
    159   // CHECK-G-NEXT: 5 | void G::j()
    160   // CHECK-G: VFTable indices for 'G' (3 entries).
    161   // CHECK-G-NEXT: 0 | void G::f()
    162   // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
    163   // CHECK-G-NEXT: 5 | void G::j()
    164 
    165   // CHECK-G: Vtable for 'G' (6 entries)
    166   // CHECK-G-NEXT: 0 | void G::f()
    167   // CHECK-G-NEXT: 1 | void A::g()
    168   // CHECK-G-NEXT: 2 | void A::h()
    169   // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
    170   // CHECK-G-NEXT: 4 | void E::i()
    171   // CHECK-G-NEXT: 5 | void G::j()
    172   // CHECK-G: VTable indices for 'G' (3 entries).
    173   // CHECK-G-NEXT: 0 | void G::f()
    174   // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
    175   // CHECK-G-NEXT: 5 | void G::j()
    176 
    177   virtual void f();  // overrides A::f()
    178   virtual ~G();
    179   virtual void j();
    180 };
    181 void G::j() {}
    182 // NO-VTABLE-NOT: @"\01??_7G@@6B@"
    183 
    184 // Test that the usual Itanium-style key method does not emit a vtable.
    185 struct H {
    186   virtual void f();
    187 };
    188 void H::f() {}
    189 // NO-VTABLE-NOT: @"\01??_7H@@6B@"
    190 
    191 struct Empty { };
    192 
    193 struct I : Empty {
    194   // CHECK-I: VFTable for 'I' (2 entries)
    195   // CHECK-I-NEXT: 0 | void I::f()
    196   // CHECK-I-NEXT: 1 | void I::g()
    197   virtual void f();
    198   virtual void g();
    199 };
    200 
    201 I i;
    202