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// <type_traits>
10//
11// UNSUPPORTED: c++03, c++11, c++14, c++17
12//
13// __is_always_bitcastable<_From, _To>
14
15#include "test_macros.h"
16TEST_CLANG_DIAGNOSTIC_IGNORED("-Wprivate-header")
17#include <__type_traits/is_always_bitcastable.h>
18
19#include <climits>
20#include <cstdint>
21#ifndef TEST_HAS_NO_WIDE_CHARACTERS
22#include <cwchar>
23#endif
24#include "type_algorithms.h"
25
26// To test pointers to functions.
27void Func1() {}
28using FuncPtr1 = decltype(&Func1);
29int Func2() { return 0; }
30using FuncPtr2 = decltype(&Func2);
31
32template <bool Expected, class T, class U>
33constexpr void check_one() {
34 static_assert(std::__is_always_bitcastable<T, U>::value == Expected);
35}
36
37template <bool Expected, class T, class U>
38constexpr void check_with_volatile() {
39 check_one<Expected, T, U>();
40 check_one<Expected, volatile T, U>();
41 check_one<Expected, T, volatile U>();
42 check_one<Expected, volatile T, volatile U>();
43}
44
45template <bool Expected, class T, class U>
46constexpr void check_with_cv() {
47 check_with_volatile<Expected, T, U>();
48 check_with_volatile<Expected, const T, U>();
49 check_with_volatile<Expected, T, const U>();
50 check_with_volatile<Expected, const T, const U>();
51}
52
53template <bool Expected, class Types1, class Types2 = Types1>
54constexpr void check() {
55 types::for_each(Types1{}, []<class T>() {
56 types::for_each(Types2{}, []<class U>() {
57 check_with_cv<Expected, T, U>();
58 });
59 });
60}
61
62template <bool Expected, class Types1, class Types2>
63constexpr void check_both_ways() {
64 check<Expected, Types1, Types2>();
65 check<Expected, Types2, Types1>();
66}
67
68constexpr void test() {
69 // Arithmetic types.
70 {
71 // Bit-castable arithmetic types.
72
73 // 8-bit types.
74 using integral_8 = types::type_list<char8_t, std::int8_t, std::uint8_t>;
75 using chars = types::type_list<char, unsigned char, signed char>;
76#if CHAR_BIT == 8
77 check<true, types::concatenate_t<integral_8, chars>>();
78#else
79 check<true, integral_8>();
80 check<true, chars>();
81#endif
82
83 // 16-bit types.
84 using integral_16 = types::type_list<char16_t, std::int16_t, std::uint16_t>;
85#if !defined(TEST_HAS_NO_WIDE_CHARACTERS) && __WCHAR_WIDTH__ == 16
86 check<true, types::concatenate_t<integral_16, types::type_list<wchar_t>>>();
87#else
88 check<true, integral_16>();
89#endif
90
91 // 32-bit types.
92 using integral_32 = types::type_list<char32_t, std::int32_t, std::uint32_t>;
93#if !defined(TEST_HAS_NO_WIDE_CHARACTERS) && __WCHAR_WIDTH__ == 32
94 check<true, types::concatenate_t<integral_32, types::type_list<wchar_t>>>();
95#else
96 check<true, integral_32>();
97#endif
98
99 // 64-bit types.
100 using integral_64 = types::type_list<std::int64_t, std::uint64_t>;
101 check<true, integral_64>();
102
103 // 128-bit types.
104#ifndef TEST_HAS_NO_INT128
105 check<true, types::type_list<__int128_t, __uint128_t>>();
106#endif
107
108 // Bool.
109 check<true, types::type_list<bool>, types::concatenate_t<types::type_list<bool>, integral_8>>();
110
111 // Non-bit-castable arithmetic types.
112
113 // Floating-point.
114 check_both_ways<false, types::floating_point_types, types::integral_types>();
115 check_both_ways<false, types::type_list<float>, types::type_list<double, long double>>();
116 check_both_ways<false, types::type_list<double>, types::type_list<float, long double>>();
117 check_both_ways<false, types::type_list<long double>, types::type_list<float, double>>();
118
119 // Different sizes.
120 check_both_ways<false, integral_8, types::concatenate_t<integral_16, integral_32, integral_64>>();
121 check_both_ways<false, integral_16, types::concatenate_t<integral_8, integral_32, integral_64>>();
122 check_both_ways<false, integral_32, types::concatenate_t<integral_8, integral_16, integral_64>>();
123 check_both_ways<false, integral_64, types::concatenate_t<integral_8, integral_16, integral_32>>();
124
125 // Different representations -- can convert from bool to other integral types, but not vice versa.
126 check<true, types::type_list<bool>, integral_8>();
127 using larger_than_bool = types::concatenate_t<
128 integral_16,
129 integral_32,
130 integral_64,
131 types::floating_point_types>;
132 check<false, types::type_list<bool>, larger_than_bool>();
133 check<false, types::concatenate_t<integral_8, larger_than_bool>, types::type_list<bool>>();
134
135 // Different representations -- floating point vs. integral.
136 check_both_ways<false, types::floating_point_types, types::integral_types>();
137 }
138
139 // Enumerations.
140 {
141 enum E1 { Value1 };
142 enum E2 { Value2 };
143 check<true, types::type_list<E1>>();
144 check_both_ways<false, types::type_list<E1>, types::type_list<E2>>();
145
146 enum class ScopedE1 { Value1 };
147 enum class ScopedE2 { Value1 };
148 check<true, types::type_list<ScopedE1>>();
149 check_both_ways<false, types::type_list<ScopedE1>, types::type_list<ScopedE2>>();
150 }
151
152 // Pointers.
153 {
154 check<true, types::type_list<int*>>();
155 check_both_ways<false, types::type_list<int*>, types::type_list<const int*, long*, void*>>();
156
157 check<true, types::type_list<FuncPtr1>>();
158 check_both_ways<false, types::type_list<FuncPtr1>, types::type_list<FuncPtr2>>();
159 }
160
161 // Pointers to members.
162 {
163 struct S {
164 int mem_obj1 = 0;
165 long mem_obj2 = 0;
166 void MemFunc1() {}
167 int MemFunc2() { return 0; }
168 };
169 using MemObjPtr1 = decltype(&S::mem_obj1);
170 using MemObjPtr2 = decltype(&S::mem_obj2);
171 using MemFuncPtr1 = decltype(&S::MemFunc1);
172 using MemFuncPtr2 = decltype(&S::MemFunc2);
173
174 check<true, types::type_list<MemObjPtr1>>();
175 check<true, types::type_list<MemFuncPtr1>>();
176 check_both_ways<false, types::type_list<MemObjPtr1>, types::type_list<MemObjPtr2>>();
177 check_both_ways<false, types::type_list<MemFuncPtr1>, types::type_list<MemFuncPtr2>>();
178 }
179
180 // Trivial classes.
181 {
182 struct S1 {};
183 check<true, types::type_list<S1>>();
184
185 struct S2 {};
186 check_both_ways<false, types::type_list<S1>, types::type_list<S2>>();
187
188 // Having a `volatile` member doesn't prevent a class type from being considered trivially copyable. This is
189 // unfortunate behavior but it is consistent with the Standard.
190 struct VolatileMembersS {
191 volatile int x;
192 };
193 check<true, types::type_list<VolatileMembersS>>();
194 }
195
196 // Trivial unions.
197 {
198 union U1 {};
199 check<true, types::type_list<U1>>();
200
201 union U2 {};
202 check_both_ways<false, types::type_list<U1>, types::type_list<U2>>();
203
204 union VolatileMembersU {
205 volatile int x;
206 };
207 check<true, types::type_list<VolatileMembersU>>();
208 }
209
210 // References are not objects, and thus are not bit-castable.
211 {
212 check_both_ways<false, types::type_list<int&>, types::type_list<int&>>();
213 }
214
215 // Arrays.
216 {
217 check<true, types::type_list<int[8]>>();
218 }
219}
220

source code of libcxx/test/libcxx/type_traits/is_always_bitcastable.compile.pass.cpp