Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit 9e64837

Browse files
Fix llvm::is_trivially_copyable portability issues
llvm::is_trivially_copyable portability is verified at compile time using std::is_trivially_copyable as the reference implementation. Unfortunately, the latter is not available on all platforms, so introduce a proper configure check to detect if it is available on the target platform. In a similar manner, std::is_copy_assignable is not fully supported for gcc4.9. Provide a portable (?) implementation instead. Differential Revision: https://reviews.llvm.org/D57018 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351820 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 703b827 commit 9e64837

File tree

4 files changed

+55
-6
lines changed

4 files changed

+55
-6
lines changed

cmake/config-ix.cmake

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,15 @@ else()
325325
unset(HAVE_FFI_CALL CACHE)
326326
endif( LLVM_ENABLE_FFI )
327327

328+
# Whether we can use std::is_trivially_copyable to verify llvm::is_trivially_copyable.
329+
CHECK_CXX_SOURCE_COMPILES("
330+
#include <type_traits>
331+
struct T { int val; };
332+
static_assert(std::is_trivially_copyable<T>::value, \"ok\");
333+
int main() { return 0;}
334+
" HAVE_STD_IS_TRIVIALLY_COPYABLE)
335+
336+
328337
# Define LLVM_HAS_ATOMICS if gcc or MSVC atomic builtins are supported.
329338
include(CheckAtomic)
330339

include/llvm/ADT/PointerIntPair.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define LLVM_ADT_POINTERINTPAIR_H
1515

1616
#include "llvm/Support/PointerLikeTypeTraits.h"
17+
#include "llvm/Support/type_traits.h"
1718
#include <cassert>
1819
#include <cstdint>
1920
#include <limits>
@@ -125,6 +126,19 @@ class PointerIntPair {
125126
}
126127
};
127128

129+
// Specialize is_trivially_copyable to avoid limitation of llvm::is_trivially_copyable
130+
// when compiled with gcc 4.9.
131+
template <typename PointerTy, unsigned IntBits, typename IntType,
132+
typename PtrTraits,
133+
typename Info>
134+
struct is_trivially_copyable<PointerIntPair<PointerTy, IntBits, IntType, PtrTraits, Info>> : std::true_type {
135+
#ifdef HAVE_STD_IS_TRIVIALLY_COPYABLE
136+
static_assert(std::is_trivially_copyable<PointerIntPair<PointerTy, IntBits, IntType, PtrTraits, Info>>::value,
137+
"inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable");
138+
#endif
139+
};
140+
141+
128142
template <typename PointerT, unsigned IntBits, typename PtrTraits>
129143
struct PointerIntPairInfo {
130144
static_assert(PtrTraits::NumLowBitsAvailable <

include/llvm/Config/config.h.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,9 @@
338338
/* Define as the return type of signal handlers (`int' or `void'). */
339339
#cmakedefine RETSIGTYPE ${RETSIGTYPE}
340340

341+
/* Define if std::is_trivially_copyable is supported */
342+
#cmakedefine HAVE_STD_IS_TRIVIALLY_COPYABLE ${HAVE_STD_IS_TRIVIALLY_COPYABLE}
343+
341344
/* Define to a function implementing stricmp */
342345
#cmakedefine stricmp ${stricmp}
343346

include/llvm/Support/type_traits.h

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ template<class T>
9595
union trivial_helper {
9696
T t;
9797
};
98+
9899
} // end namespace detail
99100

100101
/// An implementation of `std::is_trivially_copy_constructible` since we have
@@ -119,6 +120,24 @@ struct is_trivially_move_constructible<T &> : std::true_type {};
119120
template <typename T>
120121
struct is_trivially_move_constructible<T &&> : std::true_type {};
121122

123+
124+
template <typename T>
125+
struct is_copy_assignable {
126+
template<class F>
127+
static auto get(F*) -> decltype(std::declval<T &>() = std::declval<const T &>(), std::true_type{});
128+
static std::false_type get(...);
129+
static constexpr bool value = decltype(get((T*)nullptr))::value;
130+
};
131+
132+
template <typename T>
133+
struct is_move_assignable {
134+
template<class F>
135+
static auto get(F*) -> decltype(std::declval<T &>() = std::declval<T &&>(), std::true_type{});
136+
static std::false_type get(...);
137+
static constexpr bool value = decltype(get((T*)nullptr))::value;
138+
};
139+
140+
122141
// An implementation of `std::is_trivially_copyable` since STL version
123142
// is not equally supported by all compilers, especially GCC 4.9.
124143
// Uniform implementation of this trait is important for ABI compatibility
@@ -140,15 +159,15 @@ class is_trivially_copyable {
140159

141160
// copy assign
142161
static constexpr bool has_trivial_copy_assign =
143-
std::is_copy_assignable<detail::trivial_helper<T>>::value;
162+
is_copy_assignable<detail::trivial_helper<T>>::value;
144163
static constexpr bool has_deleted_copy_assign =
145-
!std::is_copy_assignable<T>::value;
164+
!is_copy_assignable<T>::value;
146165

147166
// move assign
148167
static constexpr bool has_trivial_move_assign =
149-
std::is_move_assignable<detail::trivial_helper<T>>::value;
168+
is_move_assignable<detail::trivial_helper<T>>::value;
150169
static constexpr bool has_deleted_move_assign =
151-
!std::is_move_assignable<T>::value;
170+
!is_move_assignable<T>::value;
152171

153172
// destructor
154173
static constexpr bool has_trivial_destructor =
@@ -163,10 +182,14 @@ class is_trivially_copyable {
163182
(has_deleted_copy_assign || has_trivial_copy_assign) &&
164183
(has_deleted_copy_constructor || has_trivial_copy_constructor);
165184

166-
#if (__has_feature(is_trivially_copyable) || (defined(__GNUC__) && __GNUC__ >= 5))
167-
static_assert(value == std::is_trivially_copyable<T>::value, "inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable");
185+
#ifdef HAVE_STD_IS_TRIVIALLY_COPYABLE
186+
static_assert(value == std::is_trivially_copyable<T>::value,
187+
"inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable");
168188
#endif
169189
};
190+
template <typename T>
191+
class is_trivially_copyable<T*> : public std::true_type {
192+
};
170193

171194

172195
} // end namespace llvm

0 commit comments

Comments
 (0)