[llvm] r270948 - [Support] Add a StringError convenience class to Error.h
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Thu May 26 18:37:34 PDT 2016
Author: lhames
Date: Thu May 26 20:37:32 2016
New Revision: 270948
URL: http://llvm.org/viewvc/llvm-project?rev=270948&view=rev
Log:
[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.
Modified:
llvm/trunk/include/llvm/Support/Error.h
llvm/trunk/lib/Support/Error.cpp
llvm/trunk/unittests/Support/ErrorTest.cpp
Modified: llvm/trunk/include/llvm/Support/Error.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Error.h?rev=270948&r1=270947&r2=270948&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/Error.h (original)
+++ llvm/trunk/include/llvm/Support/Error.h Thu May 26 20:37:32 2016
@@ -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> expecte
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.
Modified: llvm/trunk/lib/Support/Error.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Error.cpp?rev=270948&r1=270947&r2=270948&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Error.cpp (original)
+++ llvm/trunk/lib/Support/Error.cpp Thu May 26 20:37:32 2016
@@ -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;
+}
+
+}
Modified: llvm/trunk/unittests/Support/ErrorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/ErrorTest.cpp?rev=270948&r1=270947&r2=270948&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/ErrorTest.cpp (original)
+++ llvm/trunk/unittests/Support/ErrorTest.cpp Thu May 26 20:37:32 2016
@@ -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;
More information about the llvm-commits
mailing list