1*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 -std=c++11 -fms-extensions -fno-rtti -emit-llvm -o %t.ll -fdump-vtable-layouts %s -triple=i386-pc-win32 >%t
2*0a6a1f1dSLionel Sambuc // RUN: FileCheck %s < %t
3f4a2713aSLionel Sambuc // RUN: FileCheck --check-prefix=MANGLING %s < %t.ll
4f4a2713aSLionel Sambuc 
5f4a2713aSLionel Sambuc struct Empty { };
6f4a2713aSLionel Sambuc 
7f4a2713aSLionel Sambuc struct A {
8f4a2713aSLionel Sambuc   virtual void f();
9f4a2713aSLionel Sambuc   virtual void z();  // Useful to check there are no thunks for f() when appropriate.
10f4a2713aSLionel Sambuc };
11f4a2713aSLionel Sambuc 
12f4a2713aSLionel Sambuc struct B {
13f4a2713aSLionel Sambuc   virtual void g();
14f4a2713aSLionel Sambuc };
15f4a2713aSLionel Sambuc 
16f4a2713aSLionel Sambuc struct C: virtual A {
17*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'C' (2 entries)
18*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void C::f()
19*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
20f4a2713aSLionel Sambuc 
21*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable indices for 'C' (1 entry)
22*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: vbtable index 1, vfptr at offset 0
23*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void C::f()
24f4a2713aSLionel Sambuc 
25f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7C@@6B@"
26f4a2713aSLionel Sambuc 
fC27*0a6a1f1dSLionel Sambuc   virtual void f() {}
28f4a2713aSLionel Sambuc };
29f4a2713aSLionel Sambuc 
30f4a2713aSLionel Sambuc C c;
use(C * obj)31*0a6a1f1dSLionel Sambuc void use(C *obj) { obj->f(); }
32f4a2713aSLionel Sambuc 
33f4a2713aSLionel Sambuc struct D: virtual A {
34*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'D' (1 entry).
35*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void D::h()
36f4a2713aSLionel Sambuc 
37*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'D' (2 entries).
38*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void D::f()
39*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
40f4a2713aSLionel Sambuc 
41*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable indices for 'D' (2 entries).
42*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: via vfptr at offset 0
43*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void D::h()
44*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: via vbtable index 1, vfptr at offset 0
45*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void D::f()
46f4a2713aSLionel Sambuc 
47f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7D@@6B0@@"
48f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7D@@6BA@@@"
49f4a2713aSLionel Sambuc 
50f4a2713aSLionel Sambuc   virtual void f();
51f4a2713aSLionel Sambuc   virtual void h();
52f4a2713aSLionel Sambuc };
53f4a2713aSLionel Sambuc 
54f4a2713aSLionel Sambuc D d;
use(D * obj)55*0a6a1f1dSLionel Sambuc void use(D *obj) { obj->h(); }
56f4a2713aSLionel Sambuc 
57f4a2713aSLionel Sambuc namespace Test1 {
58f4a2713aSLionel Sambuc 
59f4a2713aSLionel Sambuc struct X { int x; };
60f4a2713aSLionel Sambuc 
61f4a2713aSLionel Sambuc // X and A get reordered in the layout since X doesn't have a vfptr while A has.
62f4a2713aSLionel Sambuc struct Y : X, A { };
63f4a2713aSLionel Sambuc // MANGLING-DAG: @"\01??_7Y@Test1@@6B@"
64f4a2713aSLionel Sambuc 
65f4a2713aSLionel Sambuc struct Z : virtual Y {
66*0a6a1f1dSLionel Sambuc   Z();
67*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'Test1::Y' in 'Test1::Z' (2 entries).
68*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void A::f()
69*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
70f4a2713aSLionel Sambuc 
71*0a6a1f1dSLionel Sambuc   // CHECK-NOT: VFTable indices for 'Test1::Z'
72f4a2713aSLionel Sambuc 
73f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7Z@Test1@@6B@"
74f4a2713aSLionel Sambuc };
75f4a2713aSLionel Sambuc 
Z()76*0a6a1f1dSLionel Sambuc Z::Z() {}
77f4a2713aSLionel Sambuc }
78f4a2713aSLionel Sambuc 
79f4a2713aSLionel Sambuc namespace Test2 {
80f4a2713aSLionel Sambuc 
81f4a2713aSLionel Sambuc struct X: virtual A, virtual B {
82*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'Test2::X' (1 entry).
83*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test2::X::h()
84f4a2713aSLionel Sambuc 
85*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'Test2::X' (2 entries).
86*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void A::f()
87*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
88f4a2713aSLionel Sambuc 
89*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'B' in 'Test2::X' (1 entry).
90*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void B::g()
91f4a2713aSLionel Sambuc 
92*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable indices for 'Test2::X' (1 entry).
93*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test2::X::h()
94f4a2713aSLionel Sambuc 
95f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7X@Test2@@6B01@@"
96f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7X@Test2@@6BA@@@"
97f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7X@Test2@@6BB@@@"
98f4a2713aSLionel Sambuc 
99f4a2713aSLionel Sambuc   virtual void h();
100f4a2713aSLionel Sambuc };
101f4a2713aSLionel Sambuc 
102f4a2713aSLionel Sambuc X x;
use(X * obj)103*0a6a1f1dSLionel Sambuc void use(X *obj) { obj->h(); }
104f4a2713aSLionel Sambuc }
105f4a2713aSLionel Sambuc 
106f4a2713aSLionel Sambuc namespace Test3 {
107f4a2713aSLionel Sambuc 
108f4a2713aSLionel Sambuc struct X : virtual A {
109f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7X@Test3@@6B@"
110f4a2713aSLionel Sambuc };
111f4a2713aSLionel Sambuc 
112f4a2713aSLionel Sambuc struct Y: virtual X {
113*0a6a1f1dSLionel Sambuc   Y();
114*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'Test3::X' in 'Test3::Y' (2 entries).
115*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void A::f()
116*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
117f4a2713aSLionel Sambuc 
118*0a6a1f1dSLionel Sambuc   // CHECK-NOT: VFTable indices for 'Test3::Y'
119f4a2713aSLionel Sambuc 
120f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7Y@Test3@@6B@"
121f4a2713aSLionel Sambuc };
122f4a2713aSLionel Sambuc 
Y()123*0a6a1f1dSLionel Sambuc Y::Y() {}
124f4a2713aSLionel Sambuc }
125f4a2713aSLionel Sambuc 
126f4a2713aSLionel Sambuc namespace Test4 {
127f4a2713aSLionel Sambuc 
128f4a2713aSLionel Sambuc struct X: virtual C {
129*0a6a1f1dSLionel Sambuc   X();
130f4a2713aSLionel Sambuc   // This one's interesting. C::f expects (A*) to be passed as 'this' and does
131f4a2713aSLionel Sambuc   // ECX-=4 to cast to (C*). In X, C and A vbases are reordered, so the thunk
132f4a2713aSLionel Sambuc   // should pass a pointer to the end of X in order
133f4a2713aSLionel Sambuc   // for ECX-=4 to point at the C part.
134f4a2713aSLionel Sambuc 
135*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'C' in 'Test4::X' (2 entries).
136*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void C::f()
137*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:     [this adjustment: 8 non-virtual]
138*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
139f4a2713aSLionel Sambuc 
140*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: Thunks for 'void C::f()' (1 entry).
141*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | [this adjustment: 8 non-virtual]
142*0a6a1f1dSLionel Sambuc 
143*0a6a1f1dSLionel Sambuc   // CHECK-NOT: VFTable indices for 'Test4::X'
144f4a2713aSLionel Sambuc 
145f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7X@Test4@@6B@"
146f4a2713aSLionel Sambuc 
147f4a2713aSLionel Sambuc   // Also check the mangling of the thunk.
148*0a6a1f1dSLionel Sambuc   // MANGLING-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@C@@WPPPPPPPI@AEXXZ"
149f4a2713aSLionel Sambuc };
150f4a2713aSLionel Sambuc 
X()151*0a6a1f1dSLionel Sambuc X::X() {}
152f4a2713aSLionel Sambuc }
153f4a2713aSLionel Sambuc 
154f4a2713aSLionel Sambuc namespace Test5 {
155f4a2713aSLionel Sambuc 
156f4a2713aSLionel Sambuc // New methods are added to the base's vftable.
157f4a2713aSLionel Sambuc struct X : A {
158f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7X@Test5@@6B@"
159f4a2713aSLionel Sambuc   virtual void g();
160f4a2713aSLionel Sambuc };
161f4a2713aSLionel Sambuc 
162f4a2713aSLionel Sambuc struct Y : virtual X {
163*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'Test5::Y' (1 entry).
164*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test5::Y::h()
165f4a2713aSLionel Sambuc 
166*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'Test5::X' in 'Test5::Y' (3 entries).
167*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void A::f()
168*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
169*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 2 | void Test5::X::g()
170f4a2713aSLionel Sambuc 
171*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable indices for 'Test5::Y' (1 entry).
172*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test5::Y::h()
173f4a2713aSLionel Sambuc 
174f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7Y@Test5@@6B01@@"
175f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7Y@Test5@@6BX@1@@"
176f4a2713aSLionel Sambuc 
177f4a2713aSLionel Sambuc   virtual void h();
178f4a2713aSLionel Sambuc };
179f4a2713aSLionel Sambuc 
180f4a2713aSLionel Sambuc Y y;
use(Y * obj)181*0a6a1f1dSLionel Sambuc void use(Y *obj) { obj->h(); }
182f4a2713aSLionel Sambuc }
183f4a2713aSLionel Sambuc 
184f4a2713aSLionel Sambuc namespace Test6 {
185f4a2713aSLionel Sambuc 
186f4a2713aSLionel Sambuc struct X : A, virtual Empty {
187*0a6a1f1dSLionel Sambuc   X();
188*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'Test6::X' (2 entries).
189*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void A::f()
190*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
191f4a2713aSLionel Sambuc 
192*0a6a1f1dSLionel Sambuc   // CHECK-NOT: VFTable indices for 'Test6::X'
193f4a2713aSLionel Sambuc 
194f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7X@Test6@@6B@"
195f4a2713aSLionel Sambuc };
196f4a2713aSLionel Sambuc 
X()197*0a6a1f1dSLionel Sambuc X::X() {}
198f4a2713aSLionel Sambuc }
199f4a2713aSLionel Sambuc 
200f4a2713aSLionel Sambuc namespace Test7 {
201f4a2713aSLionel Sambuc 
202f4a2713aSLionel Sambuc struct X : C {
203f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7X@Test7@@6B@"
204f4a2713aSLionel Sambuc };
205f4a2713aSLionel Sambuc 
206f4a2713aSLionel Sambuc struct Y : virtual X {
207*0a6a1f1dSLionel Sambuc   Y();
208*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'C' in 'Test7::X' in 'Test7::Y' (2 entries).
209*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void C::f()
210*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:     [this adjustment: 8 non-virtual]
211*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
212f4a2713aSLionel Sambuc 
213*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: Thunks for 'void C::f()' (1 entry).
214*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | [this adjustment: 8 non-virtual]
215f4a2713aSLionel Sambuc 
216*0a6a1f1dSLionel Sambuc   // CHECK-NOT: VFTable indices for 'Test7::Y'
217f4a2713aSLionel Sambuc 
218f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7Y@Test7@@6B@"
219f4a2713aSLionel Sambuc };
220f4a2713aSLionel Sambuc 
Y()221*0a6a1f1dSLionel Sambuc Y::Y() {}
222f4a2713aSLionel Sambuc }
223f4a2713aSLionel Sambuc 
224f4a2713aSLionel Sambuc namespace Test8 {
225f4a2713aSLionel Sambuc 
226f4a2713aSLionel Sambuc // This is a typical diamond inheritance with a shared 'A' vbase.
227f4a2713aSLionel Sambuc struct X : D, C {
228*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'D' in 'Test8::X' (1 entry).
229*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void D::h()
230f4a2713aSLionel Sambuc 
231*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'D' in 'Test8::X' (2 entries).
232*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test8::X::f()
233*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
234f4a2713aSLionel Sambuc 
235*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable indices for 'Test8::X' (1 entry).
236*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: via vbtable index 1, vfptr at offset 0
237*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test8::X::f()
238f4a2713aSLionel Sambuc 
239f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7X@Test8@@6BA@@@"
240f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7X@Test8@@6BD@@@"
241f4a2713aSLionel Sambuc 
242f4a2713aSLionel Sambuc   virtual void f();
243f4a2713aSLionel Sambuc };
244f4a2713aSLionel Sambuc 
245f4a2713aSLionel Sambuc X x;
use(X * obj)246*0a6a1f1dSLionel Sambuc void use(X *obj) { obj->f(); }
247f4a2713aSLionel Sambuc 
248f4a2713aSLionel Sambuc // Another diamond inheritance which led to AST crashes.
249f4a2713aSLionel Sambuc struct Y : virtual A {};
250f4a2713aSLionel Sambuc 
251*0a6a1f1dSLionel Sambuc struct Z : Y, C {
252*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'Test8::Y' in 'Test8::Z' (2 entries).
253*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test8::Z::f()
254*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
255f4a2713aSLionel Sambuc 
256*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable indices for 'Test8::Z' (1 entry).
257*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: via vbtable index 1, vfptr at offset 0
258*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test8::Z::f()
259f4a2713aSLionel Sambuc   virtual void f();
260f4a2713aSLionel Sambuc };
261f4a2713aSLionel Sambuc Z z;
use(Z * obj)262*0a6a1f1dSLionel Sambuc void use(Z *obj) { obj->f(); }
263*0a6a1f1dSLionel Sambuc 
264*0a6a1f1dSLionel Sambuc // Another diamond inheritance which we miscompiled (PR18967).
265*0a6a1f1dSLionel Sambuc struct W : virtual A {
266*0a6a1f1dSLionel Sambuc   virtual void bar();
267*0a6a1f1dSLionel Sambuc };
268*0a6a1f1dSLionel Sambuc 
269*0a6a1f1dSLionel Sambuc struct T : W, C {
270*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'Test8::W' in 'Test8::T' (1 entry)
271*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test8::T::bar()
272*0a6a1f1dSLionel Sambuc 
273*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'Test8::W' in 'Test8::T' (2 entries)
274*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void C::f()
275*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:     [this adjustment: -4 non-virtual]
276*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
277*0a6a1f1dSLionel Sambuc 
278*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: Thunks for 'void C::f()' (1 entry).
279*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual]
280*0a6a1f1dSLionel Sambuc   virtual void bar();
281*0a6a1f1dSLionel Sambuc   int field;
282*0a6a1f1dSLionel Sambuc };
283*0a6a1f1dSLionel Sambuc T t;
use(T * obj)284*0a6a1f1dSLionel Sambuc void use(T *obj) { obj->bar(); }
285f4a2713aSLionel Sambuc }
286f4a2713aSLionel Sambuc 
287f4a2713aSLionel Sambuc namespace Test9 {
288f4a2713aSLionel Sambuc 
289f4a2713aSLionel Sambuc struct X : A { };
290f4a2713aSLionel Sambuc 
291f4a2713aSLionel Sambuc struct Y : virtual X {
292*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'Test9::Y' (1 entry).
293*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test9::Y::h()
294f4a2713aSLionel Sambuc 
295*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'Test9::X' in 'Test9::Y' (2 entries).
296*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void A::f()
297*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
298f4a2713aSLionel Sambuc 
299*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable indices for 'Test9::Y' (1 entry).
300*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test9::Y::h()
301f4a2713aSLionel Sambuc 
302f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7Y@Test9@@6B01@@"
303f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7Y@Test9@@6BX@1@@"
304f4a2713aSLionel Sambuc 
305f4a2713aSLionel Sambuc   virtual void h();
306f4a2713aSLionel Sambuc };
307f4a2713aSLionel Sambuc 
308f4a2713aSLionel Sambuc Y y;
use(Y * obj)309*0a6a1f1dSLionel Sambuc void use(Y *obj) { obj->h(); }
310f4a2713aSLionel Sambuc 
311f4a2713aSLionel Sambuc struct Z : Y, virtual B {
312*0a6a1f1dSLionel Sambuc   Z();
313*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'Test9::Y' in 'Test9::Z' (1 entry).
314*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test9::Y::h()
315f4a2713aSLionel Sambuc 
316*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' (2 entries).
317*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void A::f()
318*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
319f4a2713aSLionel Sambuc 
320*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'B' in 'Test9::Z' (1 entry).
321*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void B::g()
322f4a2713aSLionel Sambuc 
323*0a6a1f1dSLionel Sambuc   // CHECK-NOT: VFTable indices for 'Test9::Z'
324f4a2713aSLionel Sambuc 
325f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7Z@Test9@@6BX@1@@"
326f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7Z@Test9@@6BY@1@@"
327f4a2713aSLionel Sambuc 
328*0a6a1f1dSLionel Sambuc   // MANGLING-DAG: @"\01??_7Z@Test9@@6B@"
329f4a2713aSLionel Sambuc };
330f4a2713aSLionel Sambuc 
Z()331*0a6a1f1dSLionel Sambuc Z::Z() {}
332f4a2713aSLionel Sambuc 
333f4a2713aSLionel Sambuc struct W : Z, D, virtual A, virtual B {
334*0a6a1f1dSLionel Sambuc   W();
335*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'Test9::Y' in 'Test9::Z' in 'Test9::W' (1 entry).
336*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test9::Y::h()
337f4a2713aSLionel Sambuc 
338*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' in 'Test9::W' (2 entries).
339*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void A::f()
340*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
341f4a2713aSLionel Sambuc 
342*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'B' in 'Test9::Z' in 'Test9::W' (1 entry).
343*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void B::g()
344f4a2713aSLionel Sambuc 
345*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'D' in 'Test9::W' (1 entry).
346*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void D::h()
347f4a2713aSLionel Sambuc 
348*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'D' in 'Test9::W' (2 entries).
349*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void D::f()
350*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:     [this adjustment: -8 non-virtual]
351*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
352f4a2713aSLionel Sambuc 
353*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: Thunks for 'void D::f()' (1 entry).
354*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
355f4a2713aSLionel Sambuc 
356*0a6a1f1dSLionel Sambuc   // CHECK-NOT: VFTable indices for 'Test9::W'
357f4a2713aSLionel Sambuc 
358f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7W@Test9@@6BA@@@"
359f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7W@Test9@@6BD@@@"
360f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7W@Test9@@6BX@1@@"
361f4a2713aSLionel Sambuc 
362*0a6a1f1dSLionel Sambuc   // MANGLING-DAG: @"\01??_7W@Test9@@6B@"
363*0a6a1f1dSLionel Sambuc   // MANGLING-DAG: @"\01??_7W@Test9@@6BY@1@@"
364f4a2713aSLionel Sambuc };
365f4a2713aSLionel Sambuc 
W()366*0a6a1f1dSLionel Sambuc W::W() {}
367f4a2713aSLionel Sambuc 
368f4a2713aSLionel Sambuc struct T : Z, D, virtual A, virtual B {
369*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'Test9::Y' in 'Test9::Z' in 'Test9::T' (1 entry).
370*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test9::T::h()
371f4a2713aSLionel Sambuc 
372*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' in 'Test9::T' (2 entries).
373*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test9::T::f()
374*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void Test9::T::z()
375f4a2713aSLionel Sambuc 
376*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'B' in 'Test9::Z' in 'Test9::T' (1 entry).
377*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test9::T::g()
378f4a2713aSLionel Sambuc 
379*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'D' in 'Test9::T' (1 entry).
380*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test9::T::h()
381*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:     [this adjustment: -8 non-virtual]
382f4a2713aSLionel Sambuc 
383*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: Thunks for 'void Test9::T::h()' (1 entry).
384*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
385f4a2713aSLionel Sambuc 
386*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'D' in 'Test9::T' (2 entries).
387*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test9::T::f()
388*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:     [this adjustment: -8 non-virtual]
389*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void Test9::T::z()
390*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:     [this adjustment: -8 non-virtual]
391f4a2713aSLionel Sambuc 
392*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: Thunks for 'void Test9::T::f()' (1 entry).
393*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
394f4a2713aSLionel Sambuc 
395*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: Thunks for 'void Test9::T::z()' (1 entry).
396*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
397f4a2713aSLionel Sambuc 
398*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable indices for 'Test9::T' (4 entries).
399*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: via vfptr at offset 0
400*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test9::T::h()
401*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: via vbtable index 1, vfptr at offset 0
402*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test9::T::f()
403*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void Test9::T::z()
404*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: via vbtable index 2, vfptr at offset 0
405*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test9::T::g()
406f4a2713aSLionel Sambuc 
407f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7T@Test9@@6BA@@@"
408f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7T@Test9@@6BD@@@"
409f4a2713aSLionel Sambuc   // MANGLING-DAG: @"\01??_7T@Test9@@6BX@1@@"
410f4a2713aSLionel Sambuc 
411*0a6a1f1dSLionel Sambuc   // MANGLING-DAG: @"\01??_7T@Test9@@6B@"
412*0a6a1f1dSLionel Sambuc   // MANGLING-DAG: @"\01??_7T@Test9@@6BY@1@@"
413f4a2713aSLionel Sambuc 
414f4a2713aSLionel Sambuc   virtual void f();
415f4a2713aSLionel Sambuc   virtual void g();
416f4a2713aSLionel Sambuc   virtual void h();
417f4a2713aSLionel Sambuc   virtual void z();
418f4a2713aSLionel Sambuc };
419f4a2713aSLionel Sambuc 
420f4a2713aSLionel Sambuc T t;
use(T * obj)421*0a6a1f1dSLionel Sambuc void use(T *obj) { obj->f(); }
422f4a2713aSLionel Sambuc }
423f4a2713aSLionel Sambuc 
424f4a2713aSLionel Sambuc namespace Test10 {
425f4a2713aSLionel Sambuc struct X : virtual C, virtual A {
426*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'C' in 'Test10::X' (2 entries).
427*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test10::X::f()
428*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void A::z()
429f4a2713aSLionel Sambuc 
430*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable indices for 'Test10::X' (1 entry).
431*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: via vbtable index 1, vfptr at offset 0
432*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void Test10::X::f()
433f4a2713aSLionel Sambuc   virtual void f();
434f4a2713aSLionel Sambuc };
435f4a2713aSLionel Sambuc 
f()436f4a2713aSLionel Sambuc void X::f() {}
437f4a2713aSLionel Sambuc X x;
use(X * obj)438*0a6a1f1dSLionel Sambuc void use(X *obj) { obj->f(); }
439*0a6a1f1dSLionel Sambuc }
440*0a6a1f1dSLionel Sambuc 
441*0a6a1f1dSLionel Sambuc namespace Test11 {
442*0a6a1f1dSLionel Sambuc struct X : virtual A {};
443*0a6a1f1dSLionel Sambuc struct Y { virtual void g(); };
444*0a6a1f1dSLionel Sambuc 
445*0a6a1f1dSLionel Sambuc struct Z : virtual X, Y {
446*0a6a1f1dSLionel Sambuc   // MANGLING-DAG: @"\01??_7Z@Test11@@6BY@1@@"
447*0a6a1f1dSLionel Sambuc   // MANGLING-DAG: @"\01??_7Z@Test11@@6BX@1@@"
448*0a6a1f1dSLionel Sambuc };
449*0a6a1f1dSLionel Sambuc 
450*0a6a1f1dSLionel Sambuc Z z;
451*0a6a1f1dSLionel Sambuc 
452*0a6a1f1dSLionel Sambuc struct W : virtual X, A {};
453*0a6a1f1dSLionel Sambuc 
454*0a6a1f1dSLionel Sambuc // Used to crash, PR17748.
455*0a6a1f1dSLionel Sambuc W w;
456*0a6a1f1dSLionel Sambuc }
457*0a6a1f1dSLionel Sambuc 
458*0a6a1f1dSLionel Sambuc namespace Test12 {
459*0a6a1f1dSLionel Sambuc struct X : B, A { };
460*0a6a1f1dSLionel Sambuc 
461*0a6a1f1dSLionel Sambuc struct Y : X {
462*0a6a1f1dSLionel Sambuc   virtual void f();  // Overrides A::f.
463*0a6a1f1dSLionel Sambuc };
464*0a6a1f1dSLionel Sambuc 
465*0a6a1f1dSLionel Sambuc struct Z : virtual Y {
466*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'Test12::X' in 'Test12::Y' in 'Test12::Z' (2 entries).
467*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:   0 | void Test12::Y::f()
468*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:   1 | void A::z()
469*0a6a1f1dSLionel Sambuc 
470*0a6a1f1dSLionel Sambuc   int z;
471*0a6a1f1dSLionel Sambuc   // MANGLING-DAG: @"\01??_7Z@Test12@@6BA@@@" = {{.*}}@"\01?f@Y@Test12@@UAEXXZ"
472*0a6a1f1dSLionel Sambuc };
473*0a6a1f1dSLionel Sambuc 
474*0a6a1f1dSLionel Sambuc struct W : Z {
475*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'Test12::X' in 'Test12::Y' in 'Test12::Z' in 'Test12::W' (2 entries).
476*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:   0 | void Test12::Y::f()
477*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:   1 | void A::z()
478*0a6a1f1dSLionel Sambuc   W();
479*0a6a1f1dSLionel Sambuc 
480*0a6a1f1dSLionel Sambuc   int w;
481*0a6a1f1dSLionel Sambuc   // MANGLING-DAG: @"\01??_7W@Test12@@6BA@@@" = {{.*}}@"\01?f@Y@Test12@@UAEXXZ"
482*0a6a1f1dSLionel Sambuc };
483*0a6a1f1dSLionel Sambuc 
W()484*0a6a1f1dSLionel Sambuc W::W() {}
485f4a2713aSLionel Sambuc }
486f4a2713aSLionel Sambuc 
487f4a2713aSLionel Sambuc namespace vdtors {
488f4a2713aSLionel Sambuc struct X {
489f4a2713aSLionel Sambuc   virtual ~X();
490f4a2713aSLionel Sambuc   virtual void zzz();
491f4a2713aSLionel Sambuc };
492f4a2713aSLionel Sambuc 
493f4a2713aSLionel Sambuc struct Y : virtual X {
494*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::Y' (2 entries).
495*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | vdtors::Y::~Y() [scalar deleting]
496*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void vdtors::X::zzz()
497f4a2713aSLionel Sambuc 
498*0a6a1f1dSLionel Sambuc   // CHECK-NOT: Thunks for 'vdtors::Y::~Y()'
499f4a2713aSLionel Sambuc   virtual ~Y();
500f4a2713aSLionel Sambuc };
501f4a2713aSLionel Sambuc 
502f4a2713aSLionel Sambuc Y y;
use(Y * obj)503*0a6a1f1dSLionel Sambuc void use(Y *obj) { delete obj; }
504f4a2713aSLionel Sambuc 
505f4a2713aSLionel Sambuc struct Z {
506f4a2713aSLionel Sambuc   virtual void z();
507f4a2713aSLionel Sambuc };
508f4a2713aSLionel Sambuc 
509f4a2713aSLionel Sambuc struct W : Z, X {
510f4a2713aSLionel Sambuc   // Implicit virtual dtor.
511f4a2713aSLionel Sambuc };
512f4a2713aSLionel Sambuc 
513f4a2713aSLionel Sambuc struct U : virtual W {
514*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'vdtors::Z' in 'vdtors::W' in 'vdtors::U' (1 entry).
515*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void vdtors::Z::z()
516f4a2713aSLionel Sambuc 
517*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::U' (2 entries).
518*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | vdtors::U::~U() [scalar deleting]
519*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:     [this adjustment: -4 non-virtual]
520*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void vdtors::X::zzz()
521f4a2713aSLionel Sambuc 
522*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: Thunks for 'vdtors::U::~U()' (1 entry).
523*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual]
524f4a2713aSLionel Sambuc 
525*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable indices for 'vdtors::U' (1 entry).
526*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 --
527*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | vdtors::U::~U() [scalar deleting]
528f4a2713aSLionel Sambuc   virtual ~U();
529f4a2713aSLionel Sambuc };
530f4a2713aSLionel Sambuc 
531f4a2713aSLionel Sambuc U u;
use(U * obj)532*0a6a1f1dSLionel Sambuc void use(U *obj) { delete obj; }
533f4a2713aSLionel Sambuc 
534f4a2713aSLionel Sambuc struct V : virtual W {
535*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'vdtors::Z' in 'vdtors::W' in 'vdtors::V' (1 entry).
536*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | void vdtors::Z::z()
537f4a2713aSLionel Sambuc 
538*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::V' (2 entries).
539*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | vdtors::V::~V() [scalar deleting]
540*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:     [this adjustment: -4 non-virtual]
541*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void vdtors::X::zzz()
542f4a2713aSLionel Sambuc 
543*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: Thunks for 'vdtors::V::~V()' (1 entry).
544*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual]
545f4a2713aSLionel Sambuc 
546*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable indices for 'vdtors::V' (1 entry).
547*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 --
548*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | vdtors::V::~V() [scalar deleting]
549f4a2713aSLionel Sambuc };
550f4a2713aSLionel Sambuc 
551f4a2713aSLionel Sambuc V v;
use(V * obj)552*0a6a1f1dSLionel Sambuc void use(V *obj) { delete obj; }
553f4a2713aSLionel Sambuc 
554f4a2713aSLionel Sambuc struct T : virtual X {
555f4a2713aSLionel Sambuc   virtual ~T();
556f4a2713aSLionel Sambuc };
557f4a2713aSLionel Sambuc 
558f4a2713aSLionel Sambuc struct P : T, Y {
559*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::T' in 'vdtors::P' (2 entries).
560*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | vdtors::P::~P() [scalar deleting]
561*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void vdtors::X::zzz()
562f4a2713aSLionel Sambuc 
563*0a6a1f1dSLionel Sambuc   // CHECK-NOT: Thunks for 'vdtors::P::~P()'
564f4a2713aSLionel Sambuc   virtual ~P();
565f4a2713aSLionel Sambuc };
566f4a2713aSLionel Sambuc 
567f4a2713aSLionel Sambuc P p;
use(P * obj)568*0a6a1f1dSLionel Sambuc void use(P *obj) { delete obj; }
569f4a2713aSLionel Sambuc 
570*0a6a1f1dSLionel Sambuc struct Q {
571*0a6a1f1dSLionel Sambuc   virtual ~Q();
572*0a6a1f1dSLionel Sambuc };
573*0a6a1f1dSLionel Sambuc 
574*0a6a1f1dSLionel Sambuc // PR19172: Yet another diamond we miscompiled.
575*0a6a1f1dSLionel Sambuc struct R : virtual Q, X {
576*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'vdtors::Q' in 'vdtors::R' (1 entry).
577*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting]
578*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:     [this adjustment: -8 non-virtual]
579*0a6a1f1dSLionel Sambuc 
580*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: Thunks for 'vdtors::R::~R()' (1 entry).
581*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
582*0a6a1f1dSLionel Sambuc 
583*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::R' (2 entries).
584*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting]
585*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | void vdtors::X::zzz()
586*0a6a1f1dSLionel Sambuc 
587*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable indices for 'vdtors::R' (1 entry).
588*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting]
589*0a6a1f1dSLionel Sambuc   virtual ~R();
590*0a6a1f1dSLionel Sambuc };
591*0a6a1f1dSLionel Sambuc 
592*0a6a1f1dSLionel Sambuc R r;
use(R * obj)593*0a6a1f1dSLionel Sambuc void use(R *obj) { delete obj; }
594f4a2713aSLionel Sambuc }
595f4a2713aSLionel Sambuc 
596f4a2713aSLionel Sambuc namespace return_adjustment {
597f4a2713aSLionel Sambuc 
598f4a2713aSLionel Sambuc struct X : virtual A {
599f4a2713aSLionel Sambuc   virtual void f();
600f4a2713aSLionel Sambuc };
601f4a2713aSLionel Sambuc 
602f4a2713aSLionel Sambuc struct Y : virtual A, virtual X {
603f4a2713aSLionel Sambuc   virtual void f();
604f4a2713aSLionel Sambuc };
605f4a2713aSLionel Sambuc 
606f4a2713aSLionel Sambuc struct Z {
607f4a2713aSLionel Sambuc   virtual A* foo();
608f4a2713aSLionel Sambuc };
609f4a2713aSLionel Sambuc 
610f4a2713aSLionel Sambuc struct W : Z {
611*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'return_adjustment::Z' in 'return_adjustment::W' (2 entries).
612*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | return_adjustment::X *return_adjustment::W::foo()
613*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:     [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual]
614*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | return_adjustment::X *return_adjustment::W::foo()
615f4a2713aSLionel Sambuc 
616*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: Thunks for 'return_adjustment::X *return_adjustment::W::foo()' (1 entry).
617*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual]
618*0a6a1f1dSLionel Sambuc 
619*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable indices for 'return_adjustment::W' (1 entry).
620*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | return_adjustment::X *return_adjustment::W::foo()
621f4a2713aSLionel Sambuc 
622f4a2713aSLionel Sambuc   virtual X* foo();
623f4a2713aSLionel Sambuc };
624f4a2713aSLionel Sambuc 
625*0a6a1f1dSLionel Sambuc W w;
use(W * obj)626*0a6a1f1dSLionel Sambuc void use(W *obj) { obj->foo(); }
627f4a2713aSLionel Sambuc 
628f4a2713aSLionel Sambuc struct T : W {
629*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'return_adjustment::Z' in 'return_adjustment::W' in 'return_adjustment::T' (3 entries).
630*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | return_adjustment::Y *return_adjustment::T::foo()
631*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:     [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual]
632*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | return_adjustment::Y *return_adjustment::T::foo()
633*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:     [return adjustment (to type 'struct return_adjustment::X *'): vbase #2, 0 non-virtual]
634*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 2 | return_adjustment::Y *return_adjustment::T::foo()
635f4a2713aSLionel Sambuc 
636*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: Thunks for 'return_adjustment::Y *return_adjustment::T::foo()' (2 entries).
637*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual]
638*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | [return adjustment (to type 'struct return_adjustment::X *'): vbase #2, 0 non-virtual]
639*0a6a1f1dSLionel Sambuc 
640*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable indices for 'return_adjustment::T' (1 entry).
641*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 2 | return_adjustment::Y *return_adjustment::T::foo()
642f4a2713aSLionel Sambuc 
643f4a2713aSLionel Sambuc   virtual Y* foo();
644f4a2713aSLionel Sambuc };
645f4a2713aSLionel Sambuc 
646f4a2713aSLionel Sambuc T t;
use(T * obj)647*0a6a1f1dSLionel Sambuc void use(T *obj) { obj->foo(); }
648f4a2713aSLionel Sambuc 
649f4a2713aSLionel Sambuc struct U : virtual A {
650f4a2713aSLionel Sambuc   virtual void g();  // adds a vfptr
651f4a2713aSLionel Sambuc };
652f4a2713aSLionel Sambuc 
653f4a2713aSLionel Sambuc struct V : Z {
654*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'return_adjustment::Z' in 'return_adjustment::V' (2 entries).
655*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | return_adjustment::U *return_adjustment::V::foo()
656*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:     [return adjustment (to type 'struct A *'): vbptr at offset 4, vbase #1, 0 non-virtual]
657*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | return_adjustment::U *return_adjustment::V::foo()
658f4a2713aSLionel Sambuc 
659*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: Thunks for 'return_adjustment::U *return_adjustment::V::foo()' (1 entry).
660*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 0 | [return adjustment (to type 'struct A *'): vbptr at offset 4, vbase #1, 0 non-virtual]
661*0a6a1f1dSLionel Sambuc 
662*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable indices for 'return_adjustment::V' (1 entry).
663*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: 1 | return_adjustment::U *return_adjustment::V::foo()
664f4a2713aSLionel Sambuc 
665f4a2713aSLionel Sambuc   virtual U* foo();
666f4a2713aSLionel Sambuc };
667f4a2713aSLionel Sambuc 
668f4a2713aSLionel Sambuc V v;
use(V * obj)669*0a6a1f1dSLionel Sambuc void use(V *obj) { obj->foo(); }
670*0a6a1f1dSLionel Sambuc }
671*0a6a1f1dSLionel Sambuc 
672*0a6a1f1dSLionel Sambuc namespace pr17748 {
673*0a6a1f1dSLionel Sambuc struct A {
fpr17748::A674*0a6a1f1dSLionel Sambuc   virtual void f() {}
675*0a6a1f1dSLionel Sambuc };
676*0a6a1f1dSLionel Sambuc 
677*0a6a1f1dSLionel Sambuc struct B : virtual A {
Bpr17748::B678*0a6a1f1dSLionel Sambuc   B() {}
679*0a6a1f1dSLionel Sambuc };
680*0a6a1f1dSLionel Sambuc 
681*0a6a1f1dSLionel Sambuc struct C : virtual B, A {
Cpr17748::C682*0a6a1f1dSLionel Sambuc   C() {}
683*0a6a1f1dSLionel Sambuc };
684*0a6a1f1dSLionel Sambuc C c;
685*0a6a1f1dSLionel Sambuc 
686*0a6a1f1dSLionel Sambuc // MANGLING-DAG: @"\01??_7A@pr17748@@6B@"
687*0a6a1f1dSLionel Sambuc // MANGLING-DAG: @"\01??_7B@pr17748@@6B@"
688*0a6a1f1dSLionel Sambuc // MANGLING-DAG: @"\01??_7C@pr17748@@6BA@1@@"
689*0a6a1f1dSLionel Sambuc // MANGLING-DAG: @"\01??_7C@pr17748@@6BB@1@@"
690*0a6a1f1dSLionel Sambuc }
691*0a6a1f1dSLionel Sambuc 
692*0a6a1f1dSLionel Sambuc namespace pr19066 {
693*0a6a1f1dSLionel Sambuc struct X : virtual B {};
694*0a6a1f1dSLionel Sambuc 
695*0a6a1f1dSLionel Sambuc struct Y : virtual X, B {
696*0a6a1f1dSLionel Sambuc   Y();
697*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'B' in 'pr19066::X' in 'pr19066::Y' (1 entry).
698*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:  0 | void B::g()
699*0a6a1f1dSLionel Sambuc 
700*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'B' in 'pr19066::Y' (1 entry).
701*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:  0 | void B::g()
702*0a6a1f1dSLionel Sambuc };
703*0a6a1f1dSLionel Sambuc 
Y()704*0a6a1f1dSLionel Sambuc Y::Y() {}
705*0a6a1f1dSLionel Sambuc }
706*0a6a1f1dSLionel Sambuc 
707*0a6a1f1dSLionel Sambuc namespace pr19240 {
708*0a6a1f1dSLionel Sambuc struct A {
709*0a6a1f1dSLionel Sambuc   virtual void c();
710*0a6a1f1dSLionel Sambuc };
711*0a6a1f1dSLionel Sambuc 
712*0a6a1f1dSLionel Sambuc struct B : virtual A {
713*0a6a1f1dSLionel Sambuc   virtual void c();
714*0a6a1f1dSLionel Sambuc };
715*0a6a1f1dSLionel Sambuc 
716*0a6a1f1dSLionel Sambuc struct C { };
717*0a6a1f1dSLionel Sambuc 
718*0a6a1f1dSLionel Sambuc struct D : virtual A, virtual C, B {};
719*0a6a1f1dSLionel Sambuc 
720*0a6a1f1dSLionel Sambuc D obj;
721*0a6a1f1dSLionel Sambuc 
722*0a6a1f1dSLionel Sambuc // Each MDC only has one vftable.
723*0a6a1f1dSLionel Sambuc 
724*0a6a1f1dSLionel Sambuc // MANGLING-DAG: @"\01??_7D@pr19240@@6B@"
725*0a6a1f1dSLionel Sambuc // MANGLING-DAG: @"\01??_7A@pr19240@@6B@"
726*0a6a1f1dSLionel Sambuc // MANGLING-DAG: @"\01??_7B@pr19240@@6B@"
727*0a6a1f1dSLionel Sambuc 
728*0a6a1f1dSLionel Sambuc }
729*0a6a1f1dSLionel Sambuc 
730*0a6a1f1dSLionel Sambuc namespace pr19408 {
731*0a6a1f1dSLionel Sambuc // This test is a non-vtordisp version of the reproducer for PR19408.
732*0a6a1f1dSLionel Sambuc struct X : virtual A {
733*0a6a1f1dSLionel Sambuc   int x;
734*0a6a1f1dSLionel Sambuc };
735*0a6a1f1dSLionel Sambuc 
736*0a6a1f1dSLionel Sambuc struct Y : X {
737*0a6a1f1dSLionel Sambuc   virtual void f();
738*0a6a1f1dSLionel Sambuc   int y;
739*0a6a1f1dSLionel Sambuc };
740*0a6a1f1dSLionel Sambuc 
741*0a6a1f1dSLionel Sambuc struct Z : Y {
742*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'pr19408::X' in 'pr19408::Y' in 'pr19408::Z' (2 entries).
743*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:   0 | void pr19408::Y::f()
744*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:       [this adjustment: -4 non-virtual]
745*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:   1 | void A::z()
746*0a6a1f1dSLionel Sambuc 
747*0a6a1f1dSLionel Sambuc   Z();
748*0a6a1f1dSLionel Sambuc   int z;
749*0a6a1f1dSLionel Sambuc   // MANGLING-DAG: @"\01??_7Z@pr19408@@6B@" = {{.*}}@"\01?f@Y@pr19408@@W3AEXXZ"
750*0a6a1f1dSLionel Sambuc };
751*0a6a1f1dSLionel Sambuc 
Z()752*0a6a1f1dSLionel Sambuc Z::Z() {}
753*0a6a1f1dSLionel Sambuc 
754*0a6a1f1dSLionel Sambuc struct W : B, Y {
755*0a6a1f1dSLionel Sambuc   // CHECK-LABEL: VFTable for 'A' in 'pr19408::X' in 'pr19408::Y' in 'pr19408::W' (2 entries).
756*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:   0 | void pr19408::Y::f()
757*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:       [this adjustment: -4 non-virtual]
758*0a6a1f1dSLionel Sambuc   // CHECK-NEXT:   1 | void A::z()
759*0a6a1f1dSLionel Sambuc 
760*0a6a1f1dSLionel Sambuc   W();
761*0a6a1f1dSLionel Sambuc   int w;
762*0a6a1f1dSLionel Sambuc   // MANGLING-DAG: @"\01??_7W@pr19408@@6BY@1@@" = {{.*}}@"\01?f@Y@pr19408@@W3AEXXZ"
763*0a6a1f1dSLionel Sambuc };
764*0a6a1f1dSLionel Sambuc 
W()765*0a6a1f1dSLionel Sambuc W::W() {}
766*0a6a1f1dSLionel Sambuc }
767*0a6a1f1dSLionel Sambuc 
768*0a6a1f1dSLionel Sambuc namespace Test13 {
769*0a6a1f1dSLionel Sambuc struct A {
770*0a6a1f1dSLionel Sambuc   virtual void f();
771*0a6a1f1dSLionel Sambuc };
772*0a6a1f1dSLionel Sambuc struct __declspec(dllexport) B : virtual A {
773*0a6a1f1dSLionel Sambuc   virtual void f() = 0;
774*0a6a1f1dSLionel Sambuc   // MANGLING-DAG: @"\01??_7B@Test13@@6B@" = weak_odr dllexport unnamed_addr constant [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)]
775*0a6a1f1dSLionel Sambuc };
776*0a6a1f1dSLionel Sambuc }
777*0a6a1f1dSLionel Sambuc 
778*0a6a1f1dSLionel Sambuc namespace pr21031_1 {
779*0a6a1f1dSLionel Sambuc // This ordering of base specifiers regressed in r202425.
780*0a6a1f1dSLionel Sambuc struct A { virtual void f(void); };
781*0a6a1f1dSLionel Sambuc struct B : virtual A { virtual void g(void); };
782*0a6a1f1dSLionel Sambuc struct C : virtual A, B { C(); };
C()783*0a6a1f1dSLionel Sambuc C::C() {}
784*0a6a1f1dSLionel Sambuc 
785*0a6a1f1dSLionel Sambuc // CHECK-LABEL: VFTable for 'pr21031_1::A' in 'pr21031_1::B' in 'pr21031_1::C' (1 entry)
786*0a6a1f1dSLionel Sambuc // CHECK-NEXT:   0 | void pr21031_1::A::f()
787*0a6a1f1dSLionel Sambuc 
788*0a6a1f1dSLionel Sambuc // CHECK-LABEL: VFTable for 'pr21031_1::B' in 'pr21031_1::C' (1 entry)
789*0a6a1f1dSLionel Sambuc // CHECK-NEXT:   0 | void pr21031_1::B::g()
790*0a6a1f1dSLionel Sambuc 
791*0a6a1f1dSLionel Sambuc // MANGLING-DAG: @"\01??_7C@pr21031_1@@6BB@1@@" = {{.*}} constant [1 x i8*]
792*0a6a1f1dSLionel Sambuc // MANGLING-DAG: @"\01??_7C@pr21031_1@@6B@" = {{.*}} constant [1 x i8*]
793*0a6a1f1dSLionel Sambuc }
794*0a6a1f1dSLionel Sambuc 
795*0a6a1f1dSLionel Sambuc namespace pr21031_2 {
796*0a6a1f1dSLionel Sambuc struct A { virtual void f(void); };
797*0a6a1f1dSLionel Sambuc struct B : virtual A { virtual void g(void); };
798*0a6a1f1dSLionel Sambuc struct C : B, virtual A { C(); };
C()799*0a6a1f1dSLionel Sambuc C::C() {}
800*0a6a1f1dSLionel Sambuc 
801*0a6a1f1dSLionel Sambuc // CHECK-LABEL: VFTable for 'pr21031_2::B' in 'pr21031_2::C' (1 entry)
802*0a6a1f1dSLionel Sambuc // CHECK-NEXT:   0 | void pr21031_2::B::g()
803*0a6a1f1dSLionel Sambuc 
804*0a6a1f1dSLionel Sambuc // CHECK-LABEL: VFTable for 'pr21031_2::A' in 'pr21031_2::B' in 'pr21031_2::C' (1 entry)
805*0a6a1f1dSLionel Sambuc // CHECK-NEXT:   0 | void pr21031_2::A::f()
806*0a6a1f1dSLionel Sambuc 
807*0a6a1f1dSLionel Sambuc // MANGLING-DAG: @"\01??_7C@pr21031_2@@6BA@1@@" = {{.*}} constant [1 x i8*]
808*0a6a1f1dSLionel Sambuc // MANGLING-DAG: @"\01??_7C@pr21031_2@@6BB@1@@" = {{.*}} constant [1 x i8*]
809f4a2713aSLionel Sambuc }
810