mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[Support] Add a StringError convenience class to Error.h
StringError can be used to represent Errors that aren't recoverable based on the error type, but that have a useful error message that can be reported to the user or logged. llvm-svn: 270948
This commit is contained in:
parent
902fe15d1a
commit
776aaf18f4
@ -26,6 +26,7 @@ namespace llvm {
|
||||
|
||||
class Error;
|
||||
class ErrorList;
|
||||
class Twine;
|
||||
|
||||
/// Base class for error info classes. Do not extend this directly: Extend
|
||||
/// the ErrorInfo template subclass instead.
|
||||
@ -850,24 +851,22 @@ protected:
|
||||
std::error_code EC;
|
||||
};
|
||||
|
||||
/// The value returned by this function can be returned from convertToErrorCode
|
||||
/// for Error values where no sensible translation to std::error_code exists.
|
||||
/// 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).
|
||||
std::error_code unconvertibleErrorCode();
|
||||
|
||||
/// Helper for converting an std::error_code to a Error.
|
||||
inline Error errorCodeToError(std::error_code EC) {
|
||||
if (!EC)
|
||||
return Error::success();
|
||||
return Error(llvm::make_unique<ECError>(ECError(EC)));
|
||||
}
|
||||
Error errorCodeToError(std::error_code EC);
|
||||
|
||||
/// Helper for converting an ECError to a std::error_code.
|
||||
///
|
||||
/// This method requires that Err be Error() or an ECError, otherwise it
|
||||
/// will trigger a call to abort().
|
||||
inline std::error_code errorToErrorCode(Error Err) {
|
||||
std::error_code EC;
|
||||
handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
|
||||
EC = EI.convertToErrorCode();
|
||||
});
|
||||
return EC;
|
||||
}
|
||||
std::error_code errorToErrorCode(Error Err);
|
||||
|
||||
/// Convert an ErrorOr<T> to an Expected<T>.
|
||||
template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) {
|
||||
@ -883,6 +882,23 @@ template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) {
|
||||
return std::move(*E);
|
||||
}
|
||||
|
||||
/// This class wraps a string in an Error.
|
||||
///
|
||||
/// StringError is useful in cases where the client is not expected to be able
|
||||
/// to consume the specific error message programmatically (for example, if the
|
||||
/// error message is to be presented to the user). It cannot be converted to a
|
||||
/// std::error_code.
|
||||
class StringError : public ErrorInfo<StringError> {
|
||||
public:
|
||||
static char ID;
|
||||
StringError(const Twine &S, std::error_code EC);
|
||||
void log(raw_ostream &OS) const override;
|
||||
std::error_code convertToErrorCode() const override;
|
||||
private:
|
||||
std::string Msg;
|
||||
std::error_code EC;
|
||||
};
|
||||
|
||||
/// Helper for check-and-exit error handling.
|
||||
///
|
||||
/// For tool use only. NOT FOR USE IN LIBRARY CODE.
|
||||
|
@ -8,15 +8,19 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
enum class ErrorErrorCode {
|
||||
MultipleErrors
|
||||
enum class ErrorErrorCode : int {
|
||||
MultipleErrors = 1,
|
||||
UnconvertibleError
|
||||
};
|
||||
|
||||
// FIXME: This class is only here to support the transition to llvm::Error. It
|
||||
@ -30,21 +34,61 @@ namespace {
|
||||
switch (static_cast<ErrorErrorCode>(condition)) {
|
||||
case ErrorErrorCode::MultipleErrors:
|
||||
return "Multiple errors";
|
||||
};
|
||||
case ErrorErrorCode::UnconvertibleError:
|
||||
return "Unconvertible error value. An error has occurred that could "
|
||||
"not be converted to a known std::error_code. Please file a "
|
||||
"bug.";
|
||||
}
|
||||
llvm_unreachable("Unhandled error code");
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static ManagedStatic<ErrorErrorCategory> ErrorErrorCat;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void ErrorInfoBase::anchor() {}
|
||||
char ErrorInfoBase::ID = 0;
|
||||
char ErrorList::ID = 0;
|
||||
char ECError::ID = 0;
|
||||
char StringError::ID = 0;
|
||||
|
||||
static ManagedStatic<ErrorErrorCategory> ErrorErrorCat;
|
||||
|
||||
std::error_code ErrorList::convertToErrorCode() const {
|
||||
return std::error_code(static_cast<int>(ErrorErrorCode::MultipleErrors),
|
||||
*ErrorErrorCat);
|
||||
}
|
||||
|
||||
std::error_code unconvertibleErrorCode() {
|
||||
return std::error_code(static_cast<int>(ErrorErrorCode::UnconvertibleError),
|
||||
*ErrorErrorCat);
|
||||
}
|
||||
|
||||
Error errorCodeToError(std::error_code EC) {
|
||||
if (!EC)
|
||||
return Error::success();
|
||||
return Error(llvm::make_unique<ECError>(ECError(EC)));
|
||||
}
|
||||
|
||||
std::error_code errorToErrorCode(Error Err) {
|
||||
std::error_code EC;
|
||||
handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
|
||||
EC = EI.convertToErrorCode();
|
||||
});
|
||||
if (EC == unconvertibleErrorCode())
|
||||
report_fatal_error(EC.message());
|
||||
return EC;
|
||||
}
|
||||
|
||||
StringError::StringError(const Twine &S, std::error_code EC)
|
||||
: Msg(S.str()), EC(EC) {}
|
||||
|
||||
void StringError::log(raw_ostream &OS) const { OS << Msg; }
|
||||
|
||||
std::error_code StringError::convertToErrorCode() const {
|
||||
return EC;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "gtest/gtest.h"
|
||||
@ -376,6 +378,20 @@ TEST(Error, CatchErrorFromHandler) {
|
||||
<< "Failed to handle Error returned from handleErrors.";
|
||||
}
|
||||
|
||||
TEST(Error, StringError) {
|
||||
std::string Msg;
|
||||
raw_string_ostream S(Msg);
|
||||
logAllUnhandledErrors(make_error<StringError>("foo" + Twine(42),
|
||||
unconvertibleErrorCode()),
|
||||
S, "");
|
||||
EXPECT_EQ(S.str(), "foo42\n") << "Unexpected StringError log result";
|
||||
|
||||
auto EC =
|
||||
errorToErrorCode(make_error<StringError>("", errc::invalid_argument));
|
||||
EXPECT_EQ(EC, errc::invalid_argument)
|
||||
<< "Failed to convert StringError to error_code.";
|
||||
}
|
||||
|
||||
// Test that the ExitOnError utility works as expected.
|
||||
TEST(Error, ExitOnError) {
|
||||
ExitOnError ExitOnErr;
|
||||
|
Loading…
x
Reference in New Issue
Block a user