summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerge Guelton <sguelton@redhat.com>2019-02-15 15:17:29 +0000
committerSerge Guelton <sguelton@redhat.com>2019-02-15 15:17:29 +0000
commitfb4df68f48702377845a471fddcd1f67a3889ae4 (patch)
tree4b087a3decad0b6b49907075acb88a5ca3f800e3
parent5dfddff2424c836da0aa30225252d350a818468e (diff)
downloadbcm5719-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.h52
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(); }
OpenPOWER on IntegriCloud