summaryrefslogtreecommitdiffstats
path: root/llvm/include
diff options
context:
space:
mode:
authorSerge Guelton <sguelton@redhat.com>2019-02-18 12:07:12 +0000
committerSerge Guelton <sguelton@redhat.com>2019-02-18 12:07:12 +0000
commit6e0b562bf6e0e94e3ea6a755a9917b2725fd604d (patch)
tree5c1a6690c80fbcd1c43ae9d9ebdc21191f762f04 /llvm/include
parent515e7cdec04a4f77defecbc9453e11159b635ddf (diff)
downloadbcm5719-llvm-6e0b562bf6e0e94e3ea6a755a9917b2725fd604d.tar.gz
bcm5719-llvm-6e0b562bf6e0e94e3ea6a755a9917b2725fd604d.zip
[NFC] Make Optional<T> trivially copyable when T is trivially copyable
This is a follow-up to r354246 and a reimplementation of https://reviews.llvm.org/D57097?id=186600 that should not trigger any UB thanks to the use of an union. This may still be subject to the problem solved by std::launder, but I'm unsure how it interacts whith union. /me plans to revert if this triggers any relevant bot failure. At least this validates in Release mode with clang 6.0.1 and gcc 4.8.5. llvm-svn: 354264
Diffstat (limited to 'llvm/include')
-rw-r--r--llvm/include/llvm/ADT/Optional.h72
1 files changed, 72 insertions, 0 deletions
diff --git a/llvm/include/llvm/ADT/Optional.h b/llvm/include/llvm/ADT/Optional.h
index f135bb8f36a..1eb84c735d2 100644
--- a/llvm/include/llvm/ADT/Optional.h
+++ b/llvm/include/llvm/ADT/Optional.h
@@ -139,6 +139,78 @@ public:
}
};
+template <typename T> class OptionalStorage<T, true> {
+ union {
+ char empty;
+ T value;
+ };
+ bool hasVal = false;
+
+public:
+ ~OptionalStorage() = default;
+
+ OptionalStorage() noexcept : empty{} {}
+
+ OptionalStorage(OptionalStorage const &other) = default;
+ OptionalStorage(OptionalStorage &&other) = default;
+
+ OptionalStorage &operator=(OptionalStorage const &other) = default;
+ OptionalStorage &operator=(OptionalStorage &&other) = default;
+
+ template <class... Args>
+ explicit OptionalStorage(in_place_t, Args &&... args)
+ : value(std::forward<Args>(args)...), hasVal(true) {}
+
+ void reset() noexcept {
+ if (hasVal) {
+ value.~T();
+ hasVal = false;
+ }
+ }
+
+ bool hasValue() const noexcept { return hasVal; }
+
+ T &getValue() LLVM_LVALUE_FUNCTION noexcept {
+ assert(hasVal);
+ return value;
+ }
+ T const &getValue() const LLVM_LVALUE_FUNCTION noexcept {
+ assert(hasVal);
+ return value;
+ }
+#if LLVM_HAS_RVALUE_REFERENCE_THIS
+ T &&getValue() && noexcept {
+ assert(hasVal);
+ return std::move(value);
+ }
+#endif
+
+ template <class... Args> void emplace(Args &&... args) {
+ reset();
+ ::new ((void *)std::addressof(value)) T(std::forward<Args>(args)...);
+ hasVal = true;
+ }
+
+ OptionalStorage &operator=(T const &y) {
+ if (hasValue()) {
+ value = y;
+ } else {
+ ::new ((void *)std::addressof(value)) T(y);
+ hasVal = true;
+ }
+ return *this;
+ }
+ OptionalStorage &operator=(T &&y) {
+ if (hasValue()) {
+ value = std::move(y);
+ } else {
+ ::new ((void *)std::addressof(value)) T(std::move(y));
+ hasVal = true;
+ }
+ return *this;
+ }
+};
+
} // namespace optional_detail
template <typename T> class Optional {
OpenPOWER on IntegriCloud