// -*- C++ -*- //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef SUPPORT_POISONED_HASH_HELPER_HPP #define SUPPORT_POISONED_HASH_HELPER_HPP #include #include #include "test_macros.h" #include "test_workarounds.h" #if TEST_STD_VER < 11 #error this header may only be used in C++11 or newer #endif template struct TypeList; // Test that the specified Hash meets the requirements of an enabled hash template void test_hash_enabled(InputKey const& key = InputKey{}); template void test_hash_enabled_for_type(InputKey const& key = InputKey{}) { return test_hash_enabled, T, InputKey>(key); } // Test that the specified Hash meets the requirements of a disabled hash. template void test_hash_disabled(); template void test_hash_disabled_for_type() { return test_hash_disabled, T>(); } namespace PoisonedHashDetail { enum Enum {}; enum EnumClass : bool {}; struct Class {}; } // Each header that declares the template hash provides enabled // specializations of hash for nullptr t and all cv-unqualified // arithmetic, enumeration, and pointer types. using LibraryHashTypes = TypeList< #if !defined(TEST_WORKAROUND_C1XX_BROKEN_NULLPTR_CONVERSION_OPERATOR) #if TEST_STD_VER > 14 decltype(nullptr), #endif #endif bool, char, signed char, unsigned char, wchar_t, #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS char16_t, char32_t, #endif short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long, #ifndef _LIBCPP_HAS_NO_INT128 __int128_t, __uint128_t, #endif float, double, long double, #if TEST_STD_VER >= 14 // Enum types PoisonedHashDetail::Enum, PoisonedHashDetail::EnumClass, #endif // pointer types void*, void const*, PoisonedHashDetail::Class* >; // Test that each of the library hash specializations for arithmetic types, // enum types, and pointer types are available and enabled. template void test_library_hash_specializations_available(Types = Types{}); namespace PoisonedHashDetail { template constexpr bool instantiate(int) { return true; } template constexpr bool instantiate(long) { return true; } template constexpr bool instantiate() { return instantiate(0); } template struct ConvertibleToSimple { operator To() const { return To{}; } }; template struct ConvertibleTo { To to{}; operator To&() & { return to; } operator To const&() const & { return to; } operator To&&() && { return std::move(to); } operator To const&&() const && { return std::move(to); } }; template ::type> constexpr bool can_hash(int) { return std::is_same::value; } template constexpr bool can_hash(long) { return false; } template constexpr bool can_hash() { return can_hash(0); } } // namespace PoisonedHashDetail template void test_hash_enabled(InputKey const& key) { using namespace PoisonedHashDetail; static_assert(std::is_destructible::value, ""); // Enabled hash requirements static_assert(std::is_default_constructible::value, ""); static_assert(std::is_copy_constructible::value, ""); static_assert(std::is_move_constructible::value, ""); static_assert(std::is_copy_assignable::value, ""); static_assert(std::is_move_assignable::value, ""); #if TEST_STD_VER > 14 static_assert(std::is_swappable::value, ""); #elif defined(_LIBCPP_VERSION) static_assert(std::__is_swappable::value, ""); #endif // Hashable requirements using CKey = ConvertibleTo; static_assert(can_hash(), ""); static_assert(can_hash(), ""); static_assert(can_hash(), ""); static_assert(can_hash(), ""); static_assert(can_hash(), ""); static_assert(can_hash(), ""); static_assert(can_hash&)>(), ""); static_assert(can_hash const&)>(), ""); static_assert(can_hash&&)>(), ""); static_assert(can_hash&)>(), ""); static_assert(can_hash const&)>(), ""); static_assert(can_hash &&)>(), ""); static_assert(can_hash const&&)>(), ""); const Hash h{}; assert(h(key) == h(key)); } template void test_hash_disabled() { using namespace PoisonedHashDetail; // Disabled hash requirements static_assert(!std::is_default_constructible::value, ""); static_assert(!std::is_copy_constructible::value, ""); static_assert(!std::is_move_constructible::value, ""); static_assert(!std::is_copy_assignable::value, ""); static_assert(!std::is_move_assignable::value, ""); static_assert(!std::is_function< typename std::remove_pointer< typename std::remove_reference::type >::type >::value, ""); // Hashable requirements using CKey = ConvertibleTo; static_assert(!can_hash(), ""); static_assert(!can_hash(), ""); static_assert(!can_hash(), ""); static_assert(!can_hash(), ""); static_assert(!can_hash(), ""); static_assert(!can_hash(), ""); static_assert(!can_hash&)>(), ""); static_assert(!can_hash const&)>(), ""); static_assert(!can_hash&&)>(), ""); static_assert(!can_hash&)>(), ""); static_assert(!can_hash const&)>(), ""); static_assert(!can_hash &&)>(), ""); static_assert(!can_hash const&&)>(), ""); } template struct TypeList { template