2 * Copyright (c) 2013 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
10 #include "native_client/src/include/nacl_assert.h"
13 // This test checks the representation of C++ method pointers used by
16 // Define example classes where a method pointer's this-offset and
17 // vtable-offset are both non-zero.
19 class TestBaseClass1 {
21 virtual ~TestBaseClass1() {}
22 virtual void some_virtual() {}
26 class TestBaseClass2 {
28 virtual ~TestBaseClass2() {}
29 int nonvirtual_method() { return 123; }
30 virtual void other_method1() {}
31 virtual void other_method2() {}
32 virtual int virtual_method() { return 456; }
35 class TestClass : public TestBaseClass1, public TestBaseClass2 {
38 // Offset of virtual_method() in vtable: it comes after
39 // ~TestBaseClass1(), ~TestBaseClass2(), other_method1() and
41 const int kVtableOffset = sizeof(void *) * 4;
42 const int kThisOffset = sizeof(TestBaseClass1);
44 // Mangled name for TestBaseClass2::method()
45 #define NONVIRTUAL_METHOD _ZN14TestBaseClass217nonvirtual_methodEv
46 extern "C" void NONVIRTUAL_METHOD();
49 typedef int (TestClass::*method_ptr)();
51 struct method_ptr_repr {
58 ASSERT_EQ(sizeof(method_ptr), 8);
59 ASSERT_EQ(kThisOffset, 1004);
61 method_ptr nonvirtual_mp = &TestClass::nonvirtual_method;
62 method_ptr virtual_mp = &TestClass::virtual_method;
64 // Check that method pointers work.
66 ASSERT_EQ((instance.*nonvirtual_mp)(), 123);
67 ASSERT_EQ((instance.*virtual_mp)(), 456);
69 method_ptr_repr nonvirtual_mpr;
70 method_ptr_repr virtual_mpr;
71 // Copy to avoid strict-aliasing problems.
72 memcpy(&nonvirtual_mpr, &nonvirtual_mp, sizeof(method_ptr));
73 memcpy(&virtual_mpr, &virtual_mp, sizeof(method_ptr));
75 #if defined(__arm__) || defined(__pnacl__)
76 // In the ARM scheme, adj & 1 indicates whether the method is
77 // virtual. This makes no assumption about the alignment of
78 // function pointers. PNaCl uses the same scheme (see
79 // https://code.google.com/p/nativeclient/issues/detail?id=3450).
81 ASSERT_EQ(nonvirtual_mpr.ptr, (ptrdiff_t) NONVIRTUAL_METHOD);
82 ASSERT_EQ(nonvirtual_mpr.adj, kThisOffset << 1);
84 ASSERT_EQ(virtual_mpr.ptr, kVtableOffset);
85 ASSERT_EQ(virtual_mpr.adj, (kThisOffset << 1) + 1);
87 // In the Itanium scheme (used for x86), ptr & 1 indicates whether
88 // the method is virtual. This assumes that function pointers are 0
89 // mod 2, so we do not want to use this scheme for PNaCl.
91 ASSERT_EQ(nonvirtual_mpr.ptr, (ptrdiff_t) NONVIRTUAL_METHOD);
92 ASSERT_EQ(nonvirtual_mpr.adj, kThisOffset);
94 ASSERT_EQ(virtual_mpr.ptr, kVtableOffset + 1);
95 ASSERT_EQ(virtual_mpr.adj, kThisOffset);