[llvm] r354137 - OptionalStorage implementation for trivial type, take III

Serge Guelton via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 15 07:17:30 PST 2019


Author: serge_sans_paille
Date: Fri Feb 15 07:17:29 2019
New Revision: 354137

URL: http://llvm.org/viewvc/llvm-project?rev=354137&view=rev
Log:
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.


Modified:
    llvm/trunk/include/llvm/ADT/Optional.h

Modified: llvm/trunk/include/llvm/ADT/Optional.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/Optional.h?rev=354137&r1=354136&r2=354137&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/Optional.h (original)
+++ llvm/trunk/include/llvm/ADT/Optional.h Fri Feb 15 07:17:29 2019
@@ -109,6 +109,54 @@ template <typename T, bool = is_triviall
   }
 };
 
+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(); }




More information about the llvm-commits mailing list