1//===----- lib/Support/Error.cpp - Error and associated utilities ---------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/Support/Error.h"
11#include "llvm/ADT/Twine.h"
12#include "llvm/Support/ErrorHandling.h"
13#include "llvm/Support/ManagedStatic.h"
14
15
16using namespace llvm;
17
18namespace {
19
20  enum class ErrorErrorCode : int {
21    MultipleErrors = 1,
22    InconvertibleError
23  };
24
25  // FIXME: This class is only here to support the transition to llvm::Error. It
26  // will be removed once this transition is complete. Clients should prefer to
27  // deal with the Error value directly, rather than converting to error_code.
28  class ErrorErrorCategory : public std::error_category {
29  public:
30    const char *name() const LLVM_NOEXCEPT override { return "Error"; }
31
32    std::string message(int condition) const override {
33      switch (static_cast<ErrorErrorCode>(condition)) {
34      case ErrorErrorCode::MultipleErrors:
35        return "Multiple errors";
36      case ErrorErrorCode::InconvertibleError:
37        return "Inconvertible error value. An error has occurred that could "
38               "not be converted to a known std::error_code. Please file a "
39               "bug.";
40      }
41      llvm_unreachable("Unhandled error code");
42    }
43  };
44
45}
46
47static ManagedStatic<ErrorErrorCategory> ErrorErrorCat;
48
49namespace llvm {
50
51void ErrorInfoBase::anchor() {}
52char ErrorInfoBase::ID = 0;
53char ErrorList::ID = 0;
54char ECError::ID = 0;
55char StringError::ID = 0;
56
57void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner) {
58  if (!E)
59    return;
60  OS << ErrorBanner;
61  handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) {
62    EI.log(OS);
63    OS << "\n";
64  });
65}
66
67
68std::error_code ErrorList::convertToErrorCode() const {
69  return std::error_code(static_cast<int>(ErrorErrorCode::MultipleErrors),
70                         *ErrorErrorCat);
71}
72
73std::error_code inconvertibleErrorCode() {
74  return std::error_code(static_cast<int>(ErrorErrorCode::InconvertibleError),
75                         *ErrorErrorCat);
76}
77
78Error errorCodeToError(std::error_code EC) {
79  if (!EC)
80    return Error::success();
81  return Error(llvm::make_unique<ECError>(ECError(EC)));
82}
83
84std::error_code errorToErrorCode(Error Err) {
85  std::error_code EC;
86  handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
87    EC = EI.convertToErrorCode();
88  });
89  if (EC == inconvertibleErrorCode())
90    report_fatal_error(EC.message());
91  return EC;
92}
93
94StringError::StringError(const Twine &S, std::error_code EC)
95    : Msg(S.str()), EC(EC) {}
96
97void StringError::log(raw_ostream &OS) const { OS << Msg; }
98
99std::error_code StringError::convertToErrorCode() const {
100  return EC;
101}
102
103void report_fatal_error(Error Err, bool GenCrashDiag) {
104  assert(Err && "report_fatal_error called with success value");
105  std::string ErrMsg;
106  {
107    raw_string_ostream ErrStream(ErrMsg);
108    logAllUnhandledErrors(std::move(Err), ErrStream, "");
109  }
110  report_fatal_error(ErrMsg);
111}
112
113}
114