1 | //===----------------------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // TODO: Make this test pass for all standards. |
10 | // XFAIL: c++03 |
11 | |
12 | // <type_traits> |
13 | |
14 | // __convert_to_integral(Tp) |
15 | |
16 | // Test that the __convert_to_integral functions properly converts Tp to the |
17 | // correct type and value for integral, enum and user defined types. |
18 | |
19 | #include "test_macros.h" |
20 | |
21 | TEST_CLANG_DIAGNOSTIC_IGNORED("-Wprivate-header" ) |
22 | #include <__utility/convert_to_integral.h> |
23 | #include <limits> |
24 | #include <type_traits> |
25 | #include <cstdint> |
26 | #include <cassert> |
27 | |
28 | #include "user_defined_integral.h" |
29 | |
30 | template <class T> |
31 | struct EnumType |
32 | { |
33 | enum type : T {E_zero, E_one}; |
34 | }; |
35 | |
36 | |
37 | template <class From, class To> |
38 | void check_integral_types() |
39 | { |
40 | typedef std::numeric_limits<From> Limits; |
41 | const From max = Limits::max(); |
42 | const From min = Limits::min(); |
43 | { |
44 | auto ret = std::__convert_to_integral((From)max); |
45 | assert(ret == max); |
46 | ret = std::__convert_to_integral((From)min); |
47 | assert(ret == min); |
48 | static_assert(std::is_same<decltype(ret), To>::value, "" ); |
49 | } |
50 | { |
51 | UserDefinedIntegral<From> f(max); |
52 | auto ret = std::__convert_to_integral(f); |
53 | assert(ret == max); |
54 | f.value = min; |
55 | ret = std::__convert_to_integral(f); |
56 | assert(ret == min); |
57 | static_assert(std::is_same<decltype(ret), To>::value, "" ); |
58 | } |
59 | { |
60 | typedef typename EnumType<From>::type Enum; |
61 | Enum e(static_cast<Enum>(max)); |
62 | auto ret = std::__convert_to_integral(e); |
63 | assert(ret == max); |
64 | e = static_cast<Enum>(min); |
65 | ret = std::__convert_to_integral(min); |
66 | assert(ret == min); |
67 | static_assert(std::is_same<decltype(ret), To>::value, "" ); |
68 | } |
69 | } |
70 | |
71 | |
72 | template <class From, class To> |
73 | void check_enum_types() |
74 | { |
75 | auto ret = std::__convert_to_integral((From)1); |
76 | assert(ret == 1); |
77 | static_assert(std::is_same<decltype(ret), To>::value, "" ); |
78 | } |
79 | |
80 | |
81 | enum enum1 { zero = 0, one = 1 }; |
82 | enum enum2 : unsigned long { |
83 | value = std::numeric_limits<unsigned long>::max() |
84 | }; |
85 | |
86 | int main(int, char**) |
87 | { |
88 | check_integral_types<bool, int>(); |
89 | check_integral_types<char, int>(); |
90 | check_integral_types<signed char, int>(); |
91 | check_integral_types<unsigned char, int>(); |
92 | #ifndef TEST_HAS_NO_WIDE_CHARACTERS |
93 | check_integral_types<wchar_t, decltype(((wchar_t)1) + 1)>(); |
94 | #endif |
95 | check_integral_types<char16_t, int>(); |
96 | // On some platforms, unsigned int and long are the same size. These |
97 | // platforms have a choice of making std::uint32_t an int or a long. However |
98 | // char32_t must promote to an unsigned int on these platforms [conv.prom]. |
99 | // Use the following logic to make the test work on such platforms. |
100 | // (sizeof(std::uint32_t) == sizeof(unsigned int)) ? unsigned int : std::uint32_t; |
101 | typedef std::conditional<sizeof(std::uint32_t) == sizeof(unsigned int), |
102 | unsigned int, std::uint32_t>::type char_integral; |
103 | check_integral_types<char32_t, char_integral>(); |
104 | check_integral_types<short, int>(); |
105 | check_integral_types<unsigned short, int>(); |
106 | check_integral_types<int, int>(); |
107 | check_integral_types<unsigned, unsigned>(); |
108 | check_integral_types<long, long>(); |
109 | check_integral_types<unsigned long, unsigned long>(); |
110 | check_integral_types<long long, long long>(); |
111 | check_integral_types<unsigned long long, unsigned long long>(); |
112 | #ifndef TEST_HAS_NO_INT128 |
113 | check_integral_types<__int128_t, __int128_t>(); |
114 | check_integral_types<__uint128_t, __uint128_t>(); |
115 | #endif |
116 | // TODO(ericwf): Not standard |
117 | typedef std::underlying_type<enum1>::type Enum1UT; |
118 | check_enum_types<enum1, decltype(((Enum1UT)1) + 1)>(); |
119 | typedef std::underlying_type<enum2>::type Enum2UT; |
120 | check_enum_types<enum2, decltype(((Enum2UT)1) + 1)>(); |
121 | |
122 | return 0; |
123 | } |
124 | |