blob: 8dad4dd7794f2f77062a7832be32af3bf101b115 [file] [log] [blame]
Timur Iskhodzhanov635de282013-07-30 09:46:19 +00001// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -fdump-vtable-layouts -o - >%t 2>&1
2
3// RUN: FileCheck --check-prefix=NO-THUNKS-Test1 %s < %t
4// RUN: FileCheck --check-prefix=NO-THUNKS-Test2 %s < %t
5// RUN: FileCheck --check-prefix=NO-THUNKS-Test3 %s < %t
6// RUN: FileCheck --check-prefix=NO-THUNKS-Test4 %s < %t
7// RUN: FileCheck --check-prefix=NO-THUNKS-Test5 %s < %t
8// RUN: FileCheck --check-prefix=NO-THUNKS-Test6 %s < %t
9// RUN: FileCheck --check-prefix=NO-THUNKS-Test7 %s < %t
10// RUN: FileCheck --check-prefix=NO-THUNKS-Test8 %s < %t
11// RUN: FileCheck --check-prefix=NO-THUNKS-Test9 %s < %t
12// RUN: FileCheck --check-prefix=PURE-VIRTUAL-Test1 %s < %t
13// RUN: FileCheck --check-prefix=THIS-THUNKS-Test1 %s < %t
14// RUN: FileCheck --check-prefix=THIS-THUNKS-Test2 %s < %t
15// RUN: FileCheck --check-prefix=THIS-THUNKS-Test3 %s < %t
16// RUN: FileCheck --check-prefix=RET-THUNKS-Test1 %s < %t
17// RUN: FileCheck --check-prefix=RET-THUNKS-Test2 %s < %t
18// RUN: FileCheck --check-prefix=RET-THUNKS-Test3 %s < %t
19// RUN: FileCheck --check-prefix=RET-THUNKS-Test4 %s < %t
20// RUN: FileCheck --check-prefix=RET-THUNKS-Test5 %s < %t
Timur Iskhodzhanov2cb17a02013-10-09 09:23:58 +000021// RUN: FileCheck --check-prefix=RET-THUNKS-Test6 %s < %t
Timur Iskhodzhanov635de282013-07-30 09:46:19 +000022
Timur Iskhodzhanova53d7a02013-09-27 14:48:01 +000023// RUN: FileCheck --check-prefix=MANGLING %s < %t
24
Timur Iskhodzhanov635de282013-07-30 09:46:19 +000025struct Empty {
26 // Doesn't have a vftable!
27};
28
29struct A {
30 virtual void f();
31};
32
33struct B {
34 virtual void g();
35 // Add an extra virtual method so it's easier to check for the absence of thunks.
36 virtual void h();
37};
38
39struct C {
40 virtual void g(); // Might "collide" with B::g if both are bases of some class.
41};
42
43
44namespace no_thunks {
45
46struct Test1: A, B {
47 // NO-THUNKS-Test1: VFTable for 'A' in 'no_thunks::Test1' (1 entries)
48 // NO-THUNKS-Test1-NEXT: 0 | void no_thunks::Test1::f()
49
50 // NO-THUNKS-Test1: VFTable for 'B' in 'no_thunks::Test1' (2 entries)
51 // NO-THUNKS-Test1-NEXT: 0 | void B::g()
52 // NO-THUNKS-Test1-NEXT: 1 | void B::h()
53
54 // NO-THUNKS-Test1: VFTable indices for 'no_thunks::Test1' (1 entries)
55 // NO-THUNKS-Test1-NEXT: 0 | void no_thunks::Test1::f()
56
Timur Iskhodzhanova53d7a02013-09-27 14:48:01 +000057 // MANGLING-DAG: @"\01??_7Test1@no_thunks@@6BA@@@"
58 // MANGLING-DAG: @"\01??_7Test1@no_thunks@@6BB@@@"
59
Timur Iskhodzhanov635de282013-07-30 09:46:19 +000060 // Overrides only the left child's method (A::f), needs no thunks.
61 virtual void f();
62};
63
64Test1 t1;
65
66struct Test2: A, B {
67 // NO-THUNKS-Test2: VFTable for 'A' in 'no_thunks::Test2' (1 entries)
68 // NO-THUNKS-Test2-NEXT: 0 | void A::f()
69
70 // NO-THUNKS-Test2: VFTable for 'B' in 'no_thunks::Test2' (2 entries)
71 // NO-THUNKS-Test2-NEXT: 0 | void no_thunks::Test2::g()
72 // NO-THUNKS-Test2-NEXT: 1 | void B::h()
73
74 // NO-THUNKS-Test2: VFTable indices for 'no_thunks::Test2' (1 entries).
75 // NO-THUNKS-Test2-NEXT: via vfptr at offset 4
76 // NO-THUNKS-Test2-NEXT: 0 | void no_thunks::Test2::g()
77
78 // Overrides only the right child's method (B::g), needs this adjustment but
79 // not thunks.
80 virtual void g();
81};
82
83Test2 t2;
84
85struct Test3: A, B {
86 // NO-THUNKS-Test3: VFTable for 'A' in 'no_thunks::Test3' (2 entries)
87 // NO-THUNKS-Test3-NEXT: 0 | void A::f()
88 // NO-THUNKS-Test3-NEXT: 1 | void no_thunks::Test3::i()
89
90 // NO-THUNKS-Test3: VFTable for 'B' in 'no_thunks::Test3' (2 entries)
91 // NO-THUNKS-Test3-NEXT: 0 | void B::g()
92 // NO-THUNKS-Test3-NEXT: 1 | void B::h()
93
94 // NO-THUNKS-Test3: VFTable indices for 'no_thunks::Test3' (1 entries).
95 // NO-THUNKS-Test3-NEXT: 1 | void no_thunks::Test3::i()
96
97 // Only adds a new method.
98 virtual void i();
99};
100
101Test3 t3;
102
103// Only the right base has a vftable, so it's laid out before the left one!
104struct Test4 : Empty, A {
105 // NO-THUNKS-Test4: VFTable for 'A' in 'no_thunks::Test4' (1 entries)
106 // NO-THUNKS-Test4-NEXT: 0 | void no_thunks::Test4::f()
107
108 // NO-THUNKS-Test4: VFTable indices for 'no_thunks::Test4' (1 entries).
109 // NO-THUNKS-Test4-NEXT: 0 | void no_thunks::Test4::f()
110
Timur Iskhodzhanova53d7a02013-09-27 14:48:01 +0000111 // MANGLING-DAG: @"\01??_7Test4@no_thunks@@6B@"
112
Timur Iskhodzhanov635de282013-07-30 09:46:19 +0000113 virtual void f();
114};
115
116Test4 t4;
117
118// 2-level structure with repeating subobject types, but no thunks needed.
119struct Test5: Test1, Test2 {
120 // NO-THUNKS-Test5: VFTable for 'A' in 'no_thunks::Test1' in 'no_thunks::Test5' (2 entries)
121 // NO-THUNKS-Test5-NEXT: 0 | void no_thunks::Test1::f()
122 // NO-THUNKS-Test5-NEXT: 1 | void no_thunks::Test5::z()
123
124 // NO-THUNKS-Test5: VFTable for 'B' in 'no_thunks::Test1' in 'no_thunks::Test5' (2 entries)
125 // NO-THUNKS-Test5-NEXT: 0 | void B::g()
126 // NO-THUNKS-Test5-NEXT: 1 | void B::h()
127
128 // NO-THUNKS-Test5: VFTable for 'A' in 'no_thunks::Test2' in 'no_thunks::Test5' (1 entries)
129 // NO-THUNKS-Test5-NEXT: 0 | void A::f()
130
131 // NO-THUNKS-Test5: VFTable for 'B' in 'no_thunks::Test2' in 'no_thunks::Test5' (2 entries)
132 // NO-THUNKS-Test5-NEXT: 0 | void no_thunks::Test2::g()
133 // NO-THUNKS-Test5-NEXT: 1 | void B::h()
134
135 // NO-THUNKS-Test5: VFTable indices for 'no_thunks::Test5' (1 entries).
136 // NO-THUNKS-Test5-NEXT: 1 | void no_thunks::Test5::z()
137
Timur Iskhodzhanova53d7a02013-09-27 14:48:01 +0000138 // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BA@@Test1@1@@"
139 // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BA@@Test2@1@@"
140 // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BB@@Test1@1@@"
141 // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BB@@Test2@1@@"
142
Timur Iskhodzhanov635de282013-07-30 09:46:19 +0000143 virtual void z();
144};
145
146Test5 t5;
147
148struct Test6: Test1 {
149 // NO-THUNKS-Test6: VFTable for 'A' in 'no_thunks::Test1' in 'no_thunks::Test6' (1 entries).
150 // NO-THUNKS-Test6-NEXT: 0 | void no_thunks::Test6::f()
151
152 // NO-THUNKS-Test6: VFTable for 'B' in 'no_thunks::Test1' in 'no_thunks::Test6' (2 entries).
153 // NO-THUNKS-Test6-NEXT: 0 | void B::g()
154 // NO-THUNKS-Test6-NEXT: 1 | void B::h()
155
156 // NO-THUNKS-Test6: VFTable indices for 'no_thunks::Test6' (1 entries).
157 // NO-THUNKS-Test6-NEXT: 0 | void no_thunks::Test6::f()
158
Timur Iskhodzhanova53d7a02013-09-27 14:48:01 +0000159 // MANGLING-DAG: @"\01??_7Test6@no_thunks@@6BA@@@"
160 // MANGLING-DAG: @"\01??_7Test6@no_thunks@@6BB@@@"
161
Timur Iskhodzhanov635de282013-07-30 09:46:19 +0000162 // Overrides both no_thunks::Test1::f and A::f.
163 virtual void f();
164};
165
166Test6 t6;
167
168struct Test7: Test2 {
169 // NO-THUNKS-Test7: VFTable for 'A' in 'no_thunks::Test2' in 'no_thunks::Test7' (1 entries).
170 // NO-THUNKS-Test7-NEXT: 0 | void A::f()
171
172 // NO-THUNKS-Test7: VFTable for 'B' in 'no_thunks::Test2' in 'no_thunks::Test7' (2 entries).
173 // NO-THUNKS-Test7-NEXT: 0 | void no_thunks::Test7::g()
174 // NO-THUNKS-Test7-NEXT: 1 | void B::h()
175
176 // NO-THUNKS-Test7: VFTable indices for 'no_thunks::Test7' (1 entries).
177 // NO-THUNKS-Test7-NEXT: via vfptr at offset 4
178 // NO-THUNKS-Test7-NEXT: 0 | void no_thunks::Test7::g()
179
180 // Overrides both no_thunks::Test2::g and B::g.
181 virtual void g();
182};
183
184Test7 t7;
185
186struct Test8: Test3 {
187 // NO-THUNKS-Test8: VFTable for 'A' in 'no_thunks::Test3' in 'no_thunks::Test8' (2 entries).
188 // NO-THUNKS-Test8-NEXT: 0 | void A::f()
189 // NO-THUNKS-Test8-NEXT: 1 | void no_thunks::Test3::i()
190
191 // NO-THUNKS-Test8: VFTable for 'B' in 'no_thunks::Test3' in 'no_thunks::Test8' (2 entries).
192 // NO-THUNKS-Test8-NEXT: 0 | void no_thunks::Test8::g()
193 // NO-THUNKS-Test8-NEXT: 1 | void B::h()
194
195 // NO-THUNKS-Test8: VFTable indices for 'no_thunks::Test8' (1 entries).
196 // NO-THUNKS-Test8-NEXT: via vfptr at offset 4
197 // NO-THUNKS-Test8-NEXT: 0 | void no_thunks::Test8::g()
198
199 // Overrides grandparent's B::g.
200 virtual void g();
201};
202
203Test8 t8;
204
205struct D : A {
206 virtual void g();
207};
208
209// Repeating subobject.
210struct Test9: A, D {
211 // NO-THUNKS-Test9: VFTable for 'A' in 'no_thunks::Test9' (2 entries).
212 // NO-THUNKS-Test9-NEXT: 0 | void A::f()
213 // NO-THUNKS-Test9-NEXT: 1 | void no_thunks::Test9::h()
214
215 // NO-THUNKS-Test9: VFTable for 'A' in 'no_thunks::D' in 'no_thunks::Test9' (2 entries).
216 // NO-THUNKS-Test9-NEXT: 0 | void A::f()
217 // NO-THUNKS-Test9-NEXT: 1 | void no_thunks::D::g()
218
219 // NO-THUNKS-Test9: VFTable indices for 'no_thunks::Test9' (1 entries).
220 // NO-THUNKS-Test9-NEXT: 1 | void no_thunks::Test9::h()
221
Timur Iskhodzhanova53d7a02013-09-27 14:48:01 +0000222 // MANGLING-DAG: @"\01??_7Test9@no_thunks@@6BA@@@"
223 // MANGLING-DAG: @"\01??_7Test9@no_thunks@@6BD@1@@"
224
Timur Iskhodzhanov635de282013-07-30 09:46:19 +0000225 virtual void h();
226};
227
228Test9 t9;
229}
230
231namespace pure_virtual {
232struct D {
233 virtual void g() = 0;
234 virtual void h();
235};
236
237
238struct Test1: A, D {
239 // PURE-VIRTUAL-Test1: VFTable for 'A' in 'pure_virtual::Test1' (1 entries)
240 // PURE-VIRTUAL-Test1-NEXT: 0 | void A::f()
241
242 // PURE-VIRTUAL-Test1: VFTable for 'pure_virtual::D' in 'pure_virtual::Test1' (2 entries)
243 // PURE-VIRTUAL-Test1-NEXT: 0 | void pure_virtual::Test1::g()
244 // PURE-VIRTUAL-Test1-NEXT: 1 | void pure_virtual::D::h()
245
246 // PURE-VIRTUAL-Test1: VFTable indices for 'pure_virtual::Test1' (1 entries).
247 // PURE-VIRTUAL-Test1-NEXT: via vfptr at offset 4
248 // PURE-VIRTUAL-Test1-NEXT: 0 | void pure_virtual::Test1::g()
249
Timur Iskhodzhanova53d7a02013-09-27 14:48:01 +0000250 // MANGLING-DAG: @"\01??_7Test1@pure_virtual@@6BA@@@"
251 // MANGLING-DAG: @"\01??_7Test1@pure_virtual@@6BD@1@@"
252
Timur Iskhodzhanov635de282013-07-30 09:46:19 +0000253 // Overrides only the right child's method (pure_virtual::D::g), needs this adjustment but
254 // not thunks.
255 virtual void g();
256};
257
258Test1 t1;
259}
260
261namespace this_adjustment {
262
263// Overrides methods of two bases at the same time, thus needing thunks.
264struct Test1 : B, C {
265 // THIS-THUNKS-Test1: VFTable for 'B' in 'this_adjustment::Test1' (2 entries).
266 // THIS-THUNKS-Test1-NEXT: 0 | void this_adjustment::Test1::g()
267 // THIS-THUNKS-Test1-NEXT: 1 | void B::h()
268
269 // THIS-THUNKS-Test1: VFTable for 'C' in 'this_adjustment::Test1' (1 entries).
270 // THIS-THUNKS-Test1-NEXT: 0 | void this_adjustment::Test1::g()
271 // THIS-THUNKS-Test1-NEXT: [this adjustment: -4 non-virtual]
272
273 // THIS-THUNKS-Test1: Thunks for 'void this_adjustment::Test1::g()' (1 entry).
274 // THIS-THUNKS-Test1-NEXT: 0 | this adjustment: -4 non-virtual
275
276 // THIS-THUNKS-Test1: VFTable indices for 'this_adjustment::Test1' (1 entries).
277 // THIS-THUNKS-Test1-NEXT: 0 | void this_adjustment::Test1::g()
278
Timur Iskhodzhanova53d7a02013-09-27 14:48:01 +0000279 // MANGLING-DAG: @"\01??_7Test1@this_adjustment@@6BB@@@"
280 // MANGLING-DAG: @"\01??_7Test1@this_adjustment@@6BC@@@"
281
Timur Iskhodzhanov635de282013-07-30 09:46:19 +0000282 virtual void g();
283};
284
285Test1 t1;
286
287struct Test2 : A, B, C {
288 // THIS-THUNKS-Test2: VFTable for 'A' in 'this_adjustment::Test2' (1 entries).
289 // THIS-THUNKS-Test2-NEXT: 0 | void A::f()
290
291 // THIS-THUNKS-Test2: VFTable for 'B' in 'this_adjustment::Test2' (2 entries).
292 // THIS-THUNKS-Test2-NEXT: 0 | void this_adjustment::Test2::g()
293 // THIS-THUNKS-Test2-NEXT: 1 | void B::h()
294
295 // THIS-THUNKS-Test2: VFTable for 'C' in 'this_adjustment::Test2' (1 entries).
296 // THIS-THUNKS-Test2-NEXT: 0 | void this_adjustment::Test2::g()
297 // THIS-THUNKS-Test2-NEXT: [this adjustment: -4 non-virtual]
298
299 // THIS-THUNKS-Test2: Thunks for 'void this_adjustment::Test2::g()' (1 entry).
300 // THIS-THUNKS-Test2-NEXT: 0 | this adjustment: -4 non-virtual
301
302 // THIS-THUNKS-Test2: VFTable indices for 'this_adjustment::Test2' (1 entries).
303 // THIS-THUNKS-Test2-NEXT: via vfptr at offset 4
304 // THIS-THUNKS-Test2-NEXT: 0 | void this_adjustment::Test2::g()
305
Timur Iskhodzhanova53d7a02013-09-27 14:48:01 +0000306 // MANGLING-DAG: @"\01??_7Test2@this_adjustment@@6BA@@@"
307 // MANGLING-DAG: @"\01??_7Test2@this_adjustment@@6BB@@@"
308 // MANGLING-DAG: @"\01??_7Test2@this_adjustment@@6BC@@@"
309
Timur Iskhodzhanov635de282013-07-30 09:46:19 +0000310 virtual void g();
311};
312
313Test2 t2;
314
315// Overrides methods of two bases at the same time, thus needing thunks.
316struct Test3: no_thunks::Test1, no_thunks::Test2 {
317 // THIS-THUNKS-Test3: VFTable for 'A' in 'no_thunks::Test1' in 'this_adjustment::Test3' (1 entries).
318 // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::f()
319
320 // THIS-THUNKS-Test3: VFTable for 'B' in 'no_thunks::Test1' in 'this_adjustment::Test3' (2 entries).
321 // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::g()
322 // THIS-THUNKS-Test3-NEXT: 1 | void B::h()
323
324 // THIS-THUNKS-Test3: VFTable for 'A' in 'no_thunks::Test2' in 'this_adjustment::Test3' (1 entries).
325 // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::f()
326 // THIS-THUNKS-Test3-NEXT: [this adjustment: -8 non-virtual]
327
328 // THIS-THUNKS-Test3: Thunks for 'void this_adjustment::Test3::f()' (1 entry).
329 // THIS-THUNKS-Test3-NEXT: 0 | this adjustment: -8 non-virtual
330
331 // THIS-THUNKS-Test3: VFTable for 'B' in 'no_thunks::Test2' in 'this_adjustment::Test3' (2 entries).
332 // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::g()
333 // THIS-THUNKS-Test3-NEXT: [this adjustment: -8 non-virtual]
334 // THIS-THUNKS-Test3-NEXT: 1 | void B::h()
335
336 // THIS-THUNKS-Test3: Thunks for 'void this_adjustment::Test3::g()' (1 entry).
337 // THIS-THUNKS-Test3-NEXT: 0 | this adjustment: -8 non-virtual
338
339 // THIS-THUNKS-Test3: VFTable indices for 'this_adjustment::Test3' (2 entries).
340 // THIS-THUNKS-Test3-NEXT: via vfptr at offset 0
341 // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::f()
342 // THIS-THUNKS-Test3-NEXT: via vfptr at offset 4
343 // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::g()
344
345 virtual void f();
346 virtual void g();
347};
348
349Test3 t3;
350}
351
352namespace return_adjustment {
353
354struct Ret1 {
355 virtual C* foo();
356 virtual void z();
357};
358
359struct Test1 : Ret1 {
360 // RET-THUNKS-Test1: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test1' (3 entries).
361 // RET-THUNKS-Test1-NEXT: 0 | this_adjustment::Test1 *return_adjustment::Test1::foo()
362 // RET-THUNKS-Test1-NEXT: [return adjustment: 4 non-virtual]
363 // RET-THUNKS-Test1-NEXT: 1 | void return_adjustment::Ret1::z()
364 // RET-THUNKS-Test1-NEXT: 2 | this_adjustment::Test1 *return_adjustment::Test1::foo()
365
366 // RET-THUNKS-Test1: VFTable indices for 'return_adjustment::Test1' (1 entries).
367 // RET-THUNKS-Test1-NEXT: 2 | this_adjustment::Test1 *return_adjustment::Test1::foo()
368
Timur Iskhodzhanova53d7a02013-09-27 14:48:01 +0000369 // MANGLING-DAG: @"\01??_7Test1@return_adjustment@@6B@"
370
Timur Iskhodzhanov635de282013-07-30 09:46:19 +0000371 virtual this_adjustment::Test1* foo();
372};
373
374Test1 t1;
375
376struct Ret2 : B, this_adjustment::Test1 { };
377
378struct Test2 : Test1 {
379 // RET-THUNKS-Test2: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test1' in 'return_adjustment::Test2' (4 entries).
380 // RET-THUNKS-Test2-NEXT: 0 | return_adjustment::Ret2 *return_adjustment::Test2::foo()
381 // RET-THUNKS-Test2-NEXT: [return adjustment: 8 non-virtual]
382 // RET-THUNKS-Test2-NEXT: 1 | void return_adjustment::Ret1::z()
383 // RET-THUNKS-Test2-NEXT: 2 | return_adjustment::Ret2 *return_adjustment::Test2::foo()
384 // RET-THUNKS-Test2-NEXT: [return adjustment: 4 non-virtual]
385 // RET-THUNKS-Test2-NEXT: 3 | return_adjustment::Ret2 *return_adjustment::Test2::foo()
386
387 // RET-THUNKS-Test2: VFTable indices for 'return_adjustment::Test2' (1 entries).
388 // RET-THUNKS-Test2-NEXT: 3 | return_adjustment::Ret2 *return_adjustment::Test2::foo()
389
390 virtual Ret2* foo();
391};
392
393Test2 t2;
394
395struct Test3: B, Ret1 {
396 // RET-THUNKS-Test3: VFTable for 'B' in 'return_adjustment::Test3' (2 entries).
397 // RET-THUNKS-Test3-NEXT: 0 | void B::g()
398 // RET-THUNKS-Test3-NEXT: 1 | void B::h()
399
400 // RET-THUNKS-Test3: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test3' (3 entries).
401 // RET-THUNKS-Test3-NEXT: 0 | this_adjustment::Test1 *return_adjustment::Test3::foo()
402 // RET-THUNKS-Test3-NEXT: [return adjustment: 4 non-virtual]
403 // RET-THUNKS-Test3-NEXT: 1 | void return_adjustment::Ret1::z()
404 // RET-THUNKS-Test3-NEXT: 2 | this_adjustment::Test1 *return_adjustment::Test3::foo()
405
406 // RET-THUNKS-Test3: VFTable indices for 'return_adjustment::Test3' (1 entries).
407 // RET-THUNKS-Test3-NEXT: via vfptr at offset 4
408 // RET-THUNKS-Test3-NEXT: 2 | this_adjustment::Test1 *return_adjustment::Test3::foo()
409
410 virtual this_adjustment::Test1* foo();
411};
412
413Test3 t3;
414
415struct Test4 : Test3 {
416 // RET-THUNKS-Test4: VFTable for 'B' in 'return_adjustment::Test3' in 'return_adjustment::Test4' (2 entries).
417 // RET-THUNKS-Test4-NEXT: 0 | void B::g()
418 // RET-THUNKS-Test4-NEXT: 1 | void B::h()
419
420 // RET-THUNKS-Test4: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test3' in 'return_adjustment::Test4' (4 entries).
421 // RET-THUNKS-Test4-NEXT: 0 | return_adjustment::Ret2 *return_adjustment::Test4::foo()
422 // RET-THUNKS-Test4-NEXT: [return adjustment: 8 non-virtual]
423 // RET-THUNKS-Test4-NEXT: 1 | void return_adjustment::Ret1::z()
424 // RET-THUNKS-Test4-NEXT: 2 | return_adjustment::Ret2 *return_adjustment::Test4::foo()
425 // RET-THUNKS-Test4-NEXT: [return adjustment: 4 non-virtual]
426 // RET-THUNKS-Test4-NEXT: 3 | return_adjustment::Ret2 *return_adjustment::Test4::foo()
427
428 // RET-THUNKS-Test4: VFTable indices for 'return_adjustment::Test4' (1 entries).
429 // RET-THUNKS-Test4-NEXT: -- accessible via vfptr at offset 4 --
430 // RET-THUNKS-Test4-NEXT: 3 | return_adjustment::Ret2 *return_adjustment::Test4::foo()
431
432 virtual Ret2* foo();
433};
434
435Test4 t4;
436
437struct Test5 : Ret1, Test1 {
438 // RET-THUNKS-Test5: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test5' (3 entries).
439 // RET-THUNKS-Test5-NEXT: 0 | return_adjustment::Ret2 *return_adjustment::Test5::foo()
440 // RET-THUNKS-Test5-NEXT: [return adjustment: 8 non-virtual]
441 // RET-THUNKS-Test5-NEXT: 1 | void return_adjustment::Ret1::z()
442 // RET-THUNKS-Test5-NEXT: 2 | return_adjustment::Ret2 *return_adjustment::Test5::foo()
443
444 // RET-THUNKS-Test5: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test1' in 'return_adjustment::Test5' (4 entries).
445 // RET-THUNKS-Test5-NEXT: 0 | return_adjustment::Ret2 *return_adjustment::Test5::foo()
446 // RET-THUNKS-Test5-NEXT: [return adjustment: 8 non-virtual]
447 // RET-THUNKS-Test5-NEXT: [this adjustment: -4 non-virtual]
448 // RET-THUNKS-Test5-NEXT: 1 | void return_adjustment::Ret1::z()
449 // RET-THUNKS-Test5-NEXT: 2 | return_adjustment::Ret2 *return_adjustment::Test5::foo()
450 // RET-THUNKS-Test5-NEXT: [return adjustment: 4 non-virtual]
451 // RET-THUNKS-Test5-NEXT: [this adjustment: -4 non-virtual]
452 // RET-THUNKS-Test5-NEXT: 3 | return_adjustment::Ret2 *return_adjustment::Test5::foo()
453 // RET-THUNKS-Test5-NEXT: [this adjustment: -4 non-virtual]
454
455 // RET-THUNKS-Test5: VFTable indices for 'return_adjustment::Test5' (1 entries).
456 // RET-THUNKS-Test5-NEXT: 2 | return_adjustment::Ret2 *return_adjustment::Test5::foo()
457
458 virtual Ret2* foo();
459};
460
461Test5 t5;
Timur Iskhodzhanov2cb17a02013-10-09 09:23:58 +0000462
463struct Ret3 : this_adjustment::Test1 { };
464
465struct Test6 : Test1 {
466 virtual Ret3* foo();
467 // RET-THUNKS-Test6: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test1' in 'return_adjustment::Test6' (4 entries).
468 // RET-THUNKS-Test6-NEXT: 0 | return_adjustment::Ret3 *return_adjustment::Test6::foo()
469 // RET-THUNKS-Test6-NEXT: [return adjustment: 4 non-virtual]
470 // RET-THUNKS-Test6-NEXT: 1 | void return_adjustment::Ret1::z()
471 // RET-THUNKS-Test6-NEXT: 2 | return_adjustment::Ret3 *return_adjustment::Test6::foo()
472 // RET-THUNKS-Test6-NEXT: 3 | return_adjustment::Ret3 *return_adjustment::Test6::foo()
473
474 // RET-THUNKS-Test6: VFTable indices for 'return_adjustment::Test6' (1 entries).
475 // RET-THUNKS-Test6-NEXT: 3 | return_adjustment::Ret3 *return_adjustment::Test6::foo()
476};
477
478Test6 t6;
479
Timur Iskhodzhanov635de282013-07-30 09:46:19 +0000480}