summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2018-01-18 16:23:40 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2018-01-18 16:23:40 +0000
commit0a2193054b13b5c4cc89cc101cedc0b3f0240d4f (patch)
treead52d80e4039eb9761f6d4bce089519ffaa5b35c
parent712cd41fa0b0f45a7bc589d89af273341be8c529 (diff)
downloadbcm5719-llvm-0a2193054b13b5c4cc89cc101cedc0b3f0240d4f.tar.gz
bcm5719-llvm-0a2193054b13b5c4cc89cc101cedc0b3f0240d4f.zip
[ADT] Just give up on GCC, I can't fix this.
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. llvm-svn: 322862
-rw-r--r--llvm/include/llvm/ADT/Optional.h13
-rw-r--r--llvm/unittests/ADT/OptionalTest.cpp3
2 files changed, 5 insertions, 11 deletions
diff --git a/llvm/include/llvm/ADT/Optional.h b/llvm/include/llvm/ADT/Optional.h
index 2c2d2c639da..0f073fab2a9 100644
--- a/llvm/include/llvm/ADT/Optional.h
+++ b/llvm/include/llvm/ADT/Optional.h
@@ -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 {
diff --git a/llvm/unittests/ADT/OptionalTest.cpp b/llvm/unittests/ADT/OptionalTest.cpp
index a9a37bf820d..be49b85f486 100644
--- a/llvm/unittests/ADT/OptionalTest.cpp
+++ b/llvm/unittests/ADT/OptionalTest.cpp
@@ -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(
OpenPOWER on IntegriCloud