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