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