diff options
| author | Serge Guelton <sguelton@redhat.com> | 2019-02-15 15:17:29 +0000 |
|---|---|---|
| committer | Serge Guelton <sguelton@redhat.com> | 2019-02-15 15:17:29 +0000 |
| commit | fb4df68f48702377845a471fddcd1f67a3889ae4 (patch) | |
| tree | 4b087a3decad0b6b49907075acb88a5ca3f800e3 | |
| parent | 5dfddff2424c836da0aa30225252d350a818468e (diff) | |
| download | bcm5719-llvm-fb4df68f48702377845a471fddcd1f67a3889ae4.tar.gz bcm5719-llvm-fb4df68f48702377845a471fddcd1f67a3889ae4.zip | |
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.
llvm-svn: 354137
| -rw-r--r-- | llvm/include/llvm/ADT/Optional.h | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/llvm/include/llvm/ADT/Optional.h b/llvm/include/llvm/ADT/Optional.h index 25a3185064f..55bbfc5f100 100644 --- a/llvm/include/llvm/ADT/Optional.h +++ b/llvm/include/llvm/ADT/Optional.h @@ -109,6 +109,54 @@ template <typename T, bool = is_trivially_copyable<T>::value> struct OptionalSto } }; +template <typename T> struct OptionalStorage<T, true> { + 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 <typename T> class Optional { @@ -153,11 +201,11 @@ public: const T *getPointer() const { assert(Storage.hasVal); - return reinterpret_cast<const T *>(Storage.storage.buffer); + return Storage.getPointer(); } T *getPointer() { assert(Storage.hasVal); - return reinterpret_cast<T *>(Storage.storage.buffer); + return Storage.getPointer(); } const T &getValue() const LLVM_LVALUE_FUNCTION { return *getPointer(); } T &getValue() LLVM_LVALUE_FUNCTION { return *getPointer(); } |

