1 // { dg-do run } 2 // { dg-options "-fno-strict-aliasing" } 3 // Origin: Mark Mitchell <mark (at) 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 35 void S0::s0 () 36 { 37 } 38 39 void S1::s1 () 40 { 41 } 42 43 void S2::s1 () 44 { 45 } 46 47 void S2::s0 () 48 { 49 } 50 51 void S3::s3 () 52 { 53 } 54 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 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 209 int main () 210 { 211 } 212 213 #endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */ 214