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