ilya-biryukov created this revision. ilya-biryukov added a reviewer: sammccall. Herald added subscribers: ioeric, jkorous-apple, klimek.
r322838 changed semantics for llvm::Optional that removes the guarantee of setting the value to empty after move. This change creates a wrapper around Optional that gives this guarantee, it is useful for code dealing with empty values that could be moved. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D42525 Files: clangd/Function.h Index: clangd/Function.h =================================================================== --- clangd/Function.h +++ clangd/Function.h @@ -138,6 +138,33 @@ } namespace detail { +/// Optional-like type that sets its value to llvm::None when it was moved +/// constructed from. +template <class T> class CleaningOptional { +public: + static_assert(std::is_same<typename std::decay<T>::type, T>::value, + "Implementation currently only supports decayed types"); + + CleaningOptional(T Value) : Value(std::move(Value)) {} + + CleaningOptional(CleaningOptional &&Other) : Value(std::move(Other.Value)) { + Other.Value = llvm::None; + } + + CleaningOptional &operator=(CleaningOptional &&Other) { + Value = std::move(Other.Value); + Other.Value = llvm::None; + } + + explicit operator bool() const { return static_cast<bool>(Value); } + + T &operator*() { return *Value; } + const T &operator*() const { return *Value; } + +private: + llvm::Optional<T> Value; +}; + /// Runs provided callback in destructor. Use onScopeExit helper function to /// create this object. template <class Func> struct ScopeExitGuard { @@ -159,7 +186,7 @@ ScopeExitGuard &operator=(ScopeExitGuard &&Other) = default; private: - llvm::Optional<Func> F; + CleaningOptional<Func> F; }; } // namespace detail
Index: clangd/Function.h =================================================================== --- clangd/Function.h +++ clangd/Function.h @@ -138,6 +138,33 @@ } namespace detail { +/// Optional-like type that sets its value to llvm::None when it was moved +/// constructed from. +template <class T> class CleaningOptional { +public: + static_assert(std::is_same<typename std::decay<T>::type, T>::value, + "Implementation currently only supports decayed types"); + + CleaningOptional(T Value) : Value(std::move(Value)) {} + + CleaningOptional(CleaningOptional &&Other) : Value(std::move(Other.Value)) { + Other.Value = llvm::None; + } + + CleaningOptional &operator=(CleaningOptional &&Other) { + Value = std::move(Other.Value); + Other.Value = llvm::None; + } + + explicit operator bool() const { return static_cast<bool>(Value); } + + T &operator*() { return *Value; } + const T &operator*() const { return *Value; } + +private: + llvm::Optional<T> Value; +}; + /// Runs provided callback in destructor. Use onScopeExit helper function to /// create this object. template <class Func> struct ScopeExitGuard { @@ -159,7 +186,7 @@ ScopeExitGuard &operator=(ScopeExitGuard &&Other) = default; private: - llvm::Optional<Func> F; + CleaningOptional<Func> F; }; } // namespace detail
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits