1*67e74705SXin Li // RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t
2*67e74705SXin Li // RUN: FileCheck %s < %t
3*67e74705SXin Li // RUN: FileCheck --check-prefix=BITCODE %s < %t.ll
4*67e74705SXin Li
5*67e74705SXin Li namespace test1 {
6*67e74705SXin Li struct A {
7*67e74705SXin Li virtual void g();
8*67e74705SXin Li // Add an extra virtual method so it's easier to check for the absence of thunks.
9*67e74705SXin Li virtual void h();
10*67e74705SXin Li };
11*67e74705SXin Li
12*67e74705SXin Li struct B {
13*67e74705SXin Li virtual void g(); // Collides with A::g if both are bases of some class.
14*67e74705SXin Li };
15*67e74705SXin Li
16*67e74705SXin Li // Overrides methods of two bases at the same time, thus needing thunks.
17*67e74705SXin Li struct X : A, B {
18*67e74705SXin Li // CHECK-LABEL: VFTable for 'test1::A' in 'test1::X' (2 entries).
19*67e74705SXin Li // CHECK-NEXT: 0 | void test1::X::g()
20*67e74705SXin Li // CHECK-NEXT: 1 | void test1::A::h()
21*67e74705SXin Li
22*67e74705SXin Li // CHECK-LABEL: VFTable for 'test1::B' in 'test1::X' (1 entry).
23*67e74705SXin Li // CHECK-NEXT: 0 | void test1::X::g()
24*67e74705SXin Li // CHECK-NEXT: [this adjustment: -4 non-virtual]
25*67e74705SXin Li
26*67e74705SXin Li // CHECK-LABEL: Thunks for 'void test1::X::g()' (1 entry).
27*67e74705SXin Li // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual]
28*67e74705SXin Li
29*67e74705SXin Li // CHECK-LABEL: VFTable indices for 'test1::X' (1 entry).
30*67e74705SXin Li // CHECK-NEXT: 0 | void test1::X::g()
31*67e74705SXin Li
32*67e74705SXin Li // BITCODE-DAG: @"\01??_7X@test1@@6BA@1@@"
33*67e74705SXin Li // BITCODE-DAG: @"\01??_7X@test1@@6BB@1@@"
34*67e74705SXin Li
35*67e74705SXin Li virtual void g();
36*67e74705SXin Li } x;
37*67e74705SXin Li
build_vftable(X * obj)38*67e74705SXin Li void build_vftable(X *obj) { obj->g(); }
39*67e74705SXin Li }
40*67e74705SXin Li
41*67e74705SXin Li namespace test2 {
42*67e74705SXin Li struct A {
43*67e74705SXin Li virtual void f();
44*67e74705SXin Li };
45*67e74705SXin Li
46*67e74705SXin Li struct B {
47*67e74705SXin Li virtual void g();
48*67e74705SXin Li virtual void h();
49*67e74705SXin Li };
50*67e74705SXin Li
51*67e74705SXin Li struct C {
52*67e74705SXin Li virtual void g();
53*67e74705SXin Li };
54*67e74705SXin Li
55*67e74705SXin Li struct X : A, B, C {
56*67e74705SXin Li // CHECK-LABEL: VFTable for 'test2::A' in 'test2::X' (1 entry).
57*67e74705SXin Li // CHECK-NEXT: 0 | void test2::A::f()
58*67e74705SXin Li
59*67e74705SXin Li // CHECK-LABEL: VFTable for 'test2::B' in 'test2::X' (2 entries).
60*67e74705SXin Li // CHECK-NEXT: 0 | void test2::X::g()
61*67e74705SXin Li // CHECK-NEXT: 1 | void test2::B::h()
62*67e74705SXin Li
63*67e74705SXin Li // CHECK-LABEL: VFTable for 'test2::C' in 'test2::X' (1 entry).
64*67e74705SXin Li // CHECK-NEXT: 0 | void test2::X::g()
65*67e74705SXin Li // CHECK-NEXT: [this adjustment: -4 non-virtual]
66*67e74705SXin Li
67*67e74705SXin Li // CHECK-LABEL: Thunks for 'void test2::X::g()' (1 entry).
68*67e74705SXin Li // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual]
69*67e74705SXin Li
70*67e74705SXin Li // CHECK-LABEL: VFTable indices for 'test2::X' (1 entry).
71*67e74705SXin Li // CHECK-NEXT: via vfptr at offset 4
72*67e74705SXin Li // CHECK-NEXT: 0 | void test2::X::g()
73*67e74705SXin Li
74*67e74705SXin Li // BITCODE-DAG: @"\01??_7X@test2@@6BA@1@@"
75*67e74705SXin Li // BITCODE-DAG: @"\01??_7X@test2@@6BB@1@@"
76*67e74705SXin Li // BITCODE-DAG: @"\01??_7X@test2@@6BC@1@@"
77*67e74705SXin Li
78*67e74705SXin Li virtual void g();
79*67e74705SXin Li } x;
80*67e74705SXin Li
build_vftable(X * obj)81*67e74705SXin Li void build_vftable(X *obj) { obj->g(); }
82*67e74705SXin Li }
83*67e74705SXin Li
84*67e74705SXin Li namespace test3 {
85*67e74705SXin Li struct A {
86*67e74705SXin Li virtual void f();
87*67e74705SXin Li };
88*67e74705SXin Li
89*67e74705SXin Li struct B {
90*67e74705SXin Li virtual void g();
91*67e74705SXin Li virtual void h();
92*67e74705SXin Li };
93*67e74705SXin Li
94*67e74705SXin Li struct C: A, B {
95*67e74705SXin Li // Overrides only the left child's method (A::f), needs no thunks.
96*67e74705SXin Li virtual void f();
97*67e74705SXin Li };
98*67e74705SXin Li
99*67e74705SXin Li struct D: A, B {
100*67e74705SXin Li // Overrides only the right child's method (B::g),
101*67e74705SXin Li // needs this adjustment but not thunks.
102*67e74705SXin Li virtual void g();
103*67e74705SXin Li };
104*67e74705SXin Li
105*67e74705SXin Li // Overrides methods of two bases at the same time, thus needing thunks.
106*67e74705SXin Li struct X: C, D {
107*67e74705SXin Li // CHECK-LABEL: VFTable for 'test3::A' in 'test3::C' in 'test3::X' (1 entry).
108*67e74705SXin Li // CHECK-NEXT: 0 | void test3::X::f()
109*67e74705SXin Li
110*67e74705SXin Li // CHECK-LABEL: VFTable for 'test3::B' in 'test3::C' in 'test3::X' (2 entries).
111*67e74705SXin Li // CHECK-NEXT: 0 | void test3::X::g()
112*67e74705SXin Li // CHECK-NEXT: 1 | void test3::B::h()
113*67e74705SXin Li
114*67e74705SXin Li // CHECK-LABEL: VFTable for 'test3::A' in 'test3::D' in 'test3::X' (1 entry).
115*67e74705SXin Li // CHECK-NEXT: 0 | void test3::X::f()
116*67e74705SXin Li // CHECK-NEXT: [this adjustment: -8 non-virtual]
117*67e74705SXin Li
118*67e74705SXin Li // CHECK-LABEL: Thunks for 'void test3::X::f()' (1 entry).
119*67e74705SXin Li // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
120*67e74705SXin Li
121*67e74705SXin Li // CHECK-LABEL: VFTable for 'test3::B' in 'test3::D' in 'test3::X' (2 entries).
122*67e74705SXin Li // CHECK-NEXT: 0 | void test3::X::g()
123*67e74705SXin Li // CHECK-NEXT: [this adjustment: -8 non-virtual]
124*67e74705SXin Li // CHECK-NEXT: 1 | void test3::B::h()
125*67e74705SXin Li
126*67e74705SXin Li // CHECK-LABEL: Thunks for 'void test3::X::g()' (1 entry).
127*67e74705SXin Li // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
128*67e74705SXin Li
129*67e74705SXin Li // CHECK-LABEL: VFTable indices for 'test3::X' (2 entries).
130*67e74705SXin Li // CHECK-NEXT: via vfptr at offset 0
131*67e74705SXin Li // CHECK-NEXT: 0 | void test3::X::f()
132*67e74705SXin Li // CHECK-NEXT: via vfptr at offset 4
133*67e74705SXin Li // CHECK-NEXT: 0 | void test3::X::g()
134*67e74705SXin Li
135*67e74705SXin Li virtual void f();
136*67e74705SXin Li virtual void g();
137*67e74705SXin Li } x;
138*67e74705SXin Li
build_vftable(X * obj)139*67e74705SXin Li void build_vftable(X *obj) { obj->g(); }
140*67e74705SXin Li }
141*67e74705SXin Li
142*67e74705SXin Li namespace test4 {
143*67e74705SXin Li struct A {
144*67e74705SXin Li virtual void foo();
145*67e74705SXin Li };
146*67e74705SXin Li struct B {
147*67e74705SXin Li virtual int filler();
148*67e74705SXin Li virtual int operator-();
149*67e74705SXin Li virtual int bar();
150*67e74705SXin Li };
151*67e74705SXin Li struct C : public A, public B {
152*67e74705SXin Li virtual int filler();
153*67e74705SXin Li virtual int operator-();
154*67e74705SXin Li virtual int bar();
155*67e74705SXin Li };
156*67e74705SXin Li
157*67e74705SXin Li // BITCODE-LABEL: define {{.*}}\01?ffun@test4@@YAXAAUC@1@@Z
ffun(C & c)158*67e74705SXin Li void ffun(C &c) {
159*67e74705SXin Li // BITCODE: load
160*67e74705SXin Li // BITCODE: bitcast
161*67e74705SXin Li // BITCODE: bitcast
162*67e74705SXin Li // BITCODE: [[THIS1:%.+]] = bitcast %"struct.test4::C"* {{.*}} to i8*
163*67e74705SXin Li // BITCODE: [[THIS2:%.+]] = getelementptr inbounds i8, i8* [[THIS1]], i32 4
164*67e74705SXin Li // BITCODE-NEXT: call x86_thiscallcc {{.*}}(i8* [[THIS2]])
165*67e74705SXin Li c.bar();
166*67e74705SXin Li }
167*67e74705SXin Li
168*67e74705SXin Li // BITCODE-LABEL: define {{.*}}\01?fop@test4@@YAXAAUC@1@@Z
fop(C & c)169*67e74705SXin Li void fop(C &c) {
170*67e74705SXin Li // BITCODE: load
171*67e74705SXin Li // BITCODE: bitcast
172*67e74705SXin Li // BITCODE: bitcast
173*67e74705SXin Li // BITCODE: [[THIS1:%.+]] = bitcast %"struct.test4::C"* {{.*}} to i8*
174*67e74705SXin Li // BITCODE: [[THIS2:%.+]] = getelementptr inbounds i8, i8* [[THIS1]], i32 4
175*67e74705SXin Li // BITCODE-NEXT: call x86_thiscallcc {{.*}}(i8* [[THIS2]])
176*67e74705SXin Li -c;
177*67e74705SXin Li }
178*67e74705SXin Li
179*67e74705SXin Li }
180