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