From: Serge Guelton Date: Fri, 15 Feb 2019 15:17:29 +0000 (+0000) Subject: OptionalStorage implementation for trivial type, take III X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f6aa45dfcea0023f7cd605cf602e6497dd48795a;p=llvm OptionalStorage implementation for trivial type, take III This is another attempt at implementating optional storage for trivially copyable type, using an union instead of a raw buffer to hold the actual storage. This make it possible to get rid of the reinterpret_cast, and hopefully to fix the UB of the previous attempts. This validates fine on my laptop for gcc 8.2 and gcc 4.8, I'll revert if it breaks the validation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354137 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 25a3185064f..55bbfc5f100 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -109,6 +109,54 @@ template ::value> struct OptionalSto } }; +template struct OptionalStorage { + struct empty_type {}; + union { + empty_type empty; + T value; + }; + bool hasVal = false; + + OptionalStorage() : empty{} {} + + OptionalStorage(const T &y) : hasVal(true) { + new ((void*)std::addressof(value)) T(y); + } + OptionalStorage(const OptionalStorage &O) = default; + OptionalStorage(T &&y) : hasVal(true) { + new ((void*)std::addressof(value)) T(std::move(y)); + } + + OptionalStorage(OptionalStorage &&O) = default; + + OptionalStorage &operator=(T &&y) { + hasVal = true; + new ((void*)std::addressof(value)) T(std::move(y)); + return *this; + } + OptionalStorage &operator=(OptionalStorage &&O) = default; + + OptionalStorage &operator=(const T &y) { + hasVal = true; + new ((void*)std::addressof(value)) T(y); + return *this; + } + OptionalStorage &operator=(const OptionalStorage &O) = default; + + ~OptionalStorage() = default; + + T *getPointer() { + assert(hasVal); + return &value; + } + const T *getPointer() const { + assert(hasVal); + return &value; + } + + void reset() { hasVal = false; } +}; + } // namespace optional_detail template class Optional { @@ -153,11 +201,11 @@ public: const T *getPointer() const { assert(Storage.hasVal); - return reinterpret_cast(Storage.storage.buffer); + return Storage.getPointer(); } T *getPointer() { assert(Storage.hasVal); - return reinterpret_cast(Storage.storage.buffer); + return Storage.getPointer(); } const T &getValue() const LLVM_LVALUE_FUNCTION { return *getPointer(); } T &getValue() LLVM_LVALUE_FUNCTION { return *getPointer(); }