[ADT] Fix Optional<> with llvm::is_trivially_move_constructible

Fix the compatibility of Optional<> with some GCC versions that it will fail
to compile when T is getting checked for `is_trivially_move_constructible`
as mentioned here: https://reviews.llvm.org/D93510#2538983

Fix the problem by using `llvm::is_trivially_move_constructible`.

Reviewed By: jplayer-nv, tatyana-krasnukha

Differential Revision: https://reviews.llvm.org/D117254
This commit is contained in:
Steven Wu 2022-01-18 08:37:22 -08:00
parent f5ff1cab43
commit 347d4d7323
2 changed files with 24 additions and 12 deletions

View File

@ -34,12 +34,12 @@ namespace optional_detail {
/// Storage for any type.
//
// The specialization condition intentionally uses
// llvm::is_trivially_copy_constructible instead of
// std::is_trivially_copy_constructible. GCC versions prior to 7.4 may
// instantiate the copy constructor of `T` when
// std::is_trivially_copy_constructible is instantiated. This causes
// compilation to fail if we query the trivially copy constructible property of
// a class which is not copy constructible.
// llvm::is_trivially_{copy/move}_constructible instead of
// std::is_trivially_{copy/move}_constructible. GCC versions prior to 7.4 may
// instantiate the copy/move constructor of `T` when
// std::is_trivially_{copy/move}_constructible is instantiated. This causes
// compilation to fail if we query the trivially copy/move constructible
// property of a class which is not copy/move constructible.
//
// The current implementation of OptionalStorage insists that in order to use
// the trivial specialization, the value_type must be trivially copy
@ -50,12 +50,13 @@ namespace optional_detail {
//
// The move constructible / assignable conditions emulate the remaining behavior
// of std::is_trivially_copyable.
template <typename T, bool = (llvm::is_trivially_copy_constructible<T>::value &&
std::is_trivially_copy_assignable<T>::value &&
(std::is_trivially_move_constructible<T>::value ||
!std::is_move_constructible<T>::value) &&
(std::is_trivially_move_assignable<T>::value ||
!std::is_move_assignable<T>::value))>
template <typename T,
bool = (llvm::is_trivially_copy_constructible<T>::value &&
std::is_trivially_copy_assignable<T>::value &&
(llvm::is_trivially_move_constructible<T>::value ||
!std::is_move_constructible<T>::value) &&
(std::is_trivially_move_assignable<T>::value ||
!std::is_move_assignable<T>::value))>
class OptionalStorage {
union {
char empty;

View File

@ -805,4 +805,15 @@ TEST(OptionalTest, HashValue) {
EXPECT_EQ(hash_value(B), hash_value(I));
}
struct NotTriviallyCopyable {
NotTriviallyCopyable(); // Constructor out-of-line.
virtual ~NotTriviallyCopyable() = default;
Optional<MoveOnly> MO;
};
TEST(OptionalTest, GCCIsTriviallyMoveConstructibleCompat) {
Optional<NotTriviallyCopyable> V;
EXPECT_FALSE(V);
}
} // end anonymous namespace