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 @@ -80,8 +80,11 @@ } std::error_code FileError::convertToErrorCode() const { - return std::error_code(static_cast(ErrorErrorCode::FileError), - *ErrorErrorCat); + std::error_code NestedEC = Err->convertToErrorCode(); + if (NestedEC == inconvertibleErrorCode()) + return std::error_code(static_cast(ErrorErrorCode::FileError), + *ErrorErrorCat); + return NestedEC; } Error errorCodeToError(std::error_code EC) { diff --git a/llvm/unittests/Support/ErrorTest.cpp b/llvm/unittests/Support/ErrorTest.cpp --- a/llvm/unittests/Support/ErrorTest.cpp +++ b/llvm/unittests/Support/ErrorTest.cpp @@ -963,6 +963,33 @@ }); } +TEST(Error, FileErrorErrorCode) { + for (std::error_code EC : { + make_error_code(std::errc::not_supported), + make_error_code(std::errc::invalid_argument), + make_error_code(std::errc::no_such_file_or_directory), + }) { + EXPECT_EQ(EC, errorToErrorCode( + createFileError("file.bin", EC))); + EXPECT_EQ(EC, errorToErrorCode( + createFileError("file.bin", /*Line=*/5, EC))); + EXPECT_EQ(EC, errorToErrorCode( + createFileError("file.bin", errorCodeToError(EC)))); + EXPECT_EQ(EC, errorToErrorCode( + createFileError("file.bin", /*Line=*/5, errorCodeToError(EC)))); + } + + // inconvertibleErrorCode() should be wrapped to avoid a fatal error. + EXPECT_EQ( + "A file error occurred.", + errorToErrorCode(createFileError("file.bin", inconvertibleErrorCode())) + .message()); + EXPECT_EQ( + "A file error occurred.", + errorToErrorCode(createFileError("file.bin", /*Line=*/5, inconvertibleErrorCode())) + .message()); +} + enum class test_error_code { unspecified = 1, error_1,