Index: include/llvm/ADT/Optional.h =================================================================== --- include/llvm/ADT/Optional.h +++ include/llvm/ADT/Optional.h @@ -109,6 +109,48 @@ } }; +template struct OptionalStorage { + AlignedCharArrayUnion storage; + bool hasVal = false; + + OptionalStorage() = default; + + OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); } + OptionalStorage(const OptionalStorage &O) = default; + OptionalStorage(T &&y) : hasVal(true) { + new (storage.buffer) T(std::move(y)); + } + + OptionalStorage(OptionalStorage &&O) = default; + + OptionalStorage &operator=(T &&y) { + hasVal = true; + new (storage.buffer) T(std::move(y)); + return *this; + } + OptionalStorage &operator=(OptionalStorage &&O) = default; + + OptionalStorage &operator=(const T &y) { + hasVal = true; + new (storage.buffer) T(y); + return *this; + } + OptionalStorage &operator=(const OptionalStorage &O) = default; + + ~OptionalStorage() = default; + + T *getPointer() { + assert(hasVal); + return reinterpret_cast(storage.buffer); + } + const T *getPointer() const { + assert(hasVal); + return reinterpret_cast(storage.buffer); + } + + void reset() { hasVal = false; } +}; + } // namespace optional_detail template class Optional { Index: unittests/ADT/OptionalTest.cpp =================================================================== --- unittests/ADT/OptionalTest.cpp +++ unittests/ADT/OptionalTest.cpp @@ -16,6 +16,12 @@ 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; @@ -43,6 +49,10 @@ 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 { }; @@ -201,6 +211,10 @@ }; unsigned MultiArgConstructor::Destructions = 0; +static_assert( + !llvm::is_trivially_copyable>::value, + "not trivially copyable"); + TEST_F(OptionalTest, Emplace) { MultiArgConstructor::ResetCounts(); Optional A; @@ -248,6 +262,9 @@ 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; @@ -349,6 +366,9 @@ 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();