summaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C
downloadcbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2
cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository.
Diffstat (limited to 'gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C')
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C146
1 files changed, 146 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C b/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C
new file mode 100644
index 000000000..077fa5084
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C
@@ -0,0 +1,146 @@
+// { dg-do run }
+// { dg-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 __SH5__ || defined __arm__ || defined __thumb__ || defined __mips__
+#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
+
+/* IA64 uses function descriptors instead of function pointers in its
+ vtables, which means that we can't meaningfully compare them directly. */
+#if defined __ia64__
+#define CMP_PTRFN(A, B) (*(void **)(A) == *(void **)(B))
+#define VPTE_SIZE (16)
+#else
+#define CMP_PTRFN(A, B) ((A) == (B))
+#define VPTE_SIZE sizeof(void *)
+#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 nonzero 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 (! CMP_PTRFN (yp->ptr, ADJUST_PTRFN (&_ZN1T1fEv, 0)))
+ return 5;
+ if (yp->adj != ADJUST_DELTA (0, 0))
+ return 6;
+ x = (sp) y;
+ if (! CMP_PTRFN (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 (VPTE_SIZE, 1))
+ return 9;
+ if (yp->adj != ADJUST_DELTA (0, 1))
+ return 10;
+ x = (sp) y;
+ if (xp->ptr != ADJUST_PTRFN (VPTE_SIZE, 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) */