2 // { dg-options "-fno-strict-aliasing" }
3 // Origin: Mark Mitchell <mark@codesourcery.com>
5 /* Generally, the lowest bit of the ptr is used to indicate whether a
6 ptr-to-mem-func points to a virtual or a non-virtual member
7 function. However, some platforms use all bits to encode a
8 function pointer. Such platforms use the lowest bit of the delta,
9 that is shifted left by one bit. */
10 #if defined __MN10300__ || defined __SH5__ || defined __arm__ || defined __thumb__ || defined __mips__ || defined __aarch64__ || defined __PRU__ || defined __loongarch__
11 #define ADJUST_PTRFN(func, virt) ((void (*)())(func))
12 #define ADJUST_DELTA(delta, virt) (((delta) << 1) + !!(virt))
14 #define ADJUST_PTRFN(func, virt) ((void (*)())((ptrdiff_t)(func) + !!(virt)))
15 #define ADJUST_DELTA(delta, virt) (delta)
18 /* IA64 uses function descriptors instead of function pointers in its
19 vtables, which means that we can't meaningfully compare them directly. */
21 #define CMP_PTRFN(A, B) (*(void **)(A) == *(void **)(B))
22 #define VPTE_SIZE (16)
24 #define CMP_PTRFN(A, B) ((A) == (B))
25 #define VPTE_SIZE sizeof(void *)
28 #if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
30 // Check that pointers-to-member functions are represented correctly.
40 // Because S does not have a VPTR, it will not be a primary base of T,
41 // and will therefore end up at a nonzero offset.
50 // Provide access to the raw function pointers. This is
51 // mangling-dependent.
53 extern "C" void _ZN1T1fEv ();
54 extern "C" void _ZN1T1gEv ();
55 extern "C" void _ZN1T1hEv ();
57 // This structure is a C representation of a pointer-to-member.
66 typedef void (S::*sp)();
67 typedef void (T::*tp)();
76 ptrmemfunc *xp = (ptrmemfunc *) &x;
77 ptrmemfunc *yp = (ptrmemfunc *) &y;
78 ptrdiff_t delta = ((char *) &t) - ((char*) (S*) (&t));
80 // Pointers-to-function-members should have the same size and
81 // alignment as the PTRMEMFUNC type.
82 if (sizeof (sp) != sizeof (ptrmemfunc))
84 if (__alignof__ (sp) != __alignof__ (ptrmemfunc))
87 // The NULL pointer-to-member should have a NULL first PTR field.
95 // A non-virtual function should have a pointer to the function.
96 // There should be no adjustment for the `T' version, and an
97 // appropriate adjustment for the `S' version.
99 if (! CMP_PTRFN (yp->ptr, ADJUST_PTRFN (&_ZN1T1fEv, 0)))
101 if (yp->adj != ADJUST_DELTA (0, 0))
104 if (! CMP_PTRFN (xp->ptr, ADJUST_PTRFN (&_ZN1T1fEv, 0)))
106 if (xp->adj != ADJUST_DELTA (delta, 0))
109 // For a virtual function, we should see the vtable offset, plus
110 // one. `T::h' is in the second slot: the vtable pointer points to
111 // the first virtual function.
113 if (yp->ptr != ADJUST_PTRFN (VPTE_SIZE, 1))
115 if (yp->adj != ADJUST_DELTA (0, 1))
118 if (xp->ptr != ADJUST_PTRFN (VPTE_SIZE, 1))
120 if (xp->adj != ADJUST_DELTA (delta, 1))
123 // Pointers-to-data-members should have the same size and alignment
125 if (sizeof (sdp) != sizeof (ptrdiff_t))
127 if (__alignof__ (sdp) != __alignof__ (ptrdiff_t))
130 // The value of a pointer-to-data member should be the offset from
131 // the start of the structure.
133 if ((char *) &s.j - (char *) &s != *((ptrdiff_t *) &z))
136 if (*((ptrdiff_t *) &z) != -1)
140 #else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
146 #endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */