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 12 struct A { 13 // CHECK-A: Vtable for 'A' (3 entries) 14 // CHECK-A-NEXT: 0 | void A::f() 15 // CHECK-A-NEXT: 1 | void A::g() 16 // CHECK-A-NEXT: 2 | void A::h() 17 virtual void f(); 18 virtual void g(); 19 virtual void h(); 20 int ia; 21 }; 22 A a; 23 // EMITS-VTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*] 24 25 struct B : A { 26 // CHECK-B: Vtable for 'B' (5 entries) 27 // CHECK-B-NEXT: 0 | void B::f() 28 // CHECK-B-NEXT: 1 | void A::g() 29 // CHECK-B-NEXT: 2 | void A::h() 30 // CHECK-B-NEXT: 3 | void B::i() 31 // CHECK-B-NEXT: 4 | void B::j() 32 virtual void f(); // overrides A::f() 33 virtual void i(); 34 virtual void j(); 35 }; 36 B b; 37 // EMITS-VTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*] 38 39 struct C { 40 // CHECK-C: Vtable for 'C' (2 entries) 41 // CHECK-C-NEXT: 0 | C::~C() [scalar deleting] 42 // CHECK-C-NEXT: 1 | void C::f() 43 // CHECK-C: VTable indices for 'C' (2 entries). 44 // CHECK-C-NEXT: 0 | C::~C() [scalar deleting] 45 // CHECK-C-NEXT: 1 | void C::f() 46 virtual ~C(); 47 48 virtual void f(); 49 }; 50 void C::f() {} 51 // NO-VTABLE-NOT: @"\01??_7C@@6B@" 52 53 struct D { 54 // CHECK-D: Vtable for 'D' (2 entries) 55 // CHECK-D-NEXT: 0 | void D::f() 56 // CHECK-D-NEXT: 1 | D::~D() [scalar deleting] 57 virtual void f(); 58 59 virtual ~D(); 60 }; 61 D d; 62 // EMITS-VTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*] 63 64 struct E : A { 65 // CHECK-E: Vtable for 'E' (5 entries) 66 // CHECK-E-NEXT: 0 | void A::f() 67 // CHECK-E-NEXT: 1 | void A::g() 68 // CHECK-E-NEXT: 2 | void A::h() 69 // CHECK-E-NEXT: 3 | E::~E() [scalar deleting] 70 // CHECK-E-NEXT: 4 | void E::i() 71 // CHECK-E: VTable indices for 'E' (2 entries). 72 // CHECK-E-NEXT: 3 | E::~E() [scalar deleting] 73 // CHECK-E-NEXT: 4 | void E::i() 74 75 // ~E would be the key method, but it isn't used, and MS ABI has no key 76 // methods. 77 virtual ~E(); 78 virtual void i(); 79 }; 80 void E::i() {} 81 // NO-VTABLE-NOT: @"\01??_7E@@6B@" 82 83 struct F : A { 84 // CHECK-F: Vtable for 'F' (5 entries) 85 // CHECK-F-NEXT: 0 | void A::f() 86 // CHECK-F-NEXT: 1 | void A::g() 87 // CHECK-F-NEXT: 2 | void A::h() 88 // CHECK-F-NEXT: 3 | void F::i() 89 // CHECK-F-NEXT: 4 | F::~F() [scalar deleting] 90 // CHECK-F: VTable indices for 'F' (2 entries). 91 // CHECK-F-NEXT: 3 | void F::i() 92 // CHECK-F-NEXT: 4 | F::~F() [scalar deleting] 93 virtual void i(); 94 virtual ~F(); 95 }; 96 F f; 97 // EMITS-VTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*] 98 99 struct G : E { 100 // CHECK-G: Vtable for 'G' (6 entries) 101 // CHECK-G-NEXT: 0 | void G::f() 102 // CHECK-G-NEXT: 1 | void A::g() 103 // CHECK-G-NEXT: 2 | void A::h() 104 // CHECK-G-NEXT: 3 | G::~G() [scalar deleting] 105 // CHECK-G-NEXT: 4 | void E::i() 106 // CHECK-G-NEXT: 5 | void G::j() 107 // CHECK-G: VTable indices for 'G' (3 entries). 108 // CHECK-G-NEXT: 0 | void G::f() 109 // CHECK-G-NEXT: 3 | G::~G() [scalar deleting] 110 // CHECK-G-NEXT: 5 | void G::j() 111 virtual void f(); // overrides A::f() 112 virtual ~G(); 113 virtual void j(); 114 }; 115 void G::j() {} 116 // NO-VTABLE-NOT: @"\01??_7G@@6B@" 117 118 // Test that the usual Itanium-style key method does not emit a vtable. 119 struct H { 120 virtual void f(); 121 }; 122 void H::f() {} 123 // NO-VTABLE-NOT: @"\01??_7H@@6B@" 124