mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +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 Error;
|
||||||
class ErrorList;
|
class ErrorList;
|
||||||
|
class Twine;
|
||||||
|
|
||||||
/// Base class for error info classes. Do not extend this directly: Extend
|
/// Base class for error info classes. Do not extend this directly: Extend
|
||||||
/// the ErrorInfo template subclass instead.
|
/// the ErrorInfo template subclass instead.
|
||||||
@ -850,24 +851,22 @@ protected:
|
|||||||
std::error_code EC;
|
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.
|
/// Helper for converting an std::error_code to a Error.
|
||||||
inline Error errorCodeToError(std::error_code EC) {
|
Error errorCodeToError(std::error_code EC);
|
||||||
if (!EC)
|
|
||||||
return Error::success();
|
|
||||||
return Error(llvm::make_unique<ECError>(ECError(EC)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper for converting an ECError to a std::error_code.
|
/// Helper for converting an ECError to a std::error_code.
|
||||||
///
|
///
|
||||||
/// This method requires that Err be Error() or an ECError, otherwise it
|
/// This method requires that Err be Error() or an ECError, otherwise it
|
||||||
/// will trigger a call to abort().
|
/// will trigger a call to abort().
|
||||||
inline std::error_code errorToErrorCode(Error Err) {
|
std::error_code errorToErrorCode(Error Err);
|
||||||
std::error_code EC;
|
|
||||||
handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
|
|
||||||
EC = EI.convertToErrorCode();
|
|
||||||
});
|
|
||||||
return EC;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert an ErrorOr<T> to an Expected<T>.
|
/// Convert an ErrorOr<T> to an Expected<T>.
|
||||||
template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) {
|
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);
|
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.
|
/// Helper for check-and-exit error handling.
|
||||||
///
|
///
|
||||||
/// For tool use only. NOT FOR USE IN LIBRARY CODE.
|
/// For tool use only. NOT FOR USE IN LIBRARY CODE.
|
||||||
|
@ -8,15 +8,19 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
|
|
||||||
|
#include "llvm/ADT/Twine.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/ManagedStatic.h"
|
#include "llvm/Support/ManagedStatic.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
enum class ErrorErrorCode {
|
enum class ErrorErrorCode : int {
|
||||||
MultipleErrors
|
MultipleErrors = 1,
|
||||||
|
UnconvertibleError
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: This class is only here to support the transition to llvm::Error. It
|
// FIXME: This class is only here to support the transition to llvm::Error. It
|
||||||
@ -30,21 +34,61 @@ namespace {
|
|||||||
switch (static_cast<ErrorErrorCode>(condition)) {
|
switch (static_cast<ErrorErrorCode>(condition)) {
|
||||||
case ErrorErrorCode::MultipleErrors:
|
case ErrorErrorCode::MultipleErrors:
|
||||||
return "Multiple errors";
|
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");
|
llvm_unreachable("Unhandled error code");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ManagedStatic<ErrorErrorCategory> ErrorErrorCat;
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
void ErrorInfoBase::anchor() {}
|
void ErrorInfoBase::anchor() {}
|
||||||
char ErrorInfoBase::ID = 0;
|
char ErrorInfoBase::ID = 0;
|
||||||
char ErrorList::ID = 0;
|
char ErrorList::ID = 0;
|
||||||
char ECError::ID = 0;
|
char ECError::ID = 0;
|
||||||
|
char StringError::ID = 0;
|
||||||
|
|
||||||
static ManagedStatic<ErrorErrorCategory> ErrorErrorCat;
|
|
||||||
|
|
||||||
std::error_code ErrorList::convertToErrorCode() const {
|
std::error_code ErrorList::convertToErrorCode() const {
|
||||||
return std::error_code(static_cast<int>(ErrorErrorCode::MultipleErrors),
|
return std::error_code(static_cast<int>(ErrorErrorCode::MultipleErrors),
|
||||||
*ErrorErrorCat);
|
*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/Support/Error.h"
|
||||||
|
|
||||||
|
#include "llvm/ADT/Twine.h"
|
||||||
#include "llvm/Support/Errc.h"
|
#include "llvm/Support/Errc.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
@ -376,6 +378,20 @@ TEST(Error, CatchErrorFromHandler) {
|
|||||||
<< "Failed to handle Error returned from handleErrors.";
|
<< "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 that the ExitOnError utility works as expected.
|
||||||
TEST(Error, ExitOnError) {
|
TEST(Error, ExitOnError) {
|
||||||
ExitOnError ExitOnErr;
|
ExitOnError ExitOnErr;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user