From: Serge Guelton Date: Wed, 13 Feb 2019 11:35:45 +0000 (+0000) Subject: Revert r353927 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e194414673592749c06af78585d27aafc27b3a87;p=llvm Revert r353927 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@353940 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 35ce0ce7010..25a3185064f 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -29,77 +29,36 @@ namespace llvm { class raw_ostream; namespace optional_detail { - /// Storage for any type. -// -template struct OptionalTrivialStorage { +template ::value> struct OptionalStorage { AlignedCharArrayUnion storage; bool hasVal = false; - OptionalTrivialStorage() = default; - OptionalTrivialStorage(OptionalTrivialStorage const &) = default; - OptionalTrivialStorage(OptionalTrivialStorage &&) = default; - OptionalTrivialStorage &operator=(OptionalTrivialStorage const &) = default; - OptionalTrivialStorage &operator=(OptionalTrivialStorage &&) = default; - ~OptionalTrivialStorage() = default; - - OptionalTrivialStorage(const T &y) : hasVal(true) { - new (storage.buffer) T(y); - } - OptionalTrivialStorage(T &&y) : hasVal(true) { - new (storage.buffer) T(std::move(y)); - } - - OptionalTrivialStorage &operator=(const T &y) { - new (storage.buffer) T(y); - hasVal = true; - return *this; - } - OptionalTrivialStorage &operator=(T &&y) { - new (storage.buffer) T(std::move(y)); - hasVal = true; - return *this; - } - - T *getPointer() { - assert(hasVal); - return reinterpret_cast(storage.buffer); - } - const T *getPointer() const { - assert(hasVal); - return reinterpret_cast(storage.buffer); - } - void reset() { hasVal = false; } -}; - -template struct OptionalStorage : OptionalTrivialStorage { OptionalStorage() = default; - OptionalStorage(const T &y) : OptionalTrivialStorage(y) {} - OptionalStorage(T &&y) : OptionalTrivialStorage(std::move(y)) {} - - OptionalStorage(const OptionalStorage &O) : OptionalTrivialStorage() { - this->hasVal = O.hasVal; - if (this->hasVal) - new (this->storage.buffer) T(*O.getPointer()); + OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); } + OptionalStorage(const OptionalStorage &O) : hasVal(O.hasVal) { + if (hasVal) + new (storage.buffer) T(*O.getPointer()); } - - OptionalStorage(OptionalStorage &&O) : OptionalTrivialStorage() { - this->hasVal = O.hasVal; + OptionalStorage(T &&y) : hasVal(true) { + new (storage.buffer) T(std::forward(y)); + } + OptionalStorage(OptionalStorage &&O) : hasVal(O.hasVal) { if (O.hasVal) { - new (this->storage.buffer) T(std::move(*O.getPointer())); + new (storage.buffer) T(std::move(*O.getPointer())); } } OptionalStorage &operator=(T &&y) { - if (this->hasVal) - *this->getPointer() = std::move(y); + if (hasVal) + *getPointer() = std::move(y); else { - OptionalTrivialStorage::operator=(std::move(y)); + new (storage.buffer) T(std::move(y)); + hasVal = true; } return *this; } - OptionalStorage &operator=(OptionalStorage &&O) { if (!O.hasVal) reset(); @@ -115,10 +74,11 @@ template struct OptionalStorage : OptionalTrivialStorage { // requirements (notably: the existence of a default ctor) when implemented // in that way. Careful SFINAE to avoid such pitfalls would be required. OptionalStorage &operator=(const T &y) { - if (this->hasVal) - *this->getPointer() = y; + if (hasVal) + *getPointer() = y; else { - OptionalTrivialStorage::operator=(y); + new (storage.buffer) T(y); + hasVal = true; } return *this; } @@ -133,19 +93,26 @@ template struct OptionalStorage : OptionalTrivialStorage { ~OptionalStorage() { reset(); } void reset() { - if (this->hasVal) { - (*this->getPointer()).~T(); - OptionalTrivialStorage::reset(); + if (hasVal) { + (*getPointer()).~T(); + hasVal = false; } } + + T *getPointer() { + assert(hasVal); + return reinterpret_cast(storage.buffer); + } + const T *getPointer() const { + assert(hasVal); + return reinterpret_cast(storage.buffer); + } }; } // namespace optional_detail template class Optional { - typename std::conditional::value, - optional_detail::OptionalTrivialStorage, - optional_detail::OptionalStorage>::type Storage; + optional_detail::OptionalStorage Storage; public: using value_type = T; diff --git a/unittests/ADT/OptionalTest.cpp b/unittests/ADT/OptionalTest.cpp index c39b6727cd5..98adaccca96 100644 --- a/unittests/ADT/OptionalTest.cpp +++ b/unittests/ADT/OptionalTest.cpp @@ -18,12 +18,6 @@ using namespace llvm; namespace { -static_assert(llvm::is_trivially_copyable>::value, - "trivially copyable"); - -static_assert(llvm::is_trivially_copyable>>::value, - "trivially copyable"); - struct NonDefaultConstructible { static unsigned CopyConstructions; static unsigned Destructions; @@ -51,10 +45,6 @@ unsigned NonDefaultConstructible::CopyConstructions = 0; unsigned NonDefaultConstructible::Destructions = 0; unsigned NonDefaultConstructible::CopyAssignments = 0; -static_assert( - !llvm::is_trivially_copyable>::value, - "not trivially copyable"); - // Test fixture class OptionalTest : public testing::Test { }; @@ -213,10 +203,6 @@ struct MultiArgConstructor { }; unsigned MultiArgConstructor::Destructions = 0; -static_assert( - !llvm::is_trivially_copyable>::value, - "not trivially copyable"); - TEST_F(OptionalTest, Emplace) { MultiArgConstructor::ResetCounts(); Optional A; @@ -264,9 +250,6 @@ unsigned MoveOnly::MoveConstructions = 0; unsigned MoveOnly::Destructions = 0; unsigned MoveOnly::MoveAssignments = 0; -static_assert(!llvm::is_trivially_copyable>::value, - "not trivially copyable"); - TEST_F(OptionalTest, MoveOnlyNull) { MoveOnly::ResetCounts(); Optional O; @@ -368,9 +351,6 @@ private: unsigned Immovable::Constructions = 0; unsigned Immovable::Destructions = 0; -static_assert(!llvm::is_trivially_copyable>::value, - "not trivially copyable"); - TEST_F(OptionalTest, ImmovableEmplace) { Optional A; Immovable::ResetCounts();