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