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=CHECK-A %s < %t 4 // RUN: FileCheck --check-prefix=CHECK-B %s < %t 5 // RUN: FileCheck --check-prefix=CHECK-C %s < %t 6 // RUN: FileCheck --check-prefix=CHECK-D %s < %t 7 // RUN: FileCheck --check-prefix=CHECK-E %s < %t 8 // RUN: FileCheck --check-prefix=CHECK-F %s < %t 9 // RUN: FileCheck --check-prefix=CHECK-G %s < %t 10 11 struct A { 12 // CHECK-A: Vtable for 'A' (3 entries) 13 // CHECK-A-NEXT: 0 | void A::f() 14 // CHECK-A-NEXT: 1 | void A::g() 15 // CHECK-A-NEXT: 2 | void A::h() 16 // EMITS-VTABLE: @"\01??_7A@@6B@" = unnamed_addr constant [3 x i8*] 17 virtual void f(); 18 virtual void g(); 19 virtual void h(); 20 int ia; 21 }; 22 void A::f() {} 23 24 struct B : A { 25 // CHECK-B: Vtable for 'B' (5 entries) 26 // CHECK-B-NEXT: 0 | void B::f() 27 // CHECK-B-NEXT: 1 | void A::g() 28 // CHECK-B-NEXT: 2 | void A::h() 29 // CHECK-B-NEXT: 3 | void B::i() 30 // CHECK-B-NEXT: 4 | void B::j() 31 // EMITS-VTABLE: @"\01??_7B@@6B@" = unnamed_addr constant [5 x i8*] 32 virtual void f(); // overrides A::f() 33 virtual void i(); 34 virtual void j(); 35 }; 36 void B::f() {} 37 38 struct C { 39 // CHECK-C: Vtable for 'C' (2 entries) 40 // CHECK-C-NEXT: 0 | C::~C() [scalar deleting] 41 // CHECK-C-NEXT: 1 | void C::f() 42 // CHECK-C: VTable indices for 'C' (2 entries). 43 // CHECK-C-NEXT: 0 | C::~C() [scalar deleting] 44 // CHECK-C-NEXT: 1 | void C::f() 45 // Never used, so doesn't emit a vtable. 46 virtual ~C(); 47 48 virtual void f(); 49 }; 50 void C::f() {} 51 52 struct D { 53 // CHECK-D: Vtable for 'D' (2 entries) 54 // CHECK-D-NEXT: 0 | void D::f() 55 // CHECK-D-NEXT: 1 | D::~D() [scalar deleting] 56 // EMITS-VTABLE: @"\01??_7D@@6B@" = unnamed_addr constant [2 x i8*] 57 virtual void f(); 58 59 virtual ~D(); 60 }; 61 void D::f() {} 62 63 struct E : A { 64 // CHECK-E: Vtable for 'E' (5 entries) 65 // CHECK-E-NEXT: 0 | void A::f() 66 // CHECK-E-NEXT: 1 | void A::g() 67 // CHECK-E-NEXT: 2 | void A::h() 68 // CHECK-E-NEXT: 3 | E::~E() [scalar deleting] 69 // CHECK-E-NEXT: 4 | void E::i() 70 // CHECK-E: VTable indices for 'E' (2 entries). 71 // CHECK-E-NEXT: 3 | E::~E() [scalar deleting] 72 // CHECK-E-NEXT: 4 | void E::i() 73 74 // Never used, so doesn't emit a vtable. 75 virtual ~E(); 76 virtual void i(); 77 }; 78 void E::i() {} 79 80 struct F : A { 81 // CHECK-F: Vtable for 'F' (5 entries) 82 // CHECK-F-NEXT: 0 | void A::f() 83 // CHECK-F-NEXT: 1 | void A::g() 84 // CHECK-F-NEXT: 2 | void A::h() 85 // CHECK-F-NEXT: 3 | void F::i() 86 // CHECK-F-NEXT: 4 | F::~F() [scalar deleting] 87 // CHECK-F: VTable indices for 'F' (2 entries). 88 // CHECK-F-NEXT: 3 | void F::i() 89 // CHECK-F-NEXT: 4 | F::~F() [scalar deleting] 90 // EMITS-VTABLE: @"\01??_7F@@6B@" = unnamed_addr constant [5 x i8*] 91 virtual void i(); 92 virtual ~F(); 93 }; 94 void F::i() {} 95 96 struct G : E { 97 // CHECK-G: Vtable for 'G' (6 entries) 98 // CHECK-G-NEXT: 0 | void G::f() 99 // CHECK-G-NEXT: 1 | void A::g() 100 // CHECK-G-NEXT: 2 | void A::h() 101 // CHECK-G-NEXT: 3 | G::~G() [scalar deleting] 102 // CHECK-G-NEXT: 4 | void E::i() 103 // CHECK-G-NEXT: 5 | void G::j() 104 // CHECK-G: VTable indices for 'G' (3 entries). 105 // CHECK-G-NEXT: 0 | void G::f() 106 // CHECK-G-NEXT: 3 | G::~G() [scalar deleting] 107 // CHECK-G-NEXT: 5 | void G::j() 108 // Never used, so doesn't emit a vtable. 109 virtual void f(); // overrides A::f() 110 virtual ~G(); 111 virtual void j(); 112 }; 113 void G::j() {} 114