diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 2c2d2c639dae6d..0f073fab2a9640 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -23,7 +23,6 @@ #include #include #include -#include #include namespace llvm { @@ -111,6 +110,7 @@ template struct OptionalStorage { } }; +#if !defined(__GNUC__) || defined(__clang__) // GCC up to GCC7 miscompiles this. /// Storage for trivially copyable types only. template struct OptionalStorage { AlignedCharArrayUnion storage; @@ -118,21 +118,16 @@ template struct OptionalStorage { OptionalStorage() = default; - OptionalStorage(const T &y) : hasVal(true) { - // We use memmove here because we know that T is trivially copyable and GCC - // up to 7 miscompiles placement new. - std::memmove(storage.buffer, &y, sizeof(y)); - } + OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); } OptionalStorage &operator=(const T &y) { + *reinterpret_cast(storage.buffer) = y; hasVal = true; - // We use memmove here because we know that T is trivially copyable and GCC - // up to 7 miscompiles placement new. - std::memmove(storage.buffer, &y, sizeof(y)); return *this; } void reset() { hasVal = false; } }; +#endif } // namespace optional_detail template class Optional { diff --git a/unittests/ADT/OptionalTest.cpp b/unittests/ADT/OptionalTest.cpp index a9a37bf820d002..be49b85f4860d9 100644 --- a/unittests/ADT/OptionalTest.cpp +++ b/unittests/ADT/OptionalTest.cpp @@ -518,8 +518,7 @@ TEST_F(OptionalTest, OperatorGreaterEqual) { CheckRelation(InequalityLhs, InequalityRhs, !IsLess); } -#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \ - (defined(__GNUC__) && __GNUC__ >= 5) +#if __has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION) static_assert(std::is_trivially_copyable>::value, "Should be trivially copyable"); static_assert(