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