]> git.saurik.com Git - apple/objc4.git/blob - runtime/llvm-type_traits.h
objc4-781.tar.gz
[apple/objc4.git] / runtime / llvm-type_traits.h
1 //===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===//
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 // This file provides useful additions to the standard type_traits library.
10 //
11 //===----------------------------------------------------------------------===//
12
13 // Taken from clang-1100.247.11.10.9
14
15 #ifndef LLVM_SUPPORT_TYPE_TRAITS_H
16 #define LLVM_SUPPORT_TYPE_TRAITS_H
17
18 #define HAVE_STD_IS_TRIVIALLY_COPYABLE 1
19
20 #include <cstddef>
21 #include <utility>
22
23 #ifndef __has_feature
24 #define LLVM_DEFINED_HAS_FEATURE
25 #define __has_feature(x) 0
26 #endif
27
28 namespace objc {
29
30
31 /// Metafunction that determines whether the given type is either an
32 /// integral type or an enumeration type, including enum classes.
33 ///
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;
40
41 public:
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);
48 };
49
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 &; };
53
54 template <typename T>
55 struct add_lvalue_reference_if_not_pointer<
56 T, typename std::enable_if<std::is_pointer<T>::value>::type> {
57 using type = T;
58 };
59
60 /// If T is a pointer to X, return a pointer to const X. If it is not,
61 /// return const T.
62 template<typename T, typename Enable = void>
63 struct add_const_past_pointer { using type = const T; };
64
65 template <typename 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 *;
69 };
70
71 template <typename T, typename Enable = void>
72 struct const_pointer_or_const_ref {
73 using type = const T &;
74 };
75 template <typename 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;
79 };
80
81 namespace detail {
82 /// Internal utility to detect trivial copy construction.
83 template<typename T> union copy_construction_triviality_helper {
84 T t;
85 copy_construction_triviality_helper() = default;
86 copy_construction_triviality_helper(const copy_construction_triviality_helper&) = default;
87 ~copy_construction_triviality_helper() = default;
88 };
89 /// Internal utility to detect trivial move construction.
90 template<typename T> union move_construction_triviality_helper {
91 T t;
92 move_construction_triviality_helper() = default;
93 move_construction_triviality_helper(move_construction_triviality_helper&&) = default;
94 ~move_construction_triviality_helper() = default;
95 };
96
97 template<class T>
98 union trivial_helper {
99 T t;
100 };
101
102 } // end namespace detail
103
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 {};
114
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 {};
125
126
127 template <typename T>
128 struct is_copy_assignable {
129 template<class F>
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;
133 };
134
135 template <typename T>
136 struct is_move_assignable {
137 template<class F>
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;
141 };
142
143
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 {
150
151 // copy constructors
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;
156
157 // move constructors
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;
162
163 // copy assign
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;
168
169 // move assign
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;
174
175 // destructor
176 static constexpr bool has_trivial_destructor =
177 std::is_destructible<detail::trivial_helper<T>>::value;
178
179 public:
180
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);
187
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");
191 #endif
192 };
193 template <typename T>
194 class is_trivially_copyable<T*> : public std::true_type {
195 };
196
197
198 } // end namespace llvm
199
200 #ifdef LLVM_DEFINED_HAS_FEATURE
201 #undef __has_feature
202 #endif
203
204 #endif // LLVM_SUPPORT_TYPE_TRAITS_H