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 };
f()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 };
f()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 };
f()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 };
f()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 };
i()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 };
i()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 };
j()113 void G::j() {}
114