| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // TODO: Make this test pass for all standards. |
| // XFAIL: c++98, c++03 |
| |
| // <type_traits> |
| |
| // __convert_to_integral(Tp) |
| |
| // Test that the __convert_to_integral functions properly converts Tp to the |
| // correct type and value for integral, enum and user defined types. |
| |
| #include <limits> |
| #include <type_traits> |
| #include <cstdint> |
| #include <cassert> |
| |
| #include "user_defined_integral.hpp" |
| |
| #include "test_macros.h" |
| |
| template <class T> |
| struct EnumType |
| { |
| enum type : T {E_zero, E_one}; |
| }; |
| |
| |
| template <class From, class To> |
| void check_integral_types() |
| { |
| typedef std::numeric_limits<From> Limits; |
| const From max = Limits::max(); |
| const From min = Limits::min(); |
| { |
| auto ret = std::__convert_to_integral((From)max); |
| assert(ret == max); |
| ret = std::__convert_to_integral((From)min); |
| assert(ret == min); |
| static_assert(std::is_same<decltype(ret), To>::value, ""); |
| } |
| { |
| UserDefinedIntegral<From> f(max); |
| auto ret = std::__convert_to_integral(f); |
| assert(ret == max); |
| f.value = min; |
| ret = std::__convert_to_integral(f); |
| assert(ret == min); |
| static_assert(std::is_same<decltype(ret), To>::value, ""); |
| } |
| { |
| typedef typename EnumType<From>::type Enum; |
| Enum e(static_cast<Enum>(max)); |
| auto ret = std::__convert_to_integral(e); |
| assert(ret == max); |
| e = static_cast<Enum>(min); |
| ret = std::__convert_to_integral(min); |
| assert(ret == min); |
| static_assert(std::is_same<decltype(ret), To>::value, ""); |
| } |
| } |
| |
| |
| template <class From, class To> |
| void check_enum_types() |
| { |
| auto ret = std::__convert_to_integral((From)1); |
| assert(ret == 1); |
| static_assert(std::is_same<decltype(ret), To>::value, ""); |
| } |
| |
| |
| enum enum1 { zero = 0, one = 1 }; |
| enum enum2 : unsigned long { |
| value = std::numeric_limits<unsigned long>::max() |
| }; |
| |
| int main(int, char**) |
| { |
| check_integral_types<bool, int>(); |
| check_integral_types<char, int>(); |
| check_integral_types<signed char, int>(); |
| check_integral_types<unsigned char, int>(); |
| check_integral_types<wchar_t, decltype(((wchar_t)1) + 1)>(); |
| check_integral_types<char16_t, int>(); |
| // On some platforms, unsigned int and long are the same size. These |
| // platforms have a choice of making uint32_t an int or a long. However |
| // char32_t must promote to an unsigned int on these platforms [conv.prom]. |
| // Use the following logic to make the test work on such platforms. |
| // (sizeof(uint32_t) == sizeof(unsigned int)) ? unsigned int : uint32_t; |
| typedef std::conditional<sizeof(uint32_t) == sizeof(unsigned int), |
| unsigned int, uint32_t>::type char_integral; |
| check_integral_types<char32_t, char_integral>(); |
| check_integral_types<short, int>(); |
| check_integral_types<unsigned short, int>(); |
| check_integral_types<int, int>(); |
| check_integral_types<unsigned, unsigned>(); |
| check_integral_types<long, long>(); |
| check_integral_types<unsigned long, unsigned long>(); |
| check_integral_types<long long, long long>(); |
| check_integral_types<unsigned long long, unsigned long long>(); |
| #ifndef _LIBCPP_HAS_NO_INT128 |
| check_integral_types<__int128_t, __int128_t>(); |
| check_integral_types<__uint128_t, __uint128_t>(); |
| #endif |
| // TODO(ericwf): Not standard |
| typedef std::underlying_type<enum1>::type Enum1UT; |
| check_enum_types<enum1, decltype(((Enum1UT)1) + 1)>(); |
| typedef std::underlying_type<enum2>::type Enum2UT; |
| check_enum_types<enum2, decltype(((Enum2UT)1) + 1)>(); |
| |
| return 0; |
| } |