Revert  [NFC] Better encapsulation of llvm::Optional Storage

I'm getting the feealing that current Optional implementation is full of UB :-/


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354217 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h
index 09a26b6..25a3185 100644
--- a/include/llvm/ADT/Optional.h
+++ b/include/llvm/ADT/Optional.h
@@ -30,12 +30,10 @@
 
 namespace optional_detail {
 /// Storage for any type.
-template <typename T, bool = is_trivially_copyable<T>::value>
-class OptionalStorage {
+template <typename T, bool = is_trivially_copyable<T>::value> struct OptionalStorage {
   AlignedCharArrayUnion<T> storage;
   bool hasVal = false;
 
-public:
   OptionalStorage() = default;
 
   OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
@@ -109,14 +107,6 @@
     assert(hasVal);
     return reinterpret_cast<const T *>(storage.buffer);
   }
-
-  template <typename... ArgTypes> void emplace(ArgTypes &&... Args) {
-    reset();
-    hasVal = true;
-    new (storage.buffer) T(std::forward<ArgTypes>(Args)...);
-  }
-
-  bool hasValue() const { return hasVal; }
 };
 
 } // namespace optional_detail
@@ -144,7 +134,9 @@
 
   /// Create a new object by constructing it in place with the given arguments.
   template <typename... ArgTypes> void emplace(ArgTypes &&... Args) {
-    Storage.emplace(std::forward<ArgTypes>(Args)...);
+    reset();
+    Storage.hasVal = true;
+    new (getPointer()) T(std::forward<ArgTypes>(Args)...);
   }
 
   static inline Optional create(const T *y) {
@@ -159,13 +151,19 @@
 
   void reset() { Storage.reset(); }
 
-  const T *getPointer() const { return Storage.getPointer(); }
-  T *getPointer() { return Storage.getPointer(); }
+  const T *getPointer() const {
+    assert(Storage.hasVal);
+    return reinterpret_cast<const T *>(Storage.storage.buffer);
+  }
+  T *getPointer() {
+    assert(Storage.hasVal);
+    return reinterpret_cast<T *>(Storage.storage.buffer);
+  }
   const T &getValue() const LLVM_LVALUE_FUNCTION { return *getPointer(); }
   T &getValue() LLVM_LVALUE_FUNCTION { return *getPointer(); }
 
-  explicit operator bool() const { return hasValue(); }
-  bool hasValue() const { return Storage.hasValue(); }
+  explicit operator bool() const { return Storage.hasVal; }
+  bool hasValue() const { return Storage.hasVal; }
   const T *operator->() const { return getPointer(); }
   T *operator->() { return getPointer(); }
   const T &operator*() const LLVM_LVALUE_FUNCTION { return *getPointer(); }