1 //===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file provides useful additions to the standard type_traits library.
11 //===----------------------------------------------------------------------===//
13 // Taken from clang-1100.247.11.10.9
15 #ifndef LLVM_SUPPORT_TYPE_TRAITS_H
16 #define LLVM_SUPPORT_TYPE_TRAITS_H
18 #define HAVE_STD_IS_TRIVIALLY_COPYABLE 1
24 #define LLVM_DEFINED_HAS_FEATURE
25 #define __has_feature(x) 0
31 /// Metafunction that determines whether the given type is either an
32 /// integral type or an enumeration type, including enum classes.
34 /// Note that this accepts potentially more integral types than is_integral
35 /// because it is based on being implicitly convertible to an integral type.
36 /// Also note that enum classes aren't implicitly convertible to integral types,
37 /// the value may therefore need to be explicitly converted before being used.
38 template <typename T
> class is_integral_or_enum
{
39 using UnderlyingT
= typename
std::remove_reference
<T
>::type
;
42 static const bool value
=
43 !std::is_class
<UnderlyingT
>::value
&& // Filter conversion operators.
44 !std::is_pointer
<UnderlyingT
>::value
&&
45 !std::is_floating_point
<UnderlyingT
>::value
&&
46 (std::is_enum
<UnderlyingT
>::value
||
47 std::is_convertible
<UnderlyingT
, unsigned long long>::value
);
50 /// If T is a pointer, just return it. If it is not, return T&.
51 template<typename T
, typename Enable
= void>
52 struct add_lvalue_reference_if_not_pointer
{ using type
= T
&; };
55 struct add_lvalue_reference_if_not_pointer
<
56 T
, typename
std::enable_if
<std::is_pointer
<T
>::value
>::type
> {
60 /// If T is a pointer to X, return a pointer to const X. If it is not,
62 template<typename T
, typename Enable
= void>
63 struct add_const_past_pointer
{ using type
= const T
; };
66 struct add_const_past_pointer
<
67 T
, typename
std::enable_if
<std::is_pointer
<T
>::value
>::type
> {
68 using type
= const typename
std::remove_pointer
<T
>::type
*;
71 template <typename T
, typename Enable
= void>
72 struct const_pointer_or_const_ref
{
73 using type
= const T
&;
76 struct const_pointer_or_const_ref
<
77 T
, typename
std::enable_if
<std::is_pointer
<T
>::value
>::type
> {
78 using type
= typename add_const_past_pointer
<T
>::type
;
82 /// Internal utility to detect trivial copy construction.
83 template<typename T
> union copy_construction_triviality_helper
{
85 copy_construction_triviality_helper() = default;
86 copy_construction_triviality_helper(const copy_construction_triviality_helper
&) = default;
87 ~copy_construction_triviality_helper() = default;
89 /// Internal utility to detect trivial move construction.
90 template<typename T
> union move_construction_triviality_helper
{
92 move_construction_triviality_helper() = default;
93 move_construction_triviality_helper(move_construction_triviality_helper
&&) = default;
94 ~move_construction_triviality_helper() = default;
98 union trivial_helper
{
102 } // end namespace detail
104 /// An implementation of `std::is_trivially_copy_constructible` since we have
105 /// users with STLs that don't yet include it.
106 template <typename T
>
107 struct is_trivially_copy_constructible
108 : std::is_copy_constructible
<
109 ::objc::detail::copy_construction_triviality_helper
<T
>> {};
110 template <typename T
>
111 struct is_trivially_copy_constructible
<T
&> : std::true_type
{};
112 template <typename T
>
113 struct is_trivially_copy_constructible
<T
&&> : std::false_type
{};
115 /// An implementation of `std::is_trivially_move_constructible` since we have
116 /// users with STLs that don't yet include it.
117 template <typename T
>
118 struct is_trivially_move_constructible
119 : std::is_move_constructible
<
120 ::objc::detail::move_construction_triviality_helper
<T
>> {};
121 template <typename T
>
122 struct is_trivially_move_constructible
<T
&> : std::true_type
{};
123 template <typename T
>
124 struct is_trivially_move_constructible
<T
&&> : std::true_type
{};
127 template <typename T
>
128 struct is_copy_assignable
{
130 static auto get(F
*) -> decltype(std::declval
<F
&>() = std::declval
<const F
&>(), std::true_type
{});
131 static std::false_type
get(...);
132 static constexpr bool value
= decltype(get((T
*)nullptr))::value
;
135 template <typename T
>
136 struct is_move_assignable
{
138 static auto get(F
*) -> decltype(std::declval
<F
&>() = std::declval
<F
&&>(), std::true_type
{});
139 static std::false_type
get(...);
140 static constexpr bool value
= decltype(get((T
*)nullptr))::value
;
144 // An implementation of `std::is_trivially_copyable` since STL version
145 // is not equally supported by all compilers, especially GCC 4.9.
146 // Uniform implementation of this trait is important for ABI compatibility
147 // as it has an impact on SmallVector's ABI (among others).
148 template <typename T
>
149 class is_trivially_copyable
{
152 static constexpr bool has_trivial_copy_constructor
=
153 std::is_copy_constructible
<detail::trivial_helper
<T
>>::value
;
154 static constexpr bool has_deleted_copy_constructor
=
155 !std::is_copy_constructible
<T
>::value
;
158 static constexpr bool has_trivial_move_constructor
=
159 std::is_move_constructible
<detail::trivial_helper
<T
>>::value
;
160 static constexpr bool has_deleted_move_constructor
=
161 !std::is_move_constructible
<T
>::value
;
164 static constexpr bool has_trivial_copy_assign
=
165 is_copy_assignable
<detail::trivial_helper
<T
>>::value
;
166 static constexpr bool has_deleted_copy_assign
=
167 !is_copy_assignable
<T
>::value
;
170 static constexpr bool has_trivial_move_assign
=
171 is_move_assignable
<detail::trivial_helper
<T
>>::value
;
172 static constexpr bool has_deleted_move_assign
=
173 !is_move_assignable
<T
>::value
;
176 static constexpr bool has_trivial_destructor
=
177 std::is_destructible
<detail::trivial_helper
<T
>>::value
;
181 static constexpr bool value
=
182 has_trivial_destructor
&&
183 (has_deleted_move_assign
|| has_trivial_move_assign
) &&
184 (has_deleted_move_constructor
|| has_trivial_move_constructor
) &&
185 (has_deleted_copy_assign
|| has_trivial_copy_assign
) &&
186 (has_deleted_copy_constructor
|| has_trivial_copy_constructor
);
188 #ifdef HAVE_STD_IS_TRIVIALLY_COPYABLE
189 static_assert(value
== std::is_trivially_copyable
<T
>::value
,
190 "inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable");
193 template <typename T
>
194 class is_trivially_copyable
<T
*> : public std::true_type
{
198 } // end namespace llvm
200 #ifdef LLVM_DEFINED_HAS_FEATURE
204 #endif // LLVM_SUPPORT_TYPE_TRAITS_H