aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C
blob: 6bef481d8cf9dac0566dd1d06df273accf8c11b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Special g++ Options: -fno-strict-aliasing
// Origin: Mark Mitchell <mark@codesourcery.com>

/* Generally, the lowest bit of the ptr is used to indicate whether a
   ptr-to-mem-func points to a virtual or a non-virtual member
   function.  However, some platforms use all bits to encode a
   function pointer.  Such platforms use the lowest bit of the delta,
   that is shifted left by one bit.  */
#if defined __MN10300__ || defined __arm__ || defined __thumb__
#define ADJUST_PTRFN(func, virt) ((void (*)())(func))
#define ADJUST_DELTA(delta, virt) (((delta) << 1) + !!(virt))
#else
#define ADJUST_PTRFN(func, virt) ((void (*)())((ptrdiff_t)(func) + !!(virt)))
#define ADJUST_DELTA(delta, virt) (delta)
#endif

#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100

// Check that pointers-to-member functions are represented correctly.

#include <cstddef>

struct S
{
  int i;
  int j;
};

// Because S does not have a VPTR, it will not be a primary base of T,
// and will therefore end up at a non-zero offset.

struct T : public S 
{
  void f () {}
  virtual void g () {}
  virtual void h () {}
};

// Provide access to the raw function pointers.  This is
// mangling-dependent.

extern "C" void _ZN1T1fEv ();
extern "C" void _ZN1T1gEv ();
extern "C" void _ZN1T1hEv ();

// This structure is a C representation of a pointer-to-member.

struct ptrmemfunc 
{
  void (*ptr) ();
  ptrdiff_t adj;
};

typedef int S::*sdp;
typedef void (S::*sp)();
typedef void (T::*tp)();

int
main ()
{
  S s;
  T t;
  sp x;
  tp y;
  ptrmemfunc *xp = (ptrmemfunc *) &x;
  ptrmemfunc *yp = (ptrmemfunc *) &y;
  ptrdiff_t delta = ((char *) &t) - ((char*) (S*) (&t));

  // Pointers-to-function-members should have the same size and
  // alignment as the PTRMEMFUNC type.
  if (sizeof (sp) != sizeof (ptrmemfunc))
    return 1;
  if (__alignof__ (sp) != __alignof__ (ptrmemfunc))
    return 2;
  
  // The NULL pointer-to-member should have a NULL first PTR field.
  x = 0;
  if (xp->ptr != 0)
    return 3;
  y = x;
  if (yp->ptr != 0)
    return 4;
  
  // A non-virtual function should have a pointer to the function.
  // There should be no adjustment for the `T' version, and an
  // appropriate adjustment for the `S' version.
  y = &T::f;
  if (yp->ptr != ADJUST_PTRFN (&_ZN1T1fEv, 0))
    return 5;
  if (yp->adj != ADJUST_DELTA (0, 0))
    return 6;
  x = (sp) y;
  if (xp->ptr != ADJUST_PTRFN (&_ZN1T1fEv, 0))
    return 7;
  if (xp->adj != ADJUST_DELTA (delta, 0))
    return 8;

  // For a virtual function, we should see the vtable offset, plus
  // one.  `T::h' is in the second slot: the vtable pointer points to
  // the first virtual function.
  y = &T::h;
  if (yp->ptr != ADJUST_PTRFN (sizeof (void *), 1))
    return 9;
  if (yp->adj != ADJUST_DELTA (0, 1))
    return 10;
  x = (sp) y;
  if (xp->ptr != ADJUST_PTRFN (sizeof (void *), 1))
    return 11;
  if (xp->adj != ADJUST_DELTA (delta, 1))
    return 12;

  // Pointers-to-data-members should have the same size and alignment
  // as a ptrdiff_t.
  if (sizeof (sdp) != sizeof (ptrdiff_t))
    return 13;
  if (__alignof__ (sdp) != __alignof__ (ptrdiff_t))
    return 14;

  // The value of a pointer-to-data member should be the offset from
  // the start of the structure.
  sdp z = &S::j;
  if ((char *) &s.j - (char *) &s != *((ptrdiff_t *) &z))
    return 15;
  z = 0;
  if (*((ptrdiff_t *) &z) != -1)
    return 16;
}

#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */

int main () 
{
}

#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */