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 136 137 138
|
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/synchronization/mutex.h"
#include <cstdlib>
#include <string>
#include "gtest/gtest.h"
#include "absl/base/config.h"
namespace {
class IncompleteClass;
#ifdef _MSC_VER
// These tests verify expectations about sizes of MSVC pointers to methods.
// Pointers to methods are distinguished by whether their class hierarchies
// contain single inheritance, multiple inheritance, or virtual inheritance.
// Declare classes of the various MSVC inheritance types.
class __single_inheritance SingleInheritance{};
class __multiple_inheritance MultipleInheritance;
class __virtual_inheritance VirtualInheritance;
TEST(MutexMethodPointerTest, MicrosoftMethodPointerSize) {
void (SingleInheritance::*single_inheritance_method_pointer)();
void (MultipleInheritance::*multiple_inheritance_method_pointer)();
void (VirtualInheritance::*virtual_inheritance_method_pointer)();
#if defined(_M_IX86) || defined(_M_ARM)
static_assert(sizeof(single_inheritance_method_pointer) == 4,
"Unexpected sizeof(single_inheritance_method_pointer).");
static_assert(sizeof(multiple_inheritance_method_pointer) == 8,
"Unexpected sizeof(multiple_inheritance_method_pointer).");
static_assert(sizeof(virtual_inheritance_method_pointer) == 12,
"Unexpected sizeof(virtual_inheritance_method_pointer).");
#elif defined(_M_X64) || defined(__aarch64__)
static_assert(sizeof(single_inheritance_method_pointer) == 8,
"Unexpected sizeof(single_inheritance_method_pointer).");
static_assert(sizeof(multiple_inheritance_method_pointer) == 16,
"Unexpected sizeof(multiple_inheritance_method_pointer).");
static_assert(sizeof(virtual_inheritance_method_pointer) == 16,
"Unexpected sizeof(virtual_inheritance_method_pointer).");
#endif
void (IncompleteClass::*incomplete_class_method_pointer)();
static_assert(sizeof(incomplete_class_method_pointer) >=
sizeof(virtual_inheritance_method_pointer),
"Failed invariant: sizeof(incomplete_class_method_pointer) >= "
"sizeof(virtual_inheritance_method_pointer)!");
}
class Callback {
bool x = true;
public:
Callback() {}
bool method() {
x = !x;
return x;
}
};
class M2 {
bool x = true;
public:
M2() {}
bool method2() {
x = !x;
return x;
}
};
class MultipleInheritance : public Callback, public M2 {};
TEST(MutexMethodPointerTest, ConditionWithMultipleInheritanceMethod) {
// This test ensures that Condition can deal with method pointers from classes
// with multiple inheritance.
MultipleInheritance object = MultipleInheritance();
absl::Condition condition(&object, &MultipleInheritance::method);
EXPECT_FALSE(condition.Eval());
EXPECT_TRUE(condition.Eval());
}
class __virtual_inheritance VirtualInheritance : virtual public Callback {
bool x = false;
public:
VirtualInheritance() {}
bool method() {
x = !x;
return x;
}
};
TEST(MutexMethodPointerTest, ConditionWithVirtualInheritanceMethod) {
// This test ensures that Condition can deal with method pointers from classes
// with virtual inheritance.
VirtualInheritance object = VirtualInheritance();
absl::Condition condition(&object, &VirtualInheritance::method);
EXPECT_TRUE(condition.Eval());
EXPECT_FALSE(condition.Eval());
}
#endif // #ifdef _MSC_VER
TEST(MutexMethodPointerTest, ConditionWithIncompleteClassMethod) {
using IncompleteClassMethodPointer = void (IncompleteClass::*)();
union CallbackSlot {
void (*anonymous_function_pointer)();
IncompleteClassMethodPointer incomplete_class_method_pointer;
};
static_assert(sizeof(CallbackSlot) >= sizeof(IncompleteClassMethodPointer),
"The callback slot is not big enough for method pointers.");
static_assert(
sizeof(CallbackSlot) == sizeof(IncompleteClassMethodPointer),
"The callback slot is not big enough for anonymous function pointers.");
#if defined(_MSC_VER)
static_assert(sizeof(IncompleteClassMethodPointer) <= 24,
"The pointer to a method of an incomplete class is too big.");
#endif
}
} // namespace
|