]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/include/llvm/Support/type_traits.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / include / llvm / Support / 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 #ifndef LLVM_SUPPORT_TYPE_TRAITS_H
14 #define LLVM_SUPPORT_TYPE_TRAITS_H
15
16 #include "llvm/Support/Compiler.h"
17 #include <type_traits>
18 #include <utility>
19
20 #ifndef __has_feature
21 #define LLVM_DEFINED_HAS_FEATURE
22 #define __has_feature(x) 0
23 #endif
24
25 namespace llvm {
26
27
28 /// Metafunction that determines whether the given type is either an
29 /// integral type or an enumeration type, including enum classes.
30 ///
31 /// Note that this accepts potentially more integral types than is_integral
32 /// because it is based on being implicitly convertible to an integral type.
33 /// Also note that enum classes aren't implicitly convertible to integral types,
34 /// the value may therefore need to be explicitly converted before being used.
35 template <typename T> class is_integral_or_enum {
36   using UnderlyingT = typename std::remove_reference<T>::type;
37
38 public:
39   static const bool value =
40       !std::is_class<UnderlyingT>::value && // Filter conversion operators.
41       !std::is_pointer<UnderlyingT>::value &&
42       !std::is_floating_point<UnderlyingT>::value &&
43       (std::is_enum<UnderlyingT>::value ||
44        std::is_convertible<UnderlyingT, unsigned long long>::value);
45 };
46
47 /// If T is a pointer, just return it. If it is not, return T&.
48 template<typename T, typename Enable = void>
49 struct add_lvalue_reference_if_not_pointer { using type = T &; };
50
51 template <typename T>
52 struct add_lvalue_reference_if_not_pointer<
53     T, typename std::enable_if<std::is_pointer<T>::value>::type> {
54   using type = T;
55 };
56
57 /// If T is a pointer to X, return a pointer to const X. If it is not,
58 /// return const T.
59 template<typename T, typename Enable = void>
60 struct add_const_past_pointer { using type = const T; };
61
62 template <typename T>
63 struct add_const_past_pointer<
64     T, typename std::enable_if<std::is_pointer<T>::value>::type> {
65   using type = const typename std::remove_pointer<T>::type *;
66 };
67
68 template <typename T, typename Enable = void>
69 struct const_pointer_or_const_ref {
70   using type = const T &;
71 };
72 template <typename T>
73 struct const_pointer_or_const_ref<
74     T, typename std::enable_if<std::is_pointer<T>::value>::type> {
75   using type = typename add_const_past_pointer<T>::type;
76 };
77
78 namespace detail {
79 /// Internal utility to detect trivial copy construction.
80 template<typename T> union copy_construction_triviality_helper {
81     T t;
82     copy_construction_triviality_helper() = default;
83     copy_construction_triviality_helper(const copy_construction_triviality_helper&) = default;
84     ~copy_construction_triviality_helper() = default;
85 };
86 /// Internal utility to detect trivial move construction.
87 template<typename T> union move_construction_triviality_helper {
88     T t;
89     move_construction_triviality_helper() = default;
90     move_construction_triviality_helper(move_construction_triviality_helper&&) = default;
91     ~move_construction_triviality_helper() = default;
92 };
93
94 template<class T>
95 union trivial_helper {
96     T t;
97 };
98
99 } // end namespace detail
100
101 /// An implementation of `std::is_trivially_copy_constructible` since we have
102 /// users with STLs that don't yet include it.
103 template <typename T>
104 struct is_trivially_copy_constructible
105     : std::is_copy_constructible<
106           ::llvm::detail::copy_construction_triviality_helper<T>> {};
107 template <typename T>
108 struct is_trivially_copy_constructible<T &> : std::true_type {};
109 template <typename T>
110 struct is_trivially_copy_constructible<T &&> : std::false_type {};
111
112 /// An implementation of `std::is_trivially_move_constructible` since we have
113 /// users with STLs that don't yet include it.
114 template <typename T>
115 struct is_trivially_move_constructible
116     : std::is_move_constructible<
117           ::llvm::detail::move_construction_triviality_helper<T>> {};
118 template <typename T>
119 struct is_trivially_move_constructible<T &> : std::true_type {};
120 template <typename T>
121 struct is_trivially_move_constructible<T &&> : std::true_type {};
122
123
124 template <typename T>
125 struct is_copy_assignable {
126   template<class F>
127     static auto get(F*) -> decltype(std::declval<F &>() = std::declval<const F &>(), std::true_type{});
128     static std::false_type get(...);
129     static constexpr bool value = decltype(get((T*)nullptr))::value;
130 };
131
132 template <typename T>
133 struct is_move_assignable {
134   template<class F>
135     static auto get(F*) -> decltype(std::declval<F &>() = std::declval<F &&>(), std::true_type{});
136     static std::false_type get(...);
137     static constexpr bool value = decltype(get((T*)nullptr))::value;
138 };
139
140
141 // An implementation of `std::is_trivially_copyable` since STL version
142 // is not equally supported by all compilers, especially GCC 4.9.
143 // Uniform implementation of this trait is important for ABI compatibility
144 // as it has an impact on SmallVector's ABI (among others).
145 template <typename T>
146 class is_trivially_copyable {
147
148   // copy constructors
149   static constexpr bool has_trivial_copy_constructor =
150       std::is_copy_constructible<detail::trivial_helper<T>>::value;
151   static constexpr bool has_deleted_copy_constructor =
152       !std::is_copy_constructible<T>::value;
153
154   // move constructors
155   static constexpr bool has_trivial_move_constructor =
156       std::is_move_constructible<detail::trivial_helper<T>>::value;
157   static constexpr bool has_deleted_move_constructor =
158       !std::is_move_constructible<T>::value;
159
160   // copy assign
161   static constexpr bool has_trivial_copy_assign =
162       is_copy_assignable<detail::trivial_helper<T>>::value;
163   static constexpr bool has_deleted_copy_assign =
164       !is_copy_assignable<T>::value;
165
166   // move assign
167   static constexpr bool has_trivial_move_assign =
168       is_move_assignable<detail::trivial_helper<T>>::value;
169   static constexpr bool has_deleted_move_assign =
170       !is_move_assignable<T>::value;
171
172   // destructor
173   static constexpr bool has_trivial_destructor =
174       std::is_destructible<detail::trivial_helper<T>>::value;
175
176   public:
177
178   static constexpr bool value =
179       has_trivial_destructor &&
180       (has_deleted_move_assign || has_trivial_move_assign) &&
181       (has_deleted_move_constructor || has_trivial_move_constructor) &&
182       (has_deleted_copy_assign || has_trivial_copy_assign) &&
183       (has_deleted_copy_constructor || has_trivial_copy_constructor);
184
185 #ifdef HAVE_STD_IS_TRIVIALLY_COPYABLE
186   static_assert(value == std::is_trivially_copyable<T>::value,
187                 "inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable");
188 #endif
189 };
190 template <typename T>
191 class is_trivially_copyable<T*> : public std::true_type {
192 };
193
194
195 } // end namespace llvm
196
197 // If the compiler supports detecting whether a class is final, define
198 // an LLVM_IS_FINAL macro. If it cannot be defined properly, this
199 // macro will be left undefined.
200 #if __cplusplus >= 201402L || defined(_MSC_VER)
201 #define LLVM_IS_FINAL(Ty) std::is_final<Ty>()
202 #elif __has_feature(is_final) || LLVM_GNUC_PREREQ(4, 7, 0)
203 #define LLVM_IS_FINAL(Ty) __is_final(Ty)
204 #endif
205
206 #ifdef LLVM_DEFINED_HAS_FEATURE
207 #undef __has_feature
208 #endif
209
210 #endif // LLVM_SUPPORT_TYPE_TRAITS_H