diff options
-rw-r--r-- | llvm/include/llvm/ADT/FunctionExtras.h | 6 | ||||
-rw-r--r-- | llvm/include/llvm/Support/type_traits.h | 39 | ||||
-rw-r--r-- | llvm/unittests/Support/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/unittests/Support/TypeTraitsTest.cpp | 77 |
4 files changed, 120 insertions, 3 deletions
diff --git a/llvm/include/llvm/ADT/FunctionExtras.h b/llvm/include/llvm/ADT/FunctionExtras.h index 00ced71cb27..e3de22d65e3 100644 --- a/llvm/include/llvm/ADT/FunctionExtras.h +++ b/llvm/include/llvm/ADT/FunctionExtras.h @@ -35,8 +35,8 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/type_traits.h" #include <memory> -#include <type_traits> namespace llvm { @@ -58,8 +58,8 @@ class unique_function<ReturnT(ParamTs...)> { template <typename T> using AdjustedParamT = typename std::conditional< !std::is_reference<T>::value && - std::is_trivially_copy_constructible<T>::value && - std::is_trivially_move_constructible<T>::value && + llvm::is_trivially_copy_constructible<T>::value && + llvm::is_trivially_move_constructible<T>::value && sizeof(T) <= (2 * sizeof(void *)), T, T &>::type; diff --git a/llvm/include/llvm/Support/type_traits.h b/llvm/include/llvm/Support/type_traits.h index 534a0654060..55d84f138f0 100644 --- a/llvm/include/llvm/Support/type_traits.h +++ b/llvm/include/llvm/Support/type_traits.h @@ -104,6 +104,45 @@ struct const_pointer_or_const_ref< using type = typename add_const_past_pointer<T>::type; }; +namespace detail { +/// Internal utility to detect trivial copy construction. +template<typename T> union copy_construction_triviality_helper { + T t; + copy_construction_triviality_helper() = default; + copy_construction_triviality_helper(const copy_construction_triviality_helper&) = default; + ~copy_construction_triviality_helper() = default; +}; +/// Internal utility to detect trivial move construction. +template<typename T> union move_construction_triviality_helper { + T t; + move_construction_triviality_helper() = default; + move_construction_triviality_helper(move_construction_triviality_helper&&) = default; + ~move_construction_triviality_helper() = default; +}; +} // end namespace detail + +/// An implementation of `std::is_trivially_copy_constructible` since we have +/// users with STLs that don't yet include it. +template <typename T> +struct is_trivially_copy_constructible + : std::is_copy_constructible< + ::llvm::detail::copy_construction_triviality_helper<T>> {}; +template <typename T> +struct is_trivially_copy_constructible<T &> : std::true_type {}; +template <typename T> +struct is_trivially_copy_constructible<T &&> : std::false_type {}; + +/// An implementation of `std::is_trivially_move_constructible` since we have +/// users with STLs that don't yet include it. +template <typename T> +struct is_trivially_move_constructible + : std::is_move_constructible< + ::llvm::detail::move_construction_triviality_helper<T>> {}; +template <typename T> +struct is_trivially_move_constructible<T &> : std::true_type {}; +template <typename T> +struct is_trivially_move_constructible<T &&> : std::true_type {}; + } // end namespace llvm // If the compiler supports detecting whether a class is final, define diff --git a/llvm/unittests/Support/CMakeLists.txt b/llvm/unittests/Support/CMakeLists.txt index 655ca7fb9b4..852180c5cf9 100644 --- a/llvm/unittests/Support/CMakeLists.txt +++ b/llvm/unittests/Support/CMakeLists.txt @@ -59,6 +59,7 @@ add_llvm_unittest(SupportTests Threading.cpp TimerTest.cpp TypeNameTest.cpp + TypeTraitsTest.cpp TrailingObjectsTest.cpp TrigramIndexTest.cpp UnicodeTest.cpp diff --git a/llvm/unittests/Support/TypeTraitsTest.cpp b/llvm/unittests/Support/TypeTraitsTest.cpp new file mode 100644 index 00000000000..06ff9cc7b28 --- /dev/null +++ b/llvm/unittests/Support/TypeTraitsTest.cpp @@ -0,0 +1,77 @@ +//===- TypeTraitsTest.cpp -------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/type_traits.h" + +namespace { + +// Compile-time tests using static assert. +namespace triviality { + +// Helper for compile time checking trivially copy constructible and trivially +// move constructible type traits. +template <typename T, bool IsTriviallyCopyConstructible, + bool IsTriviallyMoveConstructible> +void TrivialityTester() { + static_assert(llvm::is_trivially_copy_constructible<T>::value == + IsTriviallyCopyConstructible, + "Mismatch in expected trivial copy construction!"); + static_assert(llvm::is_trivially_move_constructible<T>::value == + IsTriviallyMoveConstructible, + "Mismatch in expected trivial move construction!"); + +#if __clang__ || _MSC_VER || __GNUC__ > 5 + // On compilers with support for the standard traits, make sure they agree. + static_assert(std::is_trivially_copy_constructible<T>::value == + IsTriviallyCopyConstructible, + "Mismatch in expected trivial copy construction!"); + static_assert(std::is_trivially_move_constructible<T>::value == + IsTriviallyMoveConstructible, + "Mismatch in expected trivial move construction!"); +#endif +}; + +template void TrivialityTester<int, true, true>(); +template void TrivialityTester<void *, true, true>(); +template void TrivialityTester<int &, true, true>(); +template void TrivialityTester<int &&, false, true>(); + +struct X {}; +struct Y { + Y(const Y &); +}; +struct Z { + Z(const Z &); + Z(Z &&); +}; +struct A { + A(const A &) = default; + A(A &&); +}; +struct B { + B(const B &); + B(B &&) = default; +}; + +template void TrivialityTester<X, true, true>(); +template void TrivialityTester<Y, false, false>(); +template void TrivialityTester<Z, false, false>(); +template void TrivialityTester<A, true, false>(); +template void TrivialityTester<B, false, true>(); + +template void TrivialityTester<Z &, true, true>(); +template void TrivialityTester<A &, true, true>(); +template void TrivialityTester<B &, true, true>(); +template void TrivialityTester<Z &&, false, true>(); +template void TrivialityTester<A &&, false, true>(); +template void TrivialityTester<B &&, false, true>(); + +} // namespace triviality + +} // end anonymous namespace |