• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "absl/synchronization/mutex.h"
16 
17 #include <cstdlib>
18 #include <string>
19 
20 #include "gtest/gtest.h"
21 #include "absl/base/config.h"
22 
23 namespace {
24 
25 class IncompleteClass;
26 
27 #ifdef _MSC_VER
28 // These tests verify expectations about sizes of MSVC pointers to methods.
29 // Pointers to methods are distinguished by whether their class hierarchies
30 // contain single inheritance, multiple inheritance, or virtual inheritance.
31 
32 // Declare classes of the various MSVC inheritance types.
33 class __single_inheritance SingleInheritance{};
34 class __multiple_inheritance MultipleInheritance;
35 class __virtual_inheritance VirtualInheritance;
36 
TEST(MutexMethodPointerTest,MicrosoftMethodPointerSize)37 TEST(MutexMethodPointerTest, MicrosoftMethodPointerSize) {
38   void (SingleInheritance::*single_inheritance_method_pointer)();
39   void (MultipleInheritance::*multiple_inheritance_method_pointer)();
40   void (VirtualInheritance::*virtual_inheritance_method_pointer)();
41 
42 #if defined(_M_IX86) || defined(_M_ARM)
43   static_assert(sizeof(single_inheritance_method_pointer) == 4,
44                 "Unexpected sizeof(single_inheritance_method_pointer).");
45   static_assert(sizeof(multiple_inheritance_method_pointer) == 8,
46                 "Unexpected sizeof(multiple_inheritance_method_pointer).");
47   static_assert(sizeof(virtual_inheritance_method_pointer) == 12,
48                 "Unexpected sizeof(virtual_inheritance_method_pointer).");
49 #elif defined(_M_X64) || defined(__aarch64__)
50   static_assert(sizeof(single_inheritance_method_pointer) == 8,
51                 "Unexpected sizeof(single_inheritance_method_pointer).");
52   static_assert(sizeof(multiple_inheritance_method_pointer) == 16,
53                 "Unexpected sizeof(multiple_inheritance_method_pointer).");
54   static_assert(sizeof(virtual_inheritance_method_pointer) == 16,
55                 "Unexpected sizeof(virtual_inheritance_method_pointer).");
56 #endif
57   void (IncompleteClass::*incomplete_class_method_pointer)();
58   static_assert(sizeof(incomplete_class_method_pointer) >=
59                     sizeof(virtual_inheritance_method_pointer),
60                 "Failed invariant: sizeof(incomplete_class_method_pointer) >= "
61                 "sizeof(virtual_inheritance_method_pointer)!");
62 }
63 
64 class Callback {
65   bool x = true;
66 
67  public:
Callback()68   Callback() {}
method()69   bool method() {
70     x = !x;
71     return x;
72   }
73 };
74 
75 class M2 {
76   bool x = true;
77 
78  public:
M2()79   M2() {}
method2()80   bool method2() {
81     x = !x;
82     return x;
83   }
84 };
85 
86 class MultipleInheritance : public Callback, public M2 {};
87 
TEST(MutexMethodPointerTest,ConditionWithMultipleInheritanceMethod)88 TEST(MutexMethodPointerTest, ConditionWithMultipleInheritanceMethod) {
89   // This test ensures that Condition can deal with method pointers from classes
90   // with multiple inheritance.
91   MultipleInheritance object = MultipleInheritance();
92   absl::Condition condition(&object, &MultipleInheritance::method);
93   EXPECT_FALSE(condition.Eval());
94   EXPECT_TRUE(condition.Eval());
95 }
96 
97 class __virtual_inheritance VirtualInheritance : virtual public Callback {
98   bool x = false;
99 
100  public:
VirtualInheritance()101   VirtualInheritance() {}
method()102   bool method() {
103     x = !x;
104     return x;
105   }
106 };
107 
TEST(MutexMethodPointerTest,ConditionWithVirtualInheritanceMethod)108 TEST(MutexMethodPointerTest, ConditionWithVirtualInheritanceMethod) {
109   // This test ensures that Condition can deal with method pointers from classes
110   // with virtual inheritance.
111   VirtualInheritance object = VirtualInheritance();
112   absl::Condition condition(&object, &VirtualInheritance::method);
113   EXPECT_TRUE(condition.Eval());
114   EXPECT_FALSE(condition.Eval());
115 }
116 #endif  // #ifdef _MSC_VER
117 
TEST(MutexMethodPointerTest,ConditionWithIncompleteClassMethod)118 TEST(MutexMethodPointerTest, ConditionWithIncompleteClassMethod) {
119   using IncompleteClassMethodPointer = void (IncompleteClass::*)();
120 
121   union CallbackSlot {
122     void (*anonymous_function_pointer)();
123     IncompleteClassMethodPointer incomplete_class_method_pointer;
124   };
125 
126   static_assert(sizeof(CallbackSlot) >= sizeof(IncompleteClassMethodPointer),
127                 "The callback slot is not big enough for method pointers.");
128   static_assert(
129       sizeof(CallbackSlot) == sizeof(IncompleteClassMethodPointer),
130       "The callback slot is not big enough for anonymous function pointers.");
131 
132 #if defined(_MSC_VER)
133   static_assert(sizeof(IncompleteClassMethodPointer) <= 24,
134                 "The pointer to a method of an incomplete class is too big.");
135 #endif
136 }
137 
138 }  // namespace
139