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