llvm-type_traits.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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. // Taken from clang-1100.247.11.10.9
  13. #ifndef LLVM_SUPPORT_TYPE_TRAITS_H
  14. #define LLVM_SUPPORT_TYPE_TRAITS_H
  15. #define HAVE_STD_IS_TRIVIALLY_COPYABLE 1
  16. #include <cstddef>
  17. #include <utility>
  18. #ifndef __has_feature
  19. #define LLVM_DEFINED_HAS_FEATURE
  20. #define __has_feature(x) 0
  21. #endif
  22. namespace objc {
  23. /// Metafunction that determines whether the given type is either an
  24. /// integral type or an enumeration type, including enum classes.
  25. ///
  26. /// Note that this accepts potentially more integral types than is_integral
  27. /// because it is based on being implicitly convertible to an integral type.
  28. /// Also note that enum classes aren't implicitly convertible to integral types,
  29. /// the value may therefore need to be explicitly converted before being used.
  30. template <typename T> class is_integral_or_enum {
  31. using UnderlyingT = typename std::remove_reference<T>::type;
  32. public:
  33. static const bool value =
  34. !std::is_class<UnderlyingT>::value && // Filter conversion operators.
  35. !std::is_pointer<UnderlyingT>::value &&
  36. !std::is_floating_point<UnderlyingT>::value &&
  37. (std::is_enum<UnderlyingT>::value ||
  38. std::is_convertible<UnderlyingT, unsigned long long>::value);
  39. };
  40. /// If T is a pointer, just return it. If it is not, return T&.
  41. template<typename T, typename Enable = void>
  42. struct add_lvalue_reference_if_not_pointer { using type = T &; };
  43. template <typename T>
  44. struct add_lvalue_reference_if_not_pointer<
  45. T, typename std::enable_if<std::is_pointer<T>::value>::type> {
  46. using type = T;
  47. };
  48. /// If T is a pointer to X, return a pointer to const X. If it is not,
  49. /// return const T.
  50. template<typename T, typename Enable = void>
  51. struct add_const_past_pointer { using type = const T; };
  52. template <typename T>
  53. struct add_const_past_pointer<
  54. T, typename std::enable_if<std::is_pointer<T>::value>::type> {
  55. using type = const typename std::remove_pointer<T>::type *;
  56. };
  57. template <typename T, typename Enable = void>
  58. struct const_pointer_or_const_ref {
  59. using type = const T &;
  60. };
  61. template <typename T>
  62. struct const_pointer_or_const_ref<
  63. T, typename std::enable_if<std::is_pointer<T>::value>::type> {
  64. using type = typename add_const_past_pointer<T>::type;
  65. };
  66. namespace detail {
  67. /// Internal utility to detect trivial copy construction.
  68. template<typename T> union copy_construction_triviality_helper {
  69. T t;
  70. copy_construction_triviality_helper() = default;
  71. copy_construction_triviality_helper(const copy_construction_triviality_helper&) = default;
  72. ~copy_construction_triviality_helper() = default;
  73. };
  74. /// Internal utility to detect trivial move construction.
  75. template<typename T> union move_construction_triviality_helper {
  76. T t;
  77. move_construction_triviality_helper() = default;
  78. move_construction_triviality_helper(move_construction_triviality_helper&&) = default;
  79. ~move_construction_triviality_helper() = default;
  80. };
  81. template<class T>
  82. union trivial_helper {
  83. T t;
  84. };
  85. } // end namespace detail
  86. /// An implementation of `std::is_trivially_copy_constructible` since we have
  87. /// users with STLs that don't yet include it.
  88. template <typename T>
  89. struct is_trivially_copy_constructible
  90. : std::is_copy_constructible<
  91. ::objc::detail::copy_construction_triviality_helper<T>> {};
  92. template <typename T>
  93. struct is_trivially_copy_constructible<T &> : std::true_type {};
  94. template <typename T>
  95. struct is_trivially_copy_constructible<T &&> : std::false_type {};
  96. /// An implementation of `std::is_trivially_move_constructible` since we have
  97. /// users with STLs that don't yet include it.
  98. template <typename T>
  99. struct is_trivially_move_constructible
  100. : std::is_move_constructible<
  101. ::objc::detail::move_construction_triviality_helper<T>> {};
  102. template <typename T>
  103. struct is_trivially_move_constructible<T &> : std::true_type {};
  104. template <typename T>
  105. struct is_trivially_move_constructible<T &&> : std::true_type {};
  106. template <typename T>
  107. struct is_copy_assignable {
  108. template<class F>
  109. static auto get(F*) -> decltype(std::declval<F &>() = std::declval<const F &>(), std::true_type{});
  110. static std::false_type get(...);
  111. static constexpr bool value = decltype(get((T*)nullptr))::value;
  112. };
  113. template <typename T>
  114. struct is_move_assignable {
  115. template<class F>
  116. static auto get(F*) -> decltype(std::declval<F &>() = std::declval<F &&>(), std::true_type{});
  117. static std::false_type get(...);
  118. static constexpr bool value = decltype(get((T*)nullptr))::value;
  119. };
  120. // An implementation of `std::is_trivially_copyable` since STL version
  121. // is not equally supported by all compilers, especially GCC 4.9.
  122. // Uniform implementation of this trait is important for ABI compatibility
  123. // as it has an impact on SmallVector's ABI (among others).
  124. template <typename T>
  125. class is_trivially_copyable {
  126. // copy constructors
  127. static constexpr bool has_trivial_copy_constructor =
  128. std::is_copy_constructible<detail::trivial_helper<T>>::value;
  129. static constexpr bool has_deleted_copy_constructor =
  130. !std::is_copy_constructible<T>::value;
  131. // move constructors
  132. static constexpr bool has_trivial_move_constructor =
  133. std::is_move_constructible<detail::trivial_helper<T>>::value;
  134. static constexpr bool has_deleted_move_constructor =
  135. !std::is_move_constructible<T>::value;
  136. // copy assign
  137. static constexpr bool has_trivial_copy_assign =
  138. is_copy_assignable<detail::trivial_helper<T>>::value;
  139. static constexpr bool has_deleted_copy_assign =
  140. !is_copy_assignable<T>::value;
  141. // move assign
  142. static constexpr bool has_trivial_move_assign =
  143. is_move_assignable<detail::trivial_helper<T>>::value;
  144. static constexpr bool has_deleted_move_assign =
  145. !is_move_assignable<T>::value;
  146. // destructor
  147. static constexpr bool has_trivial_destructor =
  148. std::is_destructible<detail::trivial_helper<T>>::value;
  149. public:
  150. static constexpr bool value =
  151. has_trivial_destructor &&
  152. (has_deleted_move_assign || has_trivial_move_assign) &&
  153. (has_deleted_move_constructor || has_trivial_move_constructor) &&
  154. (has_deleted_copy_assign || has_trivial_copy_assign) &&
  155. (has_deleted_copy_constructor || has_trivial_copy_constructor);
  156. #ifdef HAVE_STD_IS_TRIVIALLY_COPYABLE
  157. static_assert(value == std::is_trivially_copyable<T>::value,
  158. "inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable");
  159. #endif
  160. };
  161. template <typename T>
  162. class is_trivially_copyable<T*> : public std::true_type {
  163. };
  164. } // end namespace llvm
  165. #ifdef LLVM_DEFINED_HAS_FEATURE
  166. #undef __has_feature
  167. #endif
  168. #endif // LLVM_SUPPORT_TYPE_TRAITS_H