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