1 // { dg-do run  }
2 // { dg-options "-fno-strict-aliasing" }
3 // Origin: Mark Mitchell <mark@codesourcery.com>
4 
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__
11 #define ADJUST_PTRFN(func, virt) ((void (*)())(func))
12 #define ADJUST_DELTA(delta, virt) (((delta) << 1) + !!(virt))
13 #else
14 #define ADJUST_PTRFN(func, virt) ((void (*)())((ptrdiff_t)(func) + !!(virt)))
15 #define ADJUST_DELTA(delta, virt) (delta)
16 #endif
17 
18 /* IA64 uses function descriptors instead of function pointers in its
19    vtables, which means that we can't meaningfully compare them directly.  */
20 #if defined __ia64__
21 #define CMP_PTRFN(A, B)	(*(void **)(A) == *(void **)(B))
22 #define VPTE_SIZE	(16)
23 #else
24 #define CMP_PTRFN(A, B) ((A) == (B))
25 #define VPTE_SIZE	sizeof(void *)
26 #endif
27 
28 #if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
29 
30 // Check that pointers-to-member functions are represented correctly.
31 
32 #include <cstddef>
33 
34 struct S
35 {
36   int i;
37   int j;
38 };
39 
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.
42 
43 struct T : public S
44 {
fT45   void f () {}
gT46   virtual void g () {}
hT47   virtual void h () {}
48 };
49 
50 // Provide access to the raw function pointers.  This is
51 // mangling-dependent.
52 
53 extern "C" void _ZN1T1fEv ();
54 extern "C" void _ZN1T1gEv ();
55 extern "C" void _ZN1T1hEv ();
56 
57 // This structure is a C representation of a pointer-to-member.
58 
59 struct ptrmemfunc
60 {
61   void (*ptr) ();
62   ptrdiff_t adj;
63 };
64 
65 typedef int S::*sdp;
66 typedef void (S::*sp)();
67 typedef void (T::*tp)();
68 
69 int
main()70 main ()
71 {
72   S s;
73   T t;
74   sp x;
75   tp y;
76   ptrmemfunc *xp = (ptrmemfunc *) &x;
77   ptrmemfunc *yp = (ptrmemfunc *) &y;
78   ptrdiff_t delta = ((char *) &t) - ((char*) (S*) (&t));
79 
80   // Pointers-to-function-members should have the same size and
81   // alignment as the PTRMEMFUNC type.
82   if (sizeof (sp) != sizeof (ptrmemfunc))
83     return 1;
84   if (__alignof__ (sp) != __alignof__ (ptrmemfunc))
85     return 2;
86 
87   // The NULL pointer-to-member should have a NULL first PTR field.
88   x = 0;
89   if (xp->ptr != 0)
90     return 3;
91   y = x;
92   if (yp->ptr != 0)
93     return 4;
94 
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.
98   y = &T::f;
99   if (! CMP_PTRFN (yp->ptr, ADJUST_PTRFN (&_ZN1T1fEv, 0)))
100     return 5;
101   if (yp->adj != ADJUST_DELTA (0, 0))
102     return 6;
103   x = (sp) y;
104   if (! CMP_PTRFN (xp->ptr, ADJUST_PTRFN (&_ZN1T1fEv, 0)))
105     return 7;
106   if (xp->adj != ADJUST_DELTA (delta, 0))
107     return 8;
108 
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.
112   y = &T::h;
113   if (yp->ptr != ADJUST_PTRFN (VPTE_SIZE, 1))
114     return 9;
115   if (yp->adj != ADJUST_DELTA (0, 1))
116     return 10;
117   x = (sp) y;
118   if (xp->ptr != ADJUST_PTRFN (VPTE_SIZE, 1))
119     return 11;
120   if (xp->adj != ADJUST_DELTA (delta, 1))
121     return 12;
122 
123   // Pointers-to-data-members should have the same size and alignment
124   // as a ptrdiff_t.
125   if (sizeof (sdp) != sizeof (ptrdiff_t))
126     return 13;
127   if (__alignof__ (sdp) != __alignof__ (ptrdiff_t))
128     return 14;
129 
130   // The value of a pointer-to-data member should be the offset from
131   // the start of the structure.
132   sdp z = &S::j;
133   if ((char *) &s.j - (char *) &s != *((ptrdiff_t *) &z))
134     return 15;
135   z = 0;
136   if (*((ptrdiff_t *) &z) != -1)
137     return 16;
138 }
139 
140 #else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
141 
main()142 int main ()
143 {
144 }
145 
146 #endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
147