brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.1 KiB · d168b46 Raw
215 lines · cpp
1//===----- lib/Support/Error.cpp - Error and associated utilities ---------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Support/Error.h"10#include "llvm/ADT/SmallVector.h"11#include "llvm/ADT/StringExtras.h"12#include "llvm/ADT/Twine.h"13#include "llvm/Support/ErrorHandling.h"14#include <system_error>15 16using namespace llvm;17 18namespace {19 20  enum class ErrorErrorCode : int {21    MultipleErrors = 1,22    FileError,23    InconvertibleError24  };25 26  // FIXME: This class is only here to support the transition to llvm::Error. It27  // will be removed once this transition is complete. Clients should prefer to28  // deal with the Error value directly, rather than converting to error_code.29  class ErrorErrorCategory : public std::error_category {30  public:31    const char *name() const noexcept override { return "Error"; }32 33    std::string message(int condition) const override {34      switch (static_cast<ErrorErrorCode>(condition)) {35      case ErrorErrorCode::MultipleErrors:36        return "Multiple errors";37      case ErrorErrorCode::InconvertibleError:38        return "Inconvertible error value. An error has occurred that could "39               "not be converted to a known std::error_code. Please file a "40               "bug.";41      case ErrorErrorCode::FileError:42          return "A file error occurred.";43      }44      llvm_unreachable("Unhandled error code");45    }46  };47 48}49 50ErrorErrorCategory &getErrorErrorCat() {51  static ErrorErrorCategory ErrorErrorCat;52  return ErrorErrorCat;53}54 55namespace llvm {56 57void ErrorInfoBase::anchor() {}58char ErrorInfoBase::ID = 0;59char ErrorList::ID = 0;60void ECError::anchor() {}61char ECError::ID = 0;62char StringError::ID = 0;63char FileError::ID = 0;64 65void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner) {66  if (!E)67    return;68  OS << ErrorBanner;69  handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) {70    EI.log(OS);71    OS << "\n";72  });73}74 75/// Write all error messages (if any) in E to a string. The newline character76/// is used to separate error messages.77std::string toString(Error E) {78  SmallVector<std::string, 2> Errors;79  handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) {80    Errors.push_back(EI.message());81  });82  return join(Errors.begin(), Errors.end(), "\n");83}84 85std::string toStringWithoutConsuming(const Error &E) {86  SmallVector<std::string, 2> Errors;87  visitErrors(E, [&Errors](const ErrorInfoBase &EI) {88    Errors.push_back(EI.message());89  });90  return join(Errors.begin(), Errors.end(), "\n");91}92 93std::error_code ErrorList::convertToErrorCode() const {94  return std::error_code(static_cast<int>(ErrorErrorCode::MultipleErrors),95                         getErrorErrorCat());96}97 98std::error_code inconvertibleErrorCode() {99  return std::error_code(static_cast<int>(ErrorErrorCode::InconvertibleError),100                         getErrorErrorCat());101}102 103std::error_code FileError::convertToErrorCode() const {104  std::error_code NestedEC = Err->convertToErrorCode();105  if (NestedEC == inconvertibleErrorCode())106    return std::error_code(static_cast<int>(ErrorErrorCode::FileError),107                           getErrorErrorCat());108  return NestedEC;109}110 111Error errorCodeToError(std::error_code EC) {112  if (!EC)113    return Error::success();114  return Error(std::make_unique<ECError>(ECError(EC)));115}116 117std::error_code errorToErrorCode(Error Err) {118  std::error_code EC;119  handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {120    EC = EI.convertToErrorCode();121  });122  if (EC == inconvertibleErrorCode())123    report_fatal_error(Twine(EC.message()));124  return EC;125}126 127#if LLVM_ENABLE_ABI_BREAKING_CHECKS128void Error::fatalUncheckedError() const {129  dbgs() << "Program aborted due to an unhandled Error:\n";130  if (getPtr()) {131    getPtr()->log(dbgs());132    dbgs() << "\n";133  }else134    dbgs() << "Error value was Success. (Note: Success values must still be "135              "checked prior to being destroyed).\n";136  abort();137}138#endif139 140StringError::StringError(std::error_code EC, const Twine &S)141    : Msg(S.str()), EC(EC) {}142 143StringError::StringError(const Twine &S, std::error_code EC)144    : Msg(S.str()), EC(EC), PrintMsgOnly(true) {}145 146StringError::StringError(std::string &&S, std::error_code EC, bool PrintMsgOnly)147    : Msg(S), EC(EC), PrintMsgOnly(PrintMsgOnly) {}148 149void StringError::log(raw_ostream &OS) const {150  if (PrintMsgOnly) {151    OS << Msg;152  } else {153    OS << EC.message();154    if (!Msg.empty())155      OS << (" " + Msg);156  }157}158 159std::error_code StringError::convertToErrorCode() const {160  return EC;161}162 163Error createStringError(std::string &&Msg, std::error_code EC) {164  return make_error<StringError>(Msg, EC);165}166 167void report_fatal_error(Error Err, bool GenCrashDiag) {168  assert(Err && "report_fatal_error called with success value");169  std::string ErrMsg;170  {171    raw_string_ostream ErrStream(ErrMsg);172    logAllUnhandledErrors(std::move(Err), ErrStream);173  }174  report_fatal_error(Twine(ErrMsg), GenCrashDiag);175}176 177void reportFatalInternalError(Error Err) {178  report_fatal_error(std::move(Err), /*GenCrashDiag=*/true);179}180void reportFatalUsageError(Error Err) {181  report_fatal_error(std::move(Err), /*GenCrashDiag=*/false);182}183 184} // end namespace llvm185 186LLVMErrorTypeId LLVMGetErrorTypeId(LLVMErrorRef Err) {187  return reinterpret_cast<ErrorInfoBase *>(Err)->dynamicClassID();188}189 190void LLVMConsumeError(LLVMErrorRef Err) { consumeError(unwrap(Err)); }191 192 193 194void LLVMCantFail(LLVMErrorRef Err) {195  cantFail(unwrap(Err));196}197 198char *LLVMGetErrorMessage(LLVMErrorRef Err) {199  std::string Tmp = toString(unwrap(Err));200  char *ErrMsg = new char[Tmp.size() + 1];201  memcpy(ErrMsg, Tmp.data(), Tmp.size());202  ErrMsg[Tmp.size()] = '\0';203  return ErrMsg;204}205 206void LLVMDisposeErrorMessage(char *ErrMsg) { delete[] ErrMsg; }207 208LLVMErrorTypeId LLVMGetStringErrorTypeId() {209  return reinterpret_cast<void *>(&StringError::ID);210}211 212LLVMErrorRef LLVMCreateStringError(const char *ErrMsg) {213  return wrap(make_error<StringError>(ErrMsg, inconvertibleErrorCode()));214}215