106f32e7eSjoerg //===----- lib/Support/Error.cpp - Error and associated utilities ---------===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg
906f32e7eSjoerg #include "llvm/Support/Error.h"
1006f32e7eSjoerg #include "llvm/ADT/Twine.h"
1106f32e7eSjoerg #include "llvm/Support/ErrorHandling.h"
1206f32e7eSjoerg #include "llvm/Support/ManagedStatic.h"
1306f32e7eSjoerg #include <system_error>
1406f32e7eSjoerg
1506f32e7eSjoerg using namespace llvm;
1606f32e7eSjoerg
1706f32e7eSjoerg namespace {
1806f32e7eSjoerg
1906f32e7eSjoerg enum class ErrorErrorCode : int {
2006f32e7eSjoerg MultipleErrors = 1,
2106f32e7eSjoerg FileError,
2206f32e7eSjoerg InconvertibleError
2306f32e7eSjoerg };
2406f32e7eSjoerg
2506f32e7eSjoerg // FIXME: This class is only here to support the transition to llvm::Error. It
2606f32e7eSjoerg // will be removed once this transition is complete. Clients should prefer to
2706f32e7eSjoerg // deal with the Error value directly, rather than converting to error_code.
2806f32e7eSjoerg class ErrorErrorCategory : public std::error_category {
2906f32e7eSjoerg public:
name() const3006f32e7eSjoerg const char *name() const noexcept override { return "Error"; }
3106f32e7eSjoerg
message(int condition) const3206f32e7eSjoerg std::string message(int condition) const override {
3306f32e7eSjoerg switch (static_cast<ErrorErrorCode>(condition)) {
3406f32e7eSjoerg case ErrorErrorCode::MultipleErrors:
3506f32e7eSjoerg return "Multiple errors";
3606f32e7eSjoerg case ErrorErrorCode::InconvertibleError:
3706f32e7eSjoerg return "Inconvertible error value. An error has occurred that could "
3806f32e7eSjoerg "not be converted to a known std::error_code. Please file a "
3906f32e7eSjoerg "bug.";
4006f32e7eSjoerg case ErrorErrorCode::FileError:
4106f32e7eSjoerg return "A file error occurred.";
4206f32e7eSjoerg }
4306f32e7eSjoerg llvm_unreachable("Unhandled error code");
4406f32e7eSjoerg }
4506f32e7eSjoerg };
4606f32e7eSjoerg
4706f32e7eSjoerg }
4806f32e7eSjoerg
4906f32e7eSjoerg static ManagedStatic<ErrorErrorCategory> ErrorErrorCat;
5006f32e7eSjoerg
5106f32e7eSjoerg namespace llvm {
5206f32e7eSjoerg
anchor()5306f32e7eSjoerg void ErrorInfoBase::anchor() {}
5406f32e7eSjoerg char ErrorInfoBase::ID = 0;
5506f32e7eSjoerg char ErrorList::ID = 0;
anchor()5606f32e7eSjoerg void ECError::anchor() {}
5706f32e7eSjoerg char ECError::ID = 0;
5806f32e7eSjoerg char StringError::ID = 0;
5906f32e7eSjoerg char FileError::ID = 0;
6006f32e7eSjoerg
logAllUnhandledErrors(Error E,raw_ostream & OS,Twine ErrorBanner)6106f32e7eSjoerg void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner) {
6206f32e7eSjoerg if (!E)
6306f32e7eSjoerg return;
6406f32e7eSjoerg OS << ErrorBanner;
6506f32e7eSjoerg handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) {
6606f32e7eSjoerg EI.log(OS);
6706f32e7eSjoerg OS << "\n";
6806f32e7eSjoerg });
6906f32e7eSjoerg }
7006f32e7eSjoerg
7106f32e7eSjoerg
convertToErrorCode() const7206f32e7eSjoerg std::error_code ErrorList::convertToErrorCode() const {
7306f32e7eSjoerg return std::error_code(static_cast<int>(ErrorErrorCode::MultipleErrors),
7406f32e7eSjoerg *ErrorErrorCat);
7506f32e7eSjoerg }
7606f32e7eSjoerg
inconvertibleErrorCode()7706f32e7eSjoerg std::error_code inconvertibleErrorCode() {
7806f32e7eSjoerg return std::error_code(static_cast<int>(ErrorErrorCode::InconvertibleError),
7906f32e7eSjoerg *ErrorErrorCat);
8006f32e7eSjoerg }
8106f32e7eSjoerg
convertToErrorCode() const8206f32e7eSjoerg std::error_code FileError::convertToErrorCode() const {
8306f32e7eSjoerg return std::error_code(static_cast<int>(ErrorErrorCode::FileError),
8406f32e7eSjoerg *ErrorErrorCat);
8506f32e7eSjoerg }
8606f32e7eSjoerg
errorCodeToError(std::error_code EC)8706f32e7eSjoerg Error errorCodeToError(std::error_code EC) {
8806f32e7eSjoerg if (!EC)
8906f32e7eSjoerg return Error::success();
9006f32e7eSjoerg return Error(std::make_unique<ECError>(ECError(EC)));
9106f32e7eSjoerg }
9206f32e7eSjoerg
errorToErrorCode(Error Err)9306f32e7eSjoerg std::error_code errorToErrorCode(Error Err) {
9406f32e7eSjoerg std::error_code EC;
9506f32e7eSjoerg handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
9606f32e7eSjoerg EC = EI.convertToErrorCode();
9706f32e7eSjoerg });
9806f32e7eSjoerg if (EC == inconvertibleErrorCode())
9906f32e7eSjoerg report_fatal_error(EC.message());
10006f32e7eSjoerg return EC;
10106f32e7eSjoerg }
10206f32e7eSjoerg
10306f32e7eSjoerg #if LLVM_ENABLE_ABI_BREAKING_CHECKS
fatalUncheckedError() const10406f32e7eSjoerg void Error::fatalUncheckedError() const {
10506f32e7eSjoerg dbgs() << "Program aborted due to an unhandled Error:\n";
106*da58b97aSjoerg if (getPtr()) {
10706f32e7eSjoerg getPtr()->log(dbgs());
108*da58b97aSjoerg dbgs() << "\n";
109*da58b97aSjoerg }else
11006f32e7eSjoerg dbgs() << "Error value was Success. (Note: Success values must still be "
11106f32e7eSjoerg "checked prior to being destroyed).\n";
11206f32e7eSjoerg abort();
11306f32e7eSjoerg }
11406f32e7eSjoerg #endif
11506f32e7eSjoerg
StringError(std::error_code EC,const Twine & S)11606f32e7eSjoerg StringError::StringError(std::error_code EC, const Twine &S)
11706f32e7eSjoerg : Msg(S.str()), EC(EC) {}
11806f32e7eSjoerg
StringError(const Twine & S,std::error_code EC)11906f32e7eSjoerg StringError::StringError(const Twine &S, std::error_code EC)
12006f32e7eSjoerg : Msg(S.str()), EC(EC), PrintMsgOnly(true) {}
12106f32e7eSjoerg
log(raw_ostream & OS) const12206f32e7eSjoerg void StringError::log(raw_ostream &OS) const {
12306f32e7eSjoerg if (PrintMsgOnly) {
12406f32e7eSjoerg OS << Msg;
12506f32e7eSjoerg } else {
12606f32e7eSjoerg OS << EC.message();
12706f32e7eSjoerg if (!Msg.empty())
12806f32e7eSjoerg OS << (" " + Msg);
12906f32e7eSjoerg }
13006f32e7eSjoerg }
13106f32e7eSjoerg
convertToErrorCode() const13206f32e7eSjoerg std::error_code StringError::convertToErrorCode() const {
13306f32e7eSjoerg return EC;
13406f32e7eSjoerg }
13506f32e7eSjoerg
createStringError(std::error_code EC,char const * Msg)13606f32e7eSjoerg Error createStringError(std::error_code EC, char const *Msg) {
13706f32e7eSjoerg return make_error<StringError>(Msg, EC);
13806f32e7eSjoerg }
13906f32e7eSjoerg
report_fatal_error(Error Err,bool GenCrashDiag)14006f32e7eSjoerg void report_fatal_error(Error Err, bool GenCrashDiag) {
14106f32e7eSjoerg assert(Err && "report_fatal_error called with success value");
14206f32e7eSjoerg std::string ErrMsg;
14306f32e7eSjoerg {
14406f32e7eSjoerg raw_string_ostream ErrStream(ErrMsg);
14506f32e7eSjoerg logAllUnhandledErrors(std::move(Err), ErrStream);
14606f32e7eSjoerg }
14706f32e7eSjoerg report_fatal_error(ErrMsg);
14806f32e7eSjoerg }
14906f32e7eSjoerg
15006f32e7eSjoerg } // end namespace llvm
15106f32e7eSjoerg
LLVMGetErrorTypeId(LLVMErrorRef Err)15206f32e7eSjoerg LLVMErrorTypeId LLVMGetErrorTypeId(LLVMErrorRef Err) {
15306f32e7eSjoerg return reinterpret_cast<ErrorInfoBase *>(Err)->dynamicClassID();
15406f32e7eSjoerg }
15506f32e7eSjoerg
LLVMConsumeError(LLVMErrorRef Err)15606f32e7eSjoerg void LLVMConsumeError(LLVMErrorRef Err) { consumeError(unwrap(Err)); }
15706f32e7eSjoerg
LLVMGetErrorMessage(LLVMErrorRef Err)15806f32e7eSjoerg char *LLVMGetErrorMessage(LLVMErrorRef Err) {
15906f32e7eSjoerg std::string Tmp = toString(unwrap(Err));
16006f32e7eSjoerg char *ErrMsg = new char[Tmp.size() + 1];
16106f32e7eSjoerg memcpy(ErrMsg, Tmp.data(), Tmp.size());
16206f32e7eSjoerg ErrMsg[Tmp.size()] = '\0';
16306f32e7eSjoerg return ErrMsg;
16406f32e7eSjoerg }
16506f32e7eSjoerg
LLVMDisposeErrorMessage(char * ErrMsg)16606f32e7eSjoerg void LLVMDisposeErrorMessage(char *ErrMsg) { delete[] ErrMsg; }
16706f32e7eSjoerg
LLVMGetStringErrorTypeId()16806f32e7eSjoerg LLVMErrorTypeId LLVMGetStringErrorTypeId() {
16906f32e7eSjoerg return reinterpret_cast<void *>(&StringError::ID);
17006f32e7eSjoerg }
171*da58b97aSjoerg
LLVMCreateStringError(const char * ErrMsg)172*da58b97aSjoerg LLVMErrorRef LLVMCreateStringError(const char *ErrMsg) {
173*da58b97aSjoerg return wrap(make_error<StringError>(ErrMsg, inconvertibleErrorCode()));
174*da58b97aSjoerg }
175