kuhnel updated this revision to Diff 355470. kuhnel added a comment. addressed Sam's review comments
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D105014/new/ https://reviews.llvm.org/D105014 Files: llvm/include/llvm/Support/Error.h
Index: llvm/include/llvm/Support/Error.h =================================================================== --- llvm/include/llvm/Support/Error.h +++ llvm/include/llvm/Support/Error.h @@ -162,7 +162,7 @@ // handleErrors needs to be able to set the Checked flag. template <typename... HandlerTs> - friend Error handleErrors(Error E, HandlerTs &&... Handlers); + friend Error handleErrors(Error E, HandlerTs &&...Handlers); // Expected<T> needs to be able to steal the payload when constructed from an // error. @@ -244,7 +244,7 @@ /// Returns the dynamic class id of this error, or null if this is a success /// value. - const void* dynamicClassID() const { + const void *dynamicClassID() const { if (!getPtr()) return nullptr; return getPtr()->dynamicClassID(); @@ -270,9 +270,8 @@ ErrorInfoBase *getPtr() const { #if LLVM_ENABLE_ABI_BREAKING_CHECKS - return reinterpret_cast<ErrorInfoBase*>( - reinterpret_cast<uintptr_t>(Payload) & - ~static_cast<uintptr_t>(0x1)); + return reinterpret_cast<ErrorInfoBase *>( + reinterpret_cast<uintptr_t>(Payload) & ~static_cast<uintptr_t>(0x1)); #else return Payload; #endif @@ -280,10 +279,9 @@ void setPtr(ErrorInfoBase *EI) { #if LLVM_ENABLE_ABI_BREAKING_CHECKS - Payload = reinterpret_cast<ErrorInfoBase*>( - (reinterpret_cast<uintptr_t>(EI) & - ~static_cast<uintptr_t>(0x1)) | - (reinterpret_cast<uintptr_t>(Payload) & 0x1)); + Payload = reinterpret_cast<ErrorInfoBase *>( + (reinterpret_cast<uintptr_t>(EI) & ~static_cast<uintptr_t>(0x1)) | + (reinterpret_cast<uintptr_t>(Payload) & 0x1)); #else Payload = EI; #endif @@ -299,10 +297,9 @@ void setChecked(bool V) { #if LLVM_ENABLE_ABI_BREAKING_CHECKS - Payload = reinterpret_cast<ErrorInfoBase*>( - (reinterpret_cast<uintptr_t>(Payload) & - ~static_cast<uintptr_t>(0x1)) | - (V ? 0 : 1)); + Payload = reinterpret_cast<ErrorInfoBase *>( + (reinterpret_cast<uintptr_t>(Payload) & ~static_cast<uintptr_t>(0x1)) | + (V ? 0 : 1)); #endif } @@ -333,7 +330,7 @@ /// Make a Error instance representing failure using the given error info /// type. -template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) { +template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&...Args) { return Error(std::make_unique<ErrT>(std::forward<ArgTs>(Args)...)); } @@ -366,7 +363,7 @@ // handleErrors needs to be able to iterate the payload list of an // ErrorList. template <typename... HandlerTs> - friend Error handleErrors(Error E, HandlerTs &&... Handlers); + friend Error handleErrors(Error E, HandlerTs &&...Handlers); // joinErrors is implemented in terms of join. friend Error joinErrors(Error, Error); @@ -436,6 +433,40 @@ /// Error cannot be copied, this class replaces getError() with /// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the /// error class type. +/// +/// Example usage of 'Expected<T>' as a function return type: +/// +/// @code{.cpp} +/// Expected<int> myDivide(int A, int B) { +/// if (B == 0) { +/// // return an Error +/// return createStringError(inconvertibleErrorCode(), +/// "B must not be zero!"); +/// } +/// // return an integer +/// return A / B; +/// } +/// @endcode +/// +/// Checking the results of to a function returning 'Expected<T>': +/// @code{.cpp} +/// auto Result = myDivide(X,Y); +/// if (auto E = Result.takeError()) { +/// // We must consume the error. Typically one of: +/// // - return the error to our caller +/// // - toString(), when logging +/// // - consumeError(), to silently swallow the error +/// // - handleErrors(), to distinguish error types +/// errs() << "Problem with division " +/// << toString(Result.takeError()) << "\n"; +/// } +/// // use the result +/// outs() << "The answer is " << *Result << "\n"; +/// @endcode +/// +/// For unit-testing a function returning an 'Expceted<T>', see the +/// 'EXPECT_THAT_EXPECTED' macros in llvm/Testing/Support/Error.h + template <class T> class LLVM_NODISCARD Expected { template <class T1> friend class ExpectedAsOutParameter; template <class OtherT> friend class Expected; @@ -462,7 +493,8 @@ : HasError(true) #if LLVM_ENABLE_ABI_BREAKING_CHECKS // Expected is unchecked upon construction in Debug builds. - , Unchecked(true) + , + Unchecked(true) #endif { assert(Err && "Cannot create Expected<T> from Error success value."); @@ -764,7 +796,7 @@ /// Bar &X = cantFail(foo(false)); /// @endcode template <typename T> -T& cantFail(Expected<T&> ValOrErr, const char *Msg = nullptr) { +T &cantFail(Expected<T &> ValOrErr, const char *Msg = nullptr) { if (ValOrErr) return *ValOrErr; else { @@ -785,8 +817,8 @@ /// ErrorInfo types. template <typename HandlerT> class ErrorHandlerTraits - : public ErrorHandlerTraits<decltype( - &std::remove_reference<HandlerT>::type::operator())> {}; + : public ErrorHandlerTraits< + decltype(&std::remove_reference<HandlerT>::type::operator())> {}; // Specialization functions of the form 'Error (const ErrT&)'. template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> { @@ -888,7 +920,7 @@ template <typename HandlerT, typename... HandlerTs> Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload, - HandlerT &&Handler, HandlerTs &&... Handlers) { + HandlerT &&Handler, HandlerTs &&...Handlers) { if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload)) return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler), std::move(Payload)); @@ -903,7 +935,7 @@ /// or returned. If you intend to handle all errors use handleAllErrors /// (which returns void, and will abort() on unhandled errors) instead. template <typename... HandlerTs> -Error handleErrors(Error E, HandlerTs &&... Hs) { +Error handleErrors(Error E, HandlerTs &&...Hs) { if (!E) return Error::success(); @@ -926,15 +958,13 @@ /// *must* be handled by the given handlers (i.e. there must be no remaining /// errors after running the handlers, or llvm_unreachable is called). template <typename... HandlerTs> -void handleAllErrors(Error E, HandlerTs &&... Handlers) { +void handleAllErrors(Error E, HandlerTs &&...Handlers) { cantFail(handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...)); } /// Check that E is a non-error, then drop it. /// If E is an error, llvm_unreachable will be called. -inline void handleAllErrors(Error E) { - cantFail(std::move(E)); -} +inline void handleAllErrors(Error E) { cantFail(std::move(E)); } /// Handle any errors (if present) in an Expected<T>, then try a recovery path. /// @@ -962,7 +992,7 @@ /// @endcode template <typename T, typename RecoveryFtor, typename... HandlerTs> Expected<T> handleExpected(Expected<T> ValOrErr, RecoveryFtor &&RecoveryPath, - HandlerTs &&... Handlers) { + HandlerTs &&...Handlers) { if (ValOrErr) return ValOrErr; @@ -1078,11 +1108,9 @@ /// Helper for Expected<T>s used as out-parameters. /// /// See ErrorAsOutParameter. -template <typename T> -class ExpectedAsOutParameter { +template <typename T> class ExpectedAsOutParameter { public: - ExpectedAsOutParameter(Expected<T> *ValOrErr) - : ValOrErr(ValOrErr) { + ExpectedAsOutParameter(Expected<T> *ValOrErr) : ValOrErr(ValOrErr) { if (ValOrErr) (void)!!*ValOrErr; } @@ -1126,7 +1154,7 @@ /// It should only be used in this situation, and should never be used where a /// sensible conversion to std::error_code is available, as attempts to convert /// to/from this error will result in a fatal error. (i.e. it is a programmatic -///error to try to convert such a value). +/// error to try to convert such a value). std::error_code inconvertibleErrorCode(); /// Helper for converting an std::error_code to a Error. @@ -1200,7 +1228,7 @@ /// Create formatted StringError object. template <typename... Ts> inline Error createStringError(std::error_code EC, char const *Fmt, - const Ts &... Vals) { + const Ts &...Vals) { std::string Buffer; raw_string_ostream Stream(Buffer); Stream << format(Fmt, Vals...); @@ -1215,7 +1243,7 @@ template <typename... Ts> inline Error createStringError(std::errc EC, char const *Fmt, - const Ts &... Vals) { + const Ts &...Vals) { return createStringError(std::make_error_code(EC), Fmt, Vals...); } @@ -1285,7 +1313,7 @@ return FileError::build(F, Optional<size_t>(Line), std::move(E)); } -/// Concatenate a source file path and/or name with a std::error_code +/// Concatenate a source file path and/or name with a std::error_code /// to form an Error object. inline Error createFileError(const Twine &F, std::error_code EC) { return createFileError(F, errorCodeToError(EC)); @@ -1328,9 +1356,9 @@ return std::move(*E); } - /// Check E. If it's in a success state then return the contained reference. If - /// it's in a failure state log the error(s) and exit. - template <typename T> T& operator()(Expected<T&> &&E) const { + /// Check E. If it's in a success state then return the contained reference. + /// If it's in a failure state log the error(s) and exit. + template <typename T> T &operator()(Expected<T &> &&E) const { checkError(E.takeError()); return *E; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits