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 
6 struct 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 };
21 A a;
22 // EMITS-VFTABLE-DAG: @"??_7A@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] }
use(A * obj)23 void use(A *obj) { obj->f(); }
24 
25 struct 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 };
41 B b;
42 // EMITS-VFTABLE-DAG: @"??_7B@@6B@" = linkonce_odr unnamed_addr constant { [5 x i8*] }
use(B * obj)43 void use(B *obj) { obj->f(); }
44 
45 struct 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 };
f()56 void C::f() {}
57 // NO-VFTABLE-NOT: @"??_7C@@6B@"
use(C * obj)58 void use(C *obj) { obj->f(); }
59 
60 struct 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 };
71 D d;
72 // EMITS-VFTABLE-DAG: @"??_7D@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
use(D * obj)73 void use(D *obj) { obj->f(); }
74 
75 struct 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 };
i()91 void E::i() {}
92 // NO-VFTABLE-NOT: @"??_7E@@6B@"
use(E * obj)93 void use(E *obj) { obj->i(); }
94 
95 struct 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 };
109 F f;
110 // EMITS-VFTABLE-DAG: @"??_7F@@6B@" = linkonce_odr unnamed_addr constant { [5 x i8*] }
use(F * obj)111 void use(F *obj) { obj->i(); }
112 
113 struct 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 };
j()130 void G::j() {}
131 // NO-VFTABLE-NOT: @"??_7G@@6B@"
use(G * obj)132 void use(G *obj) { obj->j(); }
133 
134 // Test that the usual Itanium-style key method does not emit a vtable.
135 struct H {
136   virtual void f();
137 };
f()138 void H::f() {}
139 // NO-VFTABLE-NOT: @"??_7H@@6B@"
140 
141 struct Empty { };
142 
143 struct 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 
151 I i;
use(I * obj)152 void use(I *obj) { obj->f(); }
153 
154 struct 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 
170 J j;
use(J * obj)171 void use(J *obj) { obj->foo(42); }
172 
173 struct 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 
189 K k;
use(K * obj)190 void use(K *obj) { obj->foo(42.0f); }
191 
192 struct 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 
212 L l;
use(L * obj)213 void use(L *obj) { obj->foo(42.0f); }
214 
215 struct 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 
237 M m;
use(M * obj)238 void use(M *obj) { obj->foo(42.0f); }
239 
240 struct 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 
252 N n;
use(N * obj)253 void use(N *obj) { obj->operator+(42); }
254 
255 struct O { virtual A *f(); };
256 struct P : O { virtual B *f(); };
257 P p;
use(O * obj)258 void use(O *obj) { obj->f(); }
use(P * obj)259 void 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 
266 struct 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 
276 Q q;
use(Q * obj)277 void use(Q *obj) { obj->foo(42); }
278 
279 // Inherited non-virtual overloads don't participate in the ordering.
280 struct 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 
290 R r;
use(R * obj)291 void use(R *obj) { obj->foo(42l); }
292 
293 struct S {
294   // CHECK-LABEL: VFTable for 'S' (1 entry).
295   // CHECK-NEXT:   0 | void S::f() [deleted]
296   virtual void f() = delete;
297   S();
298   // EMITS-VFTABLE-DAG: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)] }
299 };
300 
S()301 S::S() {}
302 
303 struct T {
304   struct U {};
305 };
306 struct V : T {
307   // CHECK-LABEL: VFTable for 'V' (2 entries).
308   // CHECK-NEXT:   0 | void V::U()
309   // CHECK-NEXT:   1 | void V::f()
310   using T::U;
311   virtual void f();
312   virtual void U();
313   V();
314 };
315 
V()316 V::V() {}
317