Skip to content

Commit f814ad8

Browse files
committed
[Support] Fix llvm::unique_function when building with GCC 4.9 by
introducing llvm::trivially_{copy,move}_constructible type traits. This uses a completely portable implementation of these traits provided by Richard Smith. You can see it on compiler explorer in all its glory: https://godbolt.org/g/QEDZjW I have transcribed it, clang-formatted it, added some comments, and made the tests fit into a unittest file. I have also switched llvm::unique_function over to use these new, much more portable traits. =D Hopefully this will fix the build bot breakage from my prior commit. llvm-svn: 336161
1 parent f8182f1 commit f814ad8

File tree

4 files changed

+120
-3
lines changed

4 files changed

+120
-3
lines changed

llvm/include/llvm/ADT/FunctionExtras.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535

3636
#include "llvm/ADT/PointerIntPair.h"
3737
#include "llvm/ADT/PointerUnion.h"
38+
#include "llvm/Support/type_traits.h"
3839
#include <memory>
39-
#include <type_traits>
4040

4141
namespace llvm {
4242

@@ -58,8 +58,8 @@ class unique_function<ReturnT(ParamTs...)> {
5858
template <typename T>
5959
using AdjustedParamT = typename std::conditional<
6060
!std::is_reference<T>::value &&
61-
std::is_trivially_copy_constructible<T>::value &&
62-
std::is_trivially_move_constructible<T>::value &&
61+
llvm::is_trivially_copy_constructible<T>::value &&
62+
llvm::is_trivially_move_constructible<T>::value &&
6363
sizeof(T) <= (2 * sizeof(void *)),
6464
T, T &>::type;
6565

llvm/include/llvm/Support/type_traits.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,45 @@ struct const_pointer_or_const_ref<
104104
using type = typename add_const_past_pointer<T>::type;
105105
};
106106

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+
107146
} // end namespace llvm
108147

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

llvm/unittests/Support/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ add_llvm_unittest(SupportTests
5959
Threading.cpp
6060
TimerTest.cpp
6161
TypeNameTest.cpp
62+
TypeTraitsTest.cpp
6263
TrailingObjectsTest.cpp
6364
TrigramIndexTest.cpp
6465
UnicodeTest.cpp
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//===- TypeTraitsTest.cpp -------------------------------------------------===//
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+
#include "llvm/Support/type_traits.h"
11+
12+
namespace {
13+
14+
// Compile-time tests using static assert.
15+
namespace triviality {
16+
17+
// Helper for compile time checking trivially copy constructible and trivially
18+
// move constructible type traits.
19+
template <typename T, bool IsTriviallyCopyConstructible,
20+
bool IsTriviallyMoveConstructible>
21+
void TrivialityTester() {
22+
static_assert(llvm::is_trivially_copy_constructible<T>::value ==
23+
IsTriviallyCopyConstructible,
24+
"Mismatch in expected trivial copy construction!");
25+
static_assert(llvm::is_trivially_move_constructible<T>::value ==
26+
IsTriviallyMoveConstructible,
27+
"Mismatch in expected trivial move construction!");
28+
29+
#if __clang__ || _MSC_VER || __GNUC__ > 5
30+
// On compilers with support for the standard traits, make sure they agree.
31+
static_assert(std::is_trivially_copy_constructible<T>::value ==
32+
IsTriviallyCopyConstructible,
33+
"Mismatch in expected trivial copy construction!");
34+
static_assert(std::is_trivially_move_constructible<T>::value ==
35+
IsTriviallyMoveConstructible,
36+
"Mismatch in expected trivial move construction!");
37+
#endif
38+
};
39+
40+
template void TrivialityTester<int, true, true>();
41+
template void TrivialityTester<void *, true, true>();
42+
template void TrivialityTester<int &, true, true>();
43+
template void TrivialityTester<int &&, false, true>();
44+
45+
struct X {};
46+
struct Y {
47+
Y(const Y &);
48+
};
49+
struct Z {
50+
Z(const Z &);
51+
Z(Z &&);
52+
};
53+
struct A {
54+
A(const A &) = default;
55+
A(A &&);
56+
};
57+
struct B {
58+
B(const B &);
59+
B(B &&) = default;
60+
};
61+
62+
template void TrivialityTester<X, true, true>();
63+
template void TrivialityTester<Y, false, false>();
64+
template void TrivialityTester<Z, false, false>();
65+
template void TrivialityTester<A, true, false>();
66+
template void TrivialityTester<B, false, true>();
67+
68+
template void TrivialityTester<Z &, true, true>();
69+
template void TrivialityTester<A &, true, true>();
70+
template void TrivialityTester<B &, true, true>();
71+
template void TrivialityTester<Z &&, false, true>();
72+
template void TrivialityTester<A &&, false, true>();
73+
template void TrivialityTester<B &&, false, true>();
74+
75+
} // namespace triviality
76+
77+
} // end anonymous namespace

0 commit comments

Comments
 (0)