From 4ed5b9a3469de38a3cb8120c6f28e1221551a12e Mon Sep 17 00:00:00 2001 From: Russell Gallop Date: Thu, 15 Aug 2019 10:12:11 +0000 Subject: [PATCH] Revert rL368939 "Remove LVALUE / RVALUE workarounds" This reverts commit cad8356d699b36c73abb267f65db575ddacbd652. To unbreak Windows bots git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@368985 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/Optional.h | 25 +++++++++++++++---------- include/llvm/Support/Compiler.h | 20 ++++++++++++++++++++ unittests/ADT/OptionalTest.cpp | 4 ++++ 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 420f21b0d64..b45a74002e1 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -69,18 +69,20 @@ public: bool hasValue() const noexcept { return hasVal; } - T &getValue() & noexcept { + T &getValue() LLVM_LVALUE_FUNCTION noexcept { assert(hasVal); return value; } - T const &getValue() const & noexcept { + 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 void emplace(Args &&... args) { reset(); @@ -167,19 +169,20 @@ public: bool hasValue() const noexcept { return hasVal; } - T &getValue() & noexcept { + T &getValue() LLVM_LVALUE_FUNCTION noexcept { assert(hasVal); return value; } - T const &getValue() const & noexcept { + 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 void emplace(Args &&... args) { reset(); @@ -249,21 +252,22 @@ public: const T *getPointer() const { return &Storage.getValue(); } T *getPointer() { return &Storage.getValue(); } - const T &getValue() const & { return Storage.getValue(); } - T &getValue() & { return Storage.getValue(); } + const T &getValue() const LLVM_LVALUE_FUNCTION { return Storage.getValue(); } + T &getValue() LLVM_LVALUE_FUNCTION { return Storage.getValue(); } explicit operator bool() const { return hasValue(); } bool hasValue() const { return Storage.hasValue(); } const T *operator->() const { return getPointer(); } T *operator->() { return getPointer(); } - const T &operator*() const & { return getValue(); } - T &operator*() & { return getValue(); } + const T &operator*() const LLVM_LVALUE_FUNCTION { return getValue(); } + T &operator*() LLVM_LVALUE_FUNCTION { return getValue(); } template - constexpr T getValueOr(U &&value) const & { + constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION { return hasValue() ? getValue() : std::forward(value); } +#if LLVM_HAS_RVALUE_REFERENCE_THIS T &&getValue() && { return std::move(Storage.getValue()); } T &&operator*() && { return std::move(Storage.getValue()); } @@ -271,6 +275,7 @@ public: T getValueOr(U &&value) && { return hasValue() ? std::move(getValue()) : std::forward(value); } +#endif }; template diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 8f54db7c826..43114ad3a43 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -83,6 +83,26 @@ #define LLVM_MSC_PREREQ(version) 0 #endif +/// Does the compiler support ref-qualifiers for *this? +/// +/// Sadly, this is separate from just rvalue reference support because GCC +/// and MSVC implemented this later than everything else. +#if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1) +#define LLVM_HAS_RVALUE_REFERENCE_THIS 1 +#else +#define LLVM_HAS_RVALUE_REFERENCE_THIS 0 +#endif + +/// Expands to '&' if ref-qualifiers for *this are supported. +/// +/// This can be used to provide lvalue/rvalue overrides of member functions. +/// The rvalue override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS +#if LLVM_HAS_RVALUE_REFERENCE_THIS +#define LLVM_LVALUE_FUNCTION & +#else +#define LLVM_LVALUE_FUNCTION +#endif + /// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked /// into a shared library, then the class should be private to the library and /// not accessible from outside it. Can also be used to mark variables and diff --git a/unittests/ADT/OptionalTest.cpp b/unittests/ADT/OptionalTest.cpp index 3b58abf57d7..1f26c101183 100644 --- a/unittests/ADT/OptionalTest.cpp +++ b/unittests/ADT/OptionalTest.cpp @@ -382,6 +382,8 @@ TEST_F(OptionalTest, ImmovableEmplace) { EXPECT_EQ(0u, Immovable::Destructions); } +#if LLVM_HAS_RVALUE_REFERENCE_THIS + TEST_F(OptionalTest, MoveGetValueOr) { Optional A; @@ -399,6 +401,8 @@ TEST_F(OptionalTest, MoveGetValueOr) { EXPECT_EQ(2u, MoveOnly::Destructions); } +#endif // LLVM_HAS_RVALUE_REFERENCE_THIS + struct EqualTo { template static bool apply(const T &X, const U &Y) { return X == Y; -- 2.49.0