OSDN Git Service

[ADT] Just give up on GCC, I can't fix this.
authorBenjamin Kramer <benny.kra@googlemail.com>
Thu, 18 Jan 2018 16:23:40 +0000 (16:23 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Thu, 18 Jan 2018 16:23:40 +0000 (16:23 +0000)
While the memmove workaround fixed it for GCC 6.3. GCC 4.8 and GCC 7.1
are still broken. I have no clue what's going on, just blacklist GCC for
now.

Needless to say this code is ubsan, asan and msan-clean.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@322862 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/Optional.h
unittests/ADT/OptionalTest.cpp

index 2c2d2c6..0f073fa 100644 (file)
@@ -23,7 +23,6 @@
 #include <algorithm>
 #include <cassert>
 #include <new>
-#include <cstring>
 #include <utility>
 
 namespace llvm {
@@ -111,6 +110,7 @@ template <typename T, bool IsPodLike> struct OptionalStorage {
   }
 };
 
+#if !defined(__GNUC__) || defined(__clang__) // GCC up to GCC7 miscompiles this.
 /// Storage for trivially copyable types only.
 template <typename T> struct OptionalStorage<T, true> {
   AlignedCharArrayUnion<T> storage;
@@ -118,21 +118,16 @@ template <typename T> struct OptionalStorage<T, true> {
 
   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<T *>(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 <typename T> class Optional {
index a9a37bf..be49b85 100644 (file)
@@ -518,8 +518,7 @@ TEST_F(OptionalTest, OperatorGreaterEqual) {
   CheckRelation<GreaterEqual>(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<Optional<int>>::value,
               "Should be trivially copyable");
 static_assert(