1// Origin: Mark Mitchell <mark@codesourcery.com>
2// Special g++ Options: -fno-strict-aliasing
3
4#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
5
6#include <stddef.h>
7
8struct S0
9{
10  virtual void s0 ();
11};
12
13struct S1 : virtual public S0
14{
15  virtual void s1 ();
16};
17
18struct S2 : virtual public S1
19{
20  virtual void s1 ();
21  virtual void s0 ();
22};
23
24struct S3
25{
26  virtual void s3 ();
27};
28
29struct S4 : public S3, virtual public S2
30{
31  virtual void s1 ();
32};
33
34void S0::s0 ()
35{
36}
37
38void S1::s1 ()
39{
40}
41
42void S2::s1 ()
43{
44}
45
46void S2::s0 ()
47{
48}
49
50void S3::s3 ()
51{
52}
53
54void S4::s1 ()
55{
56}
57
58/* The vtables should look like:
59
60   S0 primary vtable
61
62     S0 offset to top
63     S0 RTTI
64     S0::s0
65
66   =================
67
68   S1 primary vtable
69
70     S0::s0 vcall offset
71     S0 vbase offset
72     S1 offset to top
73     S1 RTTI
74     S0::s0
75     S1::s1
76
77   =================
78
79   S2 primary vtable
80
81     S2::s1 vcall offset
82     S1 vbase offset
83     S2::s0 vcall offset
84     S0 vbase offset
85     S2 offset to top
86     S2 RTTI
87     S2::s0
88     S2::s1
89
90   =================
91
92   S3 primary vtable
93
94     S3 offset to top
95     S3 RTTI
96     S3::s3
97
98   =================
99
100   S4 primary vtable
101
102     vbase offset for S0
103     vbase offset for S1
104     vbase offset for S2
105     S4 offset to top
106     S4 RTTI
107     S3::s3
108     S4::s1
109
110   S2-in-S4 secondary vtable
111
112     S1 vbase offset
113     S4::s1 vcall offset
114     S0 vbase offset
115     S2:s0 vcall offset
116     S2 offset to top
117     S4 RTTI
118     S2::s0
119     S4::s1
120
121*/
122
123// These are tricks to allow us to get raw function pointers for
124// member functions.
125extern "C" {
126void _ZN2S32s3Ev ();
127void _ZN2S42s1Ev ();
128}
129
130// IA-64 uses function descriptors not function pointers in its vtables.
131#if defined __ia64__
132#define CMP_VPTR(A, B)	(*(void **)(A) == *(void **)(B))
133#ifdef _LP64
134#define INC_VPTR(A)	((A) += 2)
135#define INC_VDATA(A,N)	((A) += (N))
136#else
137#define INC_VPTR(A)	((A) += 4)
138#define INC_VDATA(A,N)	((A) += 2*(N))
139#endif
140#else
141#define CMP_VPTR(A, B)	(*(A) == (ptrdiff_t)(B))
142#define INC_VPTR(A)	((A) += 1)
143#define INC_VDATA(A,N)	((A) += (N))
144#endif
145
146int main ()
147{
148  S4 s4;
149  ptrdiff_t **vptr;
150  ptrdiff_t *vtbl;
151
152  // Set vtbl to point at the beginning of S4's primary vtable.
153  vptr = (ptrdiff_t **) &s4;
154  vtbl = *vptr;
155  INC_VDATA (vtbl, -5);
156
157  if (*vtbl != ((char*) (S0*) &s4) - (char*) &s4)
158    return 1;
159  INC_VDATA (vtbl, 1);
160  if (*vtbl != ((char*) (S1*) &s4) - (char*) &s4)
161    return 2;
162  INC_VDATA (vtbl, 1);
163  if (*vtbl != ((char*) (S2*) &s4) - (char*) &s4)
164    return 3;
165  INC_VDATA (vtbl, 1);
166  if (*vtbl != 0)
167    return 4;
168  INC_VDATA (vtbl, 1);
169  // Skip the RTTI entry.
170  INC_VDATA (vtbl, 1);
171  if (! CMP_VPTR (vtbl, &_ZN2S32s3Ev))
172    return 5;
173  INC_VPTR (vtbl);
174  if (! CMP_VPTR (vtbl, &_ZN2S42s1Ev))
175    return 6;
176  INC_VPTR (vtbl);
177  // The S1 vbase offset.
178  if (*vtbl != 0)
179    return 7;
180  INC_VDATA (vtbl, 1);
181  // The S4::s1 vcall offset is negative; once you convert to S2, you
182  // have to convert to S4 to find the final overrider.
183  if (*vtbl != ((char*) &s4 - (char*) (S2*) &s4))
184    return 8;
185  INC_VDATA (vtbl, 1);
186  if (*vtbl != 0)
187    return 9;
188  INC_VDATA (vtbl, 1);
189  if (*vtbl != 0)
190    return 10;
191  INC_VDATA (vtbl, 1);
192  // Now we're at the S2 offset to top entry.
193  if (*vtbl != ((char*) &s4 - (char*) (S2*) &s4))
194    return 11;
195  INC_VDATA (vtbl, 1);
196  // Skip the RTTI entry.
197  INC_VDATA (vtbl, 1);
198  // Skip the remaining virtual functions -- they are thunks.
199  INC_VPTR (vtbl);
200  INC_VPTR (vtbl);
201}
202
203#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
204
205int main ()
206{
207}
208
209#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
210