diff options
-rw-r--r-- | llvm/cmake/config-ix.cmake | 9 | ||||
-rw-r--r-- | llvm/include/llvm/ADT/PointerIntPair.h | 14 | ||||
-rw-r--r-- | llvm/include/llvm/Config/config.h.cmake | 3 | ||||
-rw-r--r-- | llvm/include/llvm/Support/type_traits.h | 35 |
4 files changed, 55 insertions, 6 deletions
diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake index 30ee2b9cbb6..9e9e28f0673 100644 --- a/llvm/cmake/config-ix.cmake +++ b/llvm/cmake/config-ix.cmake @@ -325,6 +325,15 @@ else() unset(HAVE_FFI_CALL CACHE) endif( LLVM_ENABLE_FFI ) +# Whether we can use std::is_trivially_copyable to verify llvm::is_trivially_copyable. +CHECK_CXX_SOURCE_COMPILES(" +#include <type_traits> +struct T { int val; }; +static_assert(std::is_trivially_copyable<T>::value, \"ok\"); +int main() { return 0;} +" HAVE_STD_IS_TRIVIALLY_COPYABLE) + + # Define LLVM_HAS_ATOMICS if gcc or MSVC atomic builtins are supported. include(CheckAtomic) diff --git a/llvm/include/llvm/ADT/PointerIntPair.h b/llvm/include/llvm/ADT/PointerIntPair.h index b132de81987..24a2bb67a36 100644 --- a/llvm/include/llvm/ADT/PointerIntPair.h +++ b/llvm/include/llvm/ADT/PointerIntPair.h @@ -14,6 +14,7 @@ #define LLVM_ADT_POINTERINTPAIR_H #include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/type_traits.h" #include <cassert> #include <cstdint> #include <limits> @@ -125,6 +126,19 @@ public: } }; +// Specialize is_trivially_copyable to avoid limitation of llvm::is_trivially_copyable +// when compiled with gcc 4.9. +template <typename PointerTy, unsigned IntBits, typename IntType, + typename PtrTraits, + typename Info> +struct is_trivially_copyable<PointerIntPair<PointerTy, IntBits, IntType, PtrTraits, Info>> : std::true_type { +#ifdef HAVE_STD_IS_TRIVIALLY_COPYABLE + static_assert(std::is_trivially_copyable<PointerIntPair<PointerTy, IntBits, IntType, PtrTraits, Info>>::value, + "inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable"); +#endif +}; + + template <typename PointerT, unsigned IntBits, typename PtrTraits> struct PointerIntPairInfo { static_assert(PtrTraits::NumLowBitsAvailable < diff --git a/llvm/include/llvm/Config/config.h.cmake b/llvm/include/llvm/Config/config.h.cmake index 03bbd74d6d3..a66d0fa070a 100644 --- a/llvm/include/llvm/Config/config.h.cmake +++ b/llvm/include/llvm/Config/config.h.cmake @@ -338,6 +338,9 @@ /* Define as the return type of signal handlers (`int' or `void'). */ #cmakedefine RETSIGTYPE ${RETSIGTYPE} +/* Define if std::is_trivially_copyable is supported */ +#cmakedefine HAVE_STD_IS_TRIVIALLY_COPYABLE ${HAVE_STD_IS_TRIVIALLY_COPYABLE} + /* Define to a function implementing stricmp */ #cmakedefine stricmp ${stricmp} diff --git a/llvm/include/llvm/Support/type_traits.h b/llvm/include/llvm/Support/type_traits.h index b8cf12d03d2..1ceeedd7856 100644 --- a/llvm/include/llvm/Support/type_traits.h +++ b/llvm/include/llvm/Support/type_traits.h @@ -95,6 +95,7 @@ template<class T> union trivial_helper { T t; }; + } // end namespace detail /// An implementation of `std::is_trivially_copy_constructible` since we have @@ -119,6 +120,24 @@ struct is_trivially_move_constructible<T &> : std::true_type {}; template <typename T> struct is_trivially_move_constructible<T &&> : std::true_type {}; + +template <typename T> +struct is_copy_assignable { + template<class F> + static auto get(F*) -> decltype(std::declval<T &>() = std::declval<const T &>(), std::true_type{}); + static std::false_type get(...); + static constexpr bool value = decltype(get((T*)nullptr))::value; +}; + +template <typename T> +struct is_move_assignable { + template<class F> + static auto get(F*) -> decltype(std::declval<T &>() = std::declval<T &&>(), std::true_type{}); + static std::false_type get(...); + static constexpr bool value = decltype(get((T*)nullptr))::value; +}; + + // An implementation of `std::is_trivially_copyable` since STL version // is not equally supported by all compilers, especially GCC 4.9. // Uniform implementation of this trait is important for ABI compatibility @@ -140,15 +159,15 @@ class is_trivially_copyable { // copy assign static constexpr bool has_trivial_copy_assign = - std::is_copy_assignable<detail::trivial_helper<T>>::value; + is_copy_assignable<detail::trivial_helper<T>>::value; static constexpr bool has_deleted_copy_assign = - !std::is_copy_assignable<T>::value; + !is_copy_assignable<T>::value; // move assign static constexpr bool has_trivial_move_assign = - std::is_move_assignable<detail::trivial_helper<T>>::value; + is_move_assignable<detail::trivial_helper<T>>::value; static constexpr bool has_deleted_move_assign = - !std::is_move_assignable<T>::value; + !is_move_assignable<T>::value; // destructor static constexpr bool has_trivial_destructor = @@ -163,10 +182,14 @@ class is_trivially_copyable { (has_deleted_copy_assign || has_trivial_copy_assign) && (has_deleted_copy_constructor || has_trivial_copy_constructor); -#if (__has_feature(is_trivially_copyable) || (defined(__GNUC__) && __GNUC__ >= 5)) - static_assert(value == std::is_trivially_copyable<T>::value, "inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable"); +#ifdef HAVE_STD_IS_TRIVIALLY_COPYABLE + static_assert(value == std::is_trivially_copyable<T>::value, + "inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable"); #endif }; +template <typename T> +class is_trivially_copyable<T*> : public std::true_type { +}; } // end namespace llvm |