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