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
8 struct S0
9 {
10 virtual void s0 ();
11 };
12
13 struct S1 : virtual public S0
14 {
15 virtual void s1 ();
16 };
17
18 struct S2 : virtual public S1
19 {
20 virtual void s1 ();
21 virtual void s0 ();
22 };
23
24 struct S3
25 {
26 virtual void s3 ();
27 };
28
29 struct S4 : public S3, virtual public S2
30 {
31 virtual void s1 ();
32 };
33
s0()34 void S0::s0 ()
35 {
36 }
37
s1()38 void S1::s1 ()
39 {
40 }
41
s1()42 void S2::s1 ()
43 {
44 }
45
s0()46 void S2::s0 ()
47 {
48 }
49
s3()50 void S3::s3 ()
51 {
52 }
53
s1()54 void 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.
125 extern "C" {
126 void _ZN2S32s3Ev ();
127 void _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
main()146 int 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
main()205 int main ()
206 {
207 }
208
209 #endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
210