Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / native_client / tests / toolchain / method_pointer_repr.cc
1 /*
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.
5  */
6
7 #include <stddef.h>
8 #include <string.h>
9
10 #include "native_client/src/include/nacl_assert.h"
11
12
13 // This test checks the representation of C++ method pointers used by
14 // the C++ front end.
15
16 // Define example classes where a method pointer's this-offset and
17 // vtable-offset are both non-zero.
18
19 class TestBaseClass1 {
20  public:
21   virtual ~TestBaseClass1() {}
22   virtual void some_virtual() {}
23   char data[1000];
24 };
25
26 class TestBaseClass2 {
27  public:
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; }
33 };
34
35 class TestClass : public TestBaseClass1, public TestBaseClass2 {
36 };
37
38 // Offset of virtual_method() in vtable: it comes after
39 // ~TestBaseClass1(), ~TestBaseClass2(), other_method1() and
40 // other_method2().
41 const int kVtableOffset = sizeof(void *) * 4;
42 const int kThisOffset = sizeof(TestBaseClass1);
43
44 // Mangled name for TestBaseClass2::method()
45 #define NONVIRTUAL_METHOD _ZN14TestBaseClass217nonvirtual_methodEv
46 extern "C" void NONVIRTUAL_METHOD();
47
48
49 typedef int (TestClass::*method_ptr)();
50
51 struct method_ptr_repr {
52   ptrdiff_t ptr;
53   ptrdiff_t adj;
54 };
55
56
57 int main() {
58   ASSERT_EQ(sizeof(method_ptr), 8);
59   ASSERT_EQ(kThisOffset, 1004);
60
61   method_ptr nonvirtual_mp = &TestClass::nonvirtual_method;
62   method_ptr virtual_mp = &TestClass::virtual_method;
63
64   // Check that method pointers work.
65   TestClass instance;
66   ASSERT_EQ((instance.*nonvirtual_mp)(), 123);
67   ASSERT_EQ((instance.*virtual_mp)(), 456);
68
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));
74
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).
80
81   ASSERT_EQ(nonvirtual_mpr.ptr, (ptrdiff_t) NONVIRTUAL_METHOD);
82   ASSERT_EQ(nonvirtual_mpr.adj, kThisOffset << 1);
83
84   ASSERT_EQ(virtual_mpr.ptr, kVtableOffset);
85   ASSERT_EQ(virtual_mpr.adj, (kThisOffset << 1) + 1);
86 #else
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.
90
91   ASSERT_EQ(nonvirtual_mpr.ptr, (ptrdiff_t) NONVIRTUAL_METHOD);
92   ASSERT_EQ(nonvirtual_mpr.adj, kThisOffset);
93
94   ASSERT_EQ(virtual_mpr.ptr, kVtableOffset + 1);
95   ASSERT_EQ(virtual_mpr.adj, kThisOffset);
96 #endif
97
98   return 0;
99 }