//===----- lib/Support/Error.cpp - Error and associated utilities ---------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "llvm/Support/Error.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" #include using namespace llvm; namespace { enum class ErrorErrorCode : int { MultipleErrors = 1, InconvertibleError }; // FIXME: This class is only here to support the transition to llvm::Error. It // will be removed once this transition is complete. Clients should prefer to // deal with the Error value directly, rather than converting to error_code. class ErrorErrorCategory : public std::error_category { public: const char *name() const noexcept override { return "Error"; } std::string message(int condition) const override { switch (static_cast(condition)) { case ErrorErrorCode::MultipleErrors: return "Multiple errors"; case ErrorErrorCode::InconvertibleError: return "Inconvertible 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 ErrorErrorCat; namespace llvm { void ErrorInfoBase::anchor() {} char ErrorInfoBase::ID = 0; char ErrorList::ID = 0; char ECError::ID = 0; char StringError::ID = 0; void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner) { if (!E) return; OS << ErrorBanner; handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) { EI.log(OS); OS << "\n"; }); } std::error_code ErrorList::convertToErrorCode() const { return std::error_code(static_cast(ErrorErrorCode::MultipleErrors), *ErrorErrorCat); } std::error_code inconvertibleErrorCode() { return std::error_code(static_cast(ErrorErrorCode::InconvertibleError), *ErrorErrorCat); } Error errorCodeToError(std::error_code EC) { if (!EC) return Error::success(); return Error(llvm::make_unique(ECError(EC))); } std::error_code errorToErrorCode(Error Err) { std::error_code EC; handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) { EC = EI.convertToErrorCode(); }); if (EC == inconvertibleErrorCode()) report_fatal_error(EC.message()); return EC; } #if LLVM_ENABLE_ABI_BREAKING_CHECKS void Error::fatalUncheckedError() const { dbgs() << "Program aborted due to an unhandled Error:\n"; if (getPtr()) getPtr()->log(dbgs()); else dbgs() << "Error value was Success. (Note: Success values must still be " "checked prior to being destroyed).\n"; abort(); } #endif 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; } void report_fatal_error(Error Err, bool GenCrashDiag) { assert(Err && "report_fatal_error called with success value"); std::string ErrMsg; { raw_string_ostream ErrStream(ErrMsg); logAllUnhandledErrors(std::move(Err), ErrStream, ""); } report_fatal_error(ErrMsg); } } #ifndef _MSC_VER namespace llvm { // One of these two variables will be referenced by a symbol defined in // llvm-config.h. We provide a link-time (or load time for DSO) failure when // there is a mismatch in the build configuration of the API client and LLVM. #if LLVM_ENABLE_ABI_BREAKING_CHECKS int EnableABIBreakingChecks; #else int DisableABIBreakingChecks; #endif } // end namespace llvm #endif