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