From af60db9bfbab588e6d09e33bef210debf2317a38 Mon Sep 17 00:00:00 2001 From: Serge Guelton Date: Sat, 16 Feb 2019 09:19:58 +0000 Subject: [PATCH] Make Optional Trivially Copyable when T is trivially copyable This is another attempt in the process, works nicely on my setup, let's check how it behaves on other targets. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354199 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/Optional.h | 53 ++++++++++++++++++++++++++++++++++ unittests/ADT/OptionalTest.cpp | 7 +++++ 2 files changed, 60 insertions(+) diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 25a3185064f..ab83b67b11b 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -108,6 +108,59 @@ template ::value> struct OptionalSto return reinterpret_cast(storage.buffer); } }; +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::forward(y)); + } + OptionalStorage(OptionalStorage &&O) = default; + + OptionalStorage &operator=(T &&y) { + if (hasVal) + *getPointer() = std::move(y); + else { + new (storage.buffer) T(std::move(y)); + hasVal = true; + } + return *this; + } + OptionalStorage &operator=(OptionalStorage &&O) = default; + + OptionalStorage &operator=(const T &y) { + if (hasVal) + *getPointer() = y; + else { + new (storage.buffer) T(y); + hasVal = true; + } + return *this; + } + OptionalStorage &operator=(const OptionalStorage &O) = default; + + ~OptionalStorage() = default; + + void 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 diff --git a/unittests/ADT/OptionalTest.cpp b/unittests/ADT/OptionalTest.cpp index 98adaccca96..015fcf38981 100644 --- a/unittests/ADT/OptionalTest.cpp +++ b/unittests/ADT/OptionalTest.cpp @@ -14,8 +14,15 @@ #include + using namespace llvm; +static_assert(llvm::is_trivially_copyable>::value, + "trivially copyable"); + +static_assert(llvm::is_trivially_copyable>>::value, + "trivially copyable"); + namespace { struct NonDefaultConstructible { -- 2.50.1