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 @@ -15,7 +15,6 @@ #include "llvm-c/Error.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/Config/abi-breaking.h" @@ -1015,15 +1014,17 @@ /// information to the user. void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner = {}); +namespace detail { +// Consume an Error in libSupport. +// This is used to make consumeErrors callable from code compiled with +// RTTI enabled, which would otherwise complain about missing type info for +// ErrorInfoBase. +void consumeErrorOutOfLine(Error Err); +} // end namespace detail. + /// Write all error messages (if any) in E to a string. The newline character /// is used to separate error messages. -inline std::string toString(Error E) { - SmallVector Errors; - handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) { - Errors.push_back(EI.message()); - }); - return join(Errors.begin(), Errors.end(), "\n"); -} +std::string toString(Error E); /// Consume a Error without doing anything. This method should be used /// only where an error can be considered a reasonable and expected return @@ -1033,7 +1034,8 @@ /// legitimate to do nothing while processing an "error", the error-producer /// might be more clearly refactored to return an Optional. inline void consumeError(Error Err) { - handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {}); + if (Err) + detail::consumeErrorOutOfLine(std::move(Err)); } /// Convert an Expected to an Optional without doing anything. This method @@ -1046,7 +1048,7 @@ template Optional expectedToOptional(Expected &&E) { if (E) return std::move(*E); - consumeError(E.takeError()); + detail::consumeErrorOutOfLine(E.takeError()); return None; } @@ -1056,10 +1058,11 @@ /// in a success state. Puts Err in a checked state in both cases (unlike /// Error::operator bool(), which only does this for success states). inline bool errorToBool(Error Err) { - bool IsError = static_cast(Err); - if (IsError) - consumeError(std::move(Err)); - return IsError; + if (!Err) + return false; + + detail::consumeErrorOutOfLine(std::move(Err)); + return true; } /// Helper for Errors used as out-parameters. diff --git a/llvm/lib/Support/Error.cpp b/llvm/lib/Support/Error.cpp --- a/llvm/lib/Support/Error.cpp +++ b/llvm/lib/Support/Error.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Error.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" @@ -68,6 +69,19 @@ }); } +std::string toString(Error E) { + SmallVector Errors; + handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) { + Errors.push_back(EI.message()); + }); + return join(Errors.begin(), Errors.end(), "\n"); +} + +namespace detail { +void consumeErrorOutOfLine(Error Err) { + handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {}); +} +} // namespace detail std::error_code ErrorList::convertToErrorCode() const { return std::error_code(static_cast(ErrorErrorCode::MultipleErrors),