1 | //===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===// |
---|---|

2 | // |

3 | // The LLVM Compiler Infrastructure |

4 | // |

5 | // This file is distributed under the University of Illinois Open Source |

6 | // License. See LICENSE.TXT for details. |

7 | // |

8 | //===----------------------------------------------------------------------===// |

9 | // |

10 | // This file provides useful additions to the standard type_traits library. |

11 | // |

12 | //===----------------------------------------------------------------------===// |

13 | |

14 | #ifndef LLVM_SUPPORT_TYPE_TRAITS_H |

15 | #define LLVM_SUPPORT_TYPE_TRAITS_H |

16 | |

17 | #include "llvm/Support/Compiler.h" |

18 | #include <type_traits> |

19 | #include <utility> |

20 | |

21 | #ifndef __has_feature |

22 | #define LLVM_DEFINED_HAS_FEATURE |

23 | #define __has_feature(x) 0 |

24 | #endif |

25 | |

26 | namespace llvm { |

27 | |

28 | /// isPodLike - This is a type trait that is used to determine whether a given |

29 | /// type can be copied around with memcpy instead of running ctors etc. |

30 | template <typename T> |

31 | struct isPodLike { |

32 | // std::is_trivially_copyable is available in libc++ with clang, libstdc++ |

33 | // that comes with GCC 5. |

34 | #if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \ |

35 | (defined(__GNUC__) && __GNUC__ >= 5) |

36 | // If the compiler supports the is_trivially_copyable trait use it, as it |

37 | // matches the definition of isPodLike closely. |

38 | static const bool value = std::is_trivially_copyable<T>::value; |

39 | #elif __has_feature(is_trivially_copyable) |

40 | // Use the internal name if the compiler supports is_trivially_copyable but we |

41 | // don't know if the standard library does. This is the case for clang in |

42 | // conjunction with libstdc++ from GCC 4.x. |

43 | static const bool value = __is_trivially_copyable(T); |

44 | #else |

45 | // If we don't know anything else, we can (at least) assume that all non-class |

46 | // types are PODs. |

47 | static const bool value = !std::is_class<T>::value; |

48 | #endif |

49 | }; |

50 | |

51 | // std::pair's are pod-like if their elements are. |

52 | template<typename T, typename U> |

53 | struct isPodLike<std::pair<T, U>> { |

54 | static const bool value = isPodLike<T>::value && isPodLike<U>::value; |

55 | }; |

56 | |

57 | /// Metafunction that determines whether the given type is either an |

58 | /// integral type or an enumeration type, including enum classes. |

59 | /// |

60 | /// Note that this accepts potentially more integral types than is_integral |

61 | /// because it is based on being implicitly convertible to an integral type. |

62 | /// Also note that enum classes aren't implicitly convertible to integral types, |

63 | /// the value may therefore need to be explicitly converted before being used. |

64 | template <typename T> class is_integral_or_enum { |

65 | using UnderlyingT = typename std::remove_reference<T>::type; |

66 | |

67 | public: |

68 | static const bool value = |

69 | !std::is_class<UnderlyingT>::value && // Filter conversion operators. |

70 | !std::is_pointer<UnderlyingT>::value && |

71 | !std::is_floating_point<UnderlyingT>::value && |

72 | (std::is_enum<UnderlyingT>::value || |

73 | std::is_convertible<UnderlyingT, unsigned long long>::value); |

74 | }; |

75 | |

76 | /// If T is a pointer, just return it. If it is not, return T&. |

77 | template<typename T, typename Enable = void> |

78 | struct add_lvalue_reference_if_not_pointer { using type = T &; }; |

79 | |

80 | template <typename T> |

81 | struct add_lvalue_reference_if_not_pointer< |

82 | T, typename std::enable_if<std::is_pointer<T>::value>::type> { |

83 | using type = T; |

84 | }; |

85 | |

86 | /// If T is a pointer to X, return a pointer to const X. If it is not, |

87 | /// return const T. |

88 | template<typename T, typename Enable = void> |

89 | struct add_const_past_pointer { using type = const T; }; |

90 | |

91 | template <typename T> |

92 | struct add_const_past_pointer< |

93 | T, typename std::enable_if<std::is_pointer<T>::value>::type> { |

94 | using type = const typename std::remove_pointer<T>::type *; |

95 | }; |

96 | |

97 | template <typename T, typename Enable = void> |

98 | struct const_pointer_or_const_ref { |

99 | using type = const T &; |

100 | }; |

101 | template <typename T> |

102 | struct const_pointer_or_const_ref< |

103 | T, typename std::enable_if<std::is_pointer<T>::value>::type> { |

104 | using type = typename add_const_past_pointer<T>::type; |

105 | }; |

106 | |

107 | namespace detail { |

108 | /// Internal utility to detect trivial copy construction. |

109 | template<typename T> union copy_construction_triviality_helper { |

110 | T t; |

111 | copy_construction_triviality_helper() = default; |

112 | copy_construction_triviality_helper(const copy_construction_triviality_helper&) = default; |

113 | ~copy_construction_triviality_helper() = default; |

114 | }; |

115 | /// Internal utility to detect trivial move construction. |

116 | template<typename T> union move_construction_triviality_helper { |

117 | T t; |

118 | move_construction_triviality_helper() = default; |

119 | move_construction_triviality_helper(move_construction_triviality_helper&&) = default; |

120 | ~move_construction_triviality_helper() = default; |

121 | }; |

122 | } // end namespace detail |

123 | |

124 | /// An implementation of `std::is_trivially_copy_constructible` since we have |

125 | /// users with STLs that don't yet include it. |

126 | template <typename T> |

127 | struct is_trivially_copy_constructible |

128 | : std::is_copy_constructible< |

129 | ::llvm::detail::copy_construction_triviality_helper<T>> {}; |

130 | template <typename T> |

131 | struct is_trivially_copy_constructible<T &> : std::true_type {}; |

132 | template <typename T> |

133 | struct is_trivially_copy_constructible<T &&> : std::false_type {}; |

134 | |

135 | /// An implementation of `std::is_trivially_move_constructible` since we have |

136 | /// users with STLs that don't yet include it. |

137 | template <typename T> |

138 | struct is_trivially_move_constructible |

139 | : std::is_move_constructible< |

140 | ::llvm::detail::move_construction_triviality_helper<T>> {}; |

141 | template <typename T> |

142 | struct is_trivially_move_constructible<T &> : std::true_type {}; |

143 | template <typename T> |

144 | struct is_trivially_move_constructible<T &&> : std::true_type {}; |

145 | |

146 | } // end namespace llvm |

147 | |

148 | // If the compiler supports detecting whether a class is final, define |

149 | // an LLVM_IS_FINAL macro. If it cannot be defined properly, this |

150 | // macro will be left undefined. |

151 | #if __cplusplus >= 201402L || defined(_MSC_VER) |

152 | #define LLVM_IS_FINAL(Ty) std::is_final<Ty>() |

153 | #elif __has_feature(is_final) || LLVM_GNUC_PREREQ(4, 7, 0) |

154 | #define LLVM_IS_FINAL(Ty) __is_final(Ty) |

155 | #endif |

156 | |

157 | #ifdef LLVM_DEFINED_HAS_FEATURE |

158 | #undef __has_feature |

159 | #endif |

160 | |

161 | #endif // LLVM_SUPPORT_TYPE_TRAITS_H |

162 |