diff --git a/llvm/include/llvm/Support/Error.h b/llvm/include/llvm/Support/Error.h --- a/llvm/include/llvm/Support/Error.h +++ b/llvm/include/llvm/Support/Error.h @@ -162,7 +162,7 @@ // handleErrors needs to be able to set the Checked flag. template - friend Error handleErrors(Error E, HandlerTs &&... Handlers); + friend Error handleErrors(Error E, HandlerTs &&...Handlers); // Expected 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( - reinterpret_cast(Payload) & - ~static_cast(0x1)); + return reinterpret_cast( + reinterpret_cast(Payload) & ~static_cast(0x1)); #else return Payload; #endif @@ -280,10 +279,9 @@ void setPtr(ErrorInfoBase *EI) { #if LLVM_ENABLE_ABI_BREAKING_CHECKS - Payload = reinterpret_cast( - (reinterpret_cast(EI) & - ~static_cast(0x1)) | - (reinterpret_cast(Payload) & 0x1)); + Payload = reinterpret_cast( + (reinterpret_cast(EI) & ~static_cast(0x1)) | + (reinterpret_cast(Payload) & 0x1)); #else Payload = EI; #endif @@ -299,10 +297,9 @@ void setChecked(bool V) { #if LLVM_ENABLE_ABI_BREAKING_CHECKS - Payload = reinterpret_cast( - (reinterpret_cast(Payload) & - ~static_cast(0x1)) | - (V ? 0 : 1)); + Payload = reinterpret_cast( + (reinterpret_cast(Payload) & ~static_cast(0x1)) | + (V ? 0 : 1)); #endif } @@ -333,7 +330,7 @@ /// Make a Error instance representing failure using the given error info /// type. -template Error make_error(ArgTs &&... Args) { +template Error make_error(ArgTs &&...Args) { return Error(std::make_unique(std::forward(Args)...)); } @@ -366,7 +363,7 @@ // handleErrors needs to be able to iterate the payload list of an // ErrorList. template - 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,49 @@ /// Error cannot be copied, this class replaces getError() with /// takeError(). It also adds an bool errorIsA() method for testing the /// error class type. +/// +/// Example usage of 'Expected' as a return type: +/// +/// @code{.cpp} +/// Expected myDivide(int A, int B) { +/// if (B == 0) { +/// // return an Error +/// return error("B must not be zero!"); +/// } +/// // return an integer +/// return A / B; +/// } +/// @endcode +/// +/// Checking the results of to a function returning 'Expected': +/// @code{.cpp} +/// auto Result = myDivide(X,Y); +/// if (!Result) { +/// auto Error = Result.takeError(); +/// // handle the error case here +/// } else { +/// // handle good case here +/// } +/// +/// @endcode +/// +/// Unit-testing a function returning an 'Expceted': +/// @code{.cpp} +/// TEST(MyTests, ExpectedDemo) { +/// auto Passed = myDivide(10, 5); +/// // check this call has passed, this also prints the error message +/// // if the function returns an Error +/// ASSERT_TRUE((bool)Passed) << llvm::toString(Passed.takeError()); +/// // checked the returned value +/// ASSERT_EQ(2, *Passed); +/// +/// auto Failed = myDivide(1, 0); +/// ASSERT_FALSE((bool)Failed); +/// // make sure Failed.takeError() does not get remove by the optimizer +/// std::cout << "Expected failure: " << llvm::toString(Failed.takeError()); +/// } +/// @endcode + template class LLVM_NODISCARD Expected { template friend class ExpectedAsOutParameter; template friend class Expected; @@ -462,7 +502,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 from Error success value."); @@ -764,7 +805,7 @@ /// Bar &X = cantFail(foo(false)); /// @endcode template -T& cantFail(Expected ValOrErr, const char *Msg = nullptr) { +T &cantFail(Expected ValOrErr, const char *Msg = nullptr) { if (ValOrErr) return *ValOrErr; else { @@ -785,8 +826,8 @@ /// ErrorInfo types. template class ErrorHandlerTraits - : public ErrorHandlerTraits::type::operator())> {}; + : public ErrorHandlerTraits< + decltype(&std::remove_reference::type::operator())> {}; // Specialization functions of the form 'Error (const ErrT&)'. template class ErrorHandlerTraits { @@ -888,7 +929,7 @@ template Error handleErrorImpl(std::unique_ptr Payload, - HandlerT &&Handler, HandlerTs &&... Handlers) { + HandlerT &&Handler, HandlerTs &&...Handlers) { if (ErrorHandlerTraits::appliesTo(*Payload)) return ErrorHandlerTraits::apply(std::forward(Handler), std::move(Payload)); @@ -903,7 +944,7 @@ /// or returned. If you intend to handle all errors use handleAllErrors /// (which returns void, and will abort() on unhandled errors) instead. template -Error handleErrors(Error E, HandlerTs &&... Hs) { +Error handleErrors(Error E, HandlerTs &&...Hs) { if (!E) return Error::success(); @@ -926,15 +967,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 -void handleAllErrors(Error E, HandlerTs &&... Handlers) { +void handleAllErrors(Error E, HandlerTs &&...Handlers) { cantFail(handleErrors(std::move(E), std::forward(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, then try a recovery path. /// @@ -962,7 +1001,7 @@ /// @endcode template Expected handleExpected(Expected ValOrErr, RecoveryFtor &&RecoveryPath, - HandlerTs &&... Handlers) { + HandlerTs &&...Handlers) { if (ValOrErr) return ValOrErr; @@ -1078,11 +1117,9 @@ /// Helper for Expecteds used as out-parameters. /// /// See ErrorAsOutParameter. -template -class ExpectedAsOutParameter { +template class ExpectedAsOutParameter { public: - ExpectedAsOutParameter(Expected *ValOrErr) - : ValOrErr(ValOrErr) { + ExpectedAsOutParameter(Expected *ValOrErr) : ValOrErr(ValOrErr) { if (ValOrErr) (void)!!*ValOrErr; } @@ -1126,7 +1163,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 +1237,7 @@ /// Create formatted StringError object. template 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 +1252,7 @@ template 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 +1322,7 @@ return FileError::build(F, Optional(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 +1365,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 T& operator()(Expected &&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 T &operator()(Expected &&E) const { checkError(E.takeError()); return *E; }