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