[InstCombine] Preserve NSW flags for `lshr (mul nuw X, C1), C2 -> mul nuw nsw X,...
[llvm-project.git] / clang / test / CodeGenCXX / microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp
blob62289e42804d79bc6eb245125f80659d3c1cb463
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=MANGLING %s < %t.ll
5 namespace test1 {
6 struct A {
7 virtual void f();
8 };
10 struct B {
11 virtual void g();
12 // Add an extra virtual method so it's easier to check for the absence of thunks.
13 virtual void h();
16 struct X : A, B {
17 // CHECK-LABEL: VFTable for 'test1::A' in 'test1::X' (1 entry)
18 // CHECK-NEXT: 0 | void test1::X::f()
20 // CHECK-LABEL: VFTable for 'test1::B' in 'test1::X' (2 entries)
21 // CHECK-NEXT: 0 | void test1::B::g()
22 // CHECK-NEXT: 1 | void test1::B::h()
24 // CHECK-LABEL: VFTable indices for 'test1::X' (1 entry)
25 // CHECK-NEXT: 0 | void test1::X::f()
27 // MANGLING-DAG: @"??_7X@test1@@6BA@1@@"
28 // MANGLING-DAG: @"??_7X@test1@@6BB@1@@"
30 // Overrides only the left child's method (A::f), needs no thunks.
31 virtual void f();
32 } x;
34 void build_vftable(X *obj) { obj->f(); }
37 namespace test2 {
38 struct A {
39 virtual void f();
42 struct B {
43 virtual void g();
44 virtual void h();
47 struct X : A, B {
48 // CHECK-LABEL: VFTable for 'test2::A' in 'test2::X' (1 entry)
49 // CHECK-NEXT: 0 | void test2::A::f()
51 // CHECK-LABEL: VFTable for 'test2::B' in 'test2::X' (2 entries)
52 // CHECK-NEXT: 0 | void test2::X::g()
53 // CHECK-NEXT: 1 | void test2::B::h()
55 // CHECK-LABEL: VFTable indices for 'test2::X' (1 entry).
56 // CHECK-NEXT: via vfptr at offset 4
57 // CHECK-NEXT: 0 | void test2::X::g()
59 // Overrides only the right child's method (B::g), needs this adjustment but
60 // not thunks.
61 virtual void g();
64 void build_vftable(X *obj) { obj->g(); }
67 namespace test3 {
68 struct A {
69 virtual void f();
72 struct B {
73 virtual void g();
74 virtual void h();
77 struct X : A, B {
78 // CHECK-LABEL: VFTable for 'test3::A' in 'test3::X' (2 entries)
79 // CHECK-NEXT: 0 | void test3::A::f()
80 // CHECK-NEXT: 1 | void test3::X::i()
82 // CHECK-LABEL: VFTable for 'test3::B' in 'test3::X' (2 entries)
83 // CHECK-NEXT: 0 | void test3::B::g()
84 // CHECK-NEXT: 1 | void test3::B::h()
86 // CHECK-LABEL: VFTable indices for 'test3::X' (1 entry).
87 // CHECK-NEXT: 1 | void test3::X::i()
89 // Only adds a new method.
90 virtual void i();
93 void build_vftable(X *obj) { obj->i(); }
96 namespace test4 {
97 struct A {
98 virtual void f();
101 struct Empty { }; // Doesn't have a vftable!
103 // Only the right base has a vftable, so it's laid out before the left one!
104 struct X : Empty, A {
105 // CHECK-LABEL: VFTable for 'test4::A' in 'test4::X' (1 entry)
106 // CHECK-NEXT: 0 | void test4::X::f()
108 // CHECK-LABEL: VFTable indices for 'test4::X' (1 entry).
109 // CHECK-NEXT: 0 | void test4::X::f()
111 // MANGLING-DAG: @"??_7X@test4@@6B@"
113 virtual void f();
114 } x;
116 void build_vftable(X *obj) { obj->f(); }
119 namespace test5 {
120 struct A {
121 virtual void f();
124 struct B {
125 virtual void g();
126 virtual void h();
129 struct C : A, B {
130 virtual void f();
133 struct X : C {
134 // CHECK-LABEL: VFTable for 'test5::A' in 'test5::C' in 'test5::X' (1 entry).
135 // CHECK-NEXT: 0 | void test5::X::f()
137 // CHECK-LABEL: VFTable for 'test5::B' in 'test5::C' in 'test5::X' (2 entries).
138 // CHECK-NEXT: 0 | void test5::B::g()
139 // CHECK-NEXT: 1 | void test5::B::h()
141 // CHECK-LABEL: VFTable indices for 'test5::X' (1 entry).
142 // CHECK-NEXT: 0 | void test5::X::f()
144 // MANGLING-DAG: @"??_7X@test5@@6BA@1@@"
145 // MANGLING-DAG: @"??_7X@test5@@6BB@1@@"
147 // Overrides both C::f and A::f.
148 virtual void f();
149 } x;
151 void build_vftable(X *obj) { obj->f(); }
154 namespace test6 {
155 struct A {
156 virtual void f();
159 struct B {
160 virtual void g();
161 virtual void h();
164 struct C : A, B {
165 virtual void g();
168 struct X : C {
169 // CHECK-LABEL: VFTable for 'test6::A' in 'test6::C' in 'test6::X' (1 entry).
170 // CHECK-NEXT: 0 | void test6::A::f()
172 // CHECK-LABEL: VFTable for 'test6::B' in 'test6::C' in 'test6::X' (2 entries).
173 // CHECK-NEXT: 0 | void test6::X::g()
174 // CHECK-NEXT: 1 | void test6::B::h()
176 // CHECK-LABEL: VFTable indices for 'test6::X' (1 entry).
177 // CHECK-NEXT: via vfptr at offset 4
178 // CHECK-NEXT: 0 | void test6::X::g()
180 // Overrides both C::g and B::g.
181 virtual void g();
184 void build_vftable(X *obj) { obj->g(); }
187 namespace test7 {
188 struct A {
189 virtual void f();
192 struct B {
193 virtual void g();
194 virtual void h();
197 struct C : A, B {
198 // Only adds a new method.
199 virtual void i();
202 struct X : C {
203 // CHECK-LABEL: VFTable for 'test7::A' in 'test7::C' in 'test7::X' (2 entries).
204 // CHECK-NEXT: 0 | void test7::A::f()
205 // CHECK-NEXT: 1 | void test7::C::i()
207 // CHECK-LABEL: VFTable for 'test7::B' in 'test7::C' in 'test7::X' (2 entries).
208 // CHECK-NEXT: 0 | void test7::X::g()
209 // CHECK-NEXT: 1 | void test7::B::h()
211 // CHECK-LABEL: VFTable indices for 'test7::X' (1 entry).
212 // CHECK-NEXT: via vfptr at offset 4
213 // CHECK-NEXT: 0 | void test7::X::g()
215 // Overrides grandparent's B::g.
216 virtual void g();
219 void build_vftable(X *obj) { obj->g(); }
222 namespace test8 {
223 struct A {
224 virtual void f();
227 struct B : A {
228 virtual void g();
231 // There are two 'A' subobjects in this class.
232 struct X : A, B {
233 // CHECK-LABEL: VFTable for 'test8::A' in 'test8::X' (2 entries).
234 // CHECK-NEXT: 0 | void test8::A::f()
235 // CHECK-NEXT: 1 | void test8::X::h()
237 // CHECK-LABEL: VFTable for 'test8::A' in 'test8::B' in 'test8::X' (2 entries).
238 // CHECK-NEXT: 0 | void test8::A::f()
239 // CHECK-NEXT: 1 | void test8::B::g()
241 // CHECK-LABEL: VFTable indices for 'test8::X' (1 entry).
242 // CHECK-NEXT: 1 | void test8::X::h()
244 // MANGLING-DAG: @"??_7X@test8@@6BA@1@@"
245 // MANGLING-DAG: @"??_7X@test8@@6BB@1@@"
247 virtual void h();
248 } x;
250 void build_vftable(X *obj) { obj->h(); }
253 namespace test9 {
254 struct A {
255 virtual void f();
258 struct B {
259 virtual void g();
260 virtual void h();
263 struct C : A, B {
264 // Overrides only the left child's method (A::f).
265 virtual void f();
268 struct D : A, B {
269 // Overrides only the right child's method (B::g).
270 virtual void g();
273 // 2-level structure with repeating subobject types, but no thunks needed.
274 struct X : C, D {
275 // CHECK-LABEL: VFTable for 'test9::A' in 'test9::C' in 'test9::X' (2 entries)
276 // CHECK-NEXT: 0 | void test9::C::f()
277 // CHECK-NEXT: 1 | void test9::X::z()
279 // CHECK-LABEL: VFTable for 'test9::B' in 'test9::C' in 'test9::X' (2 entries)
280 // CHECK-NEXT: 0 | void test9::B::g()
281 // CHECK-NEXT: 1 | void test9::B::h()
283 // CHECK-LABEL: VFTable for 'test9::A' in 'test9::D' in 'test9::X' (1 entry)
284 // CHECK-NEXT: 0 | void test9::A::f()
286 // CHECK-LABEL: VFTable for 'test9::B' in 'test9::D' in 'test9::X' (2 entries)
287 // CHECK-NEXT: 0 | void test9::D::g()
288 // CHECK-NEXT: 1 | void test9::B::h()
290 // CHECK-LABEL: VFTable indices for 'test9::X' (1 entry).
291 // CHECK-NEXT: 1 | void test9::X::z()
293 // MANGLING-DAG: @"??_7X@test9@@6BA@1@C@1@@"
294 // MANGLING-DAG: @"??_7X@test9@@6BA@1@D@1@@"
295 // MANGLING-DAG: @"??_7X@test9@@6BB@1@C@1@@"
296 // MANGLING-DAG: @"??_7X@test9@@6BB@1@D@1@@"
298 virtual void z();
299 } x;
301 void build_vftable(test9::X *obj) { obj->z(); }