Line data Source code
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 : #include <system_error>
15 :
16 : using namespace llvm;
17 :
18 : namespace {
19 :
20 : enum class ErrorErrorCode : int {
21 : MultipleErrors = 1,
22 : FileError,
23 : InconvertibleError
24 : };
25 :
26 : // FIXME: This class is only here to support the transition to llvm::Error. It
27 : // will be removed once this transition is complete. Clients should prefer to
28 : // deal with the Error value directly, rather than converting to error_code.
29 4644 : class ErrorErrorCategory : public std::error_category {
30 : public:
31 0 : const char *name() const noexcept override { return "Error"; }
32 :
33 0 : std::string message(int condition) const override {
34 0 : switch (static_cast<ErrorErrorCode>(condition)) {
35 : case ErrorErrorCode::MultipleErrors:
36 0 : 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 0 : "bug.";
41 : case ErrorErrorCode::FileError:
42 0 : return "A file error occurred.";
43 : }
44 0 : llvm_unreachable("Unhandled error code");
45 : }
46 : };
47 :
48 : }
49 :
50 : static ManagedStatic<ErrorErrorCategory> ErrorErrorCat;
51 :
52 : namespace llvm {
53 :
54 0 : void ErrorInfoBase::anchor() {}
55 : char ErrorInfoBase::ID = 0;
56 : char ErrorList::ID = 0;
57 : char ECError::ID = 0;
58 : char StringError::ID = 0;
59 : char FileError::ID = 0;
60 :
61 1252 : void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner) {
62 1252 : if (!E)
63 : return;
64 : OS << ErrorBanner;
65 1389 : handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) {
66 : EI.log(OS);
67 : OS << "\n";
68 : });
69 : }
70 :
71 :
72 0 : std::error_code ErrorList::convertToErrorCode() const {
73 0 : return std::error_code(static_cast<int>(ErrorErrorCode::MultipleErrors),
74 0 : *ErrorErrorCat);
75 : }
76 :
77 36247 : std::error_code inconvertibleErrorCode() {
78 36247 : return std::error_code(static_cast<int>(ErrorErrorCode::InconvertibleError),
79 36247 : *ErrorErrorCat);
80 : }
81 :
82 0 : std::error_code FileError::convertToErrorCode() const {
83 0 : return std::error_code(static_cast<int>(ErrorErrorCode::FileError),
84 0 : *ErrorErrorCat);
85 : }
86 :
87 10412 : Error errorCodeToError(std::error_code EC) {
88 10412 : if (!EC)
89 : return Error::success();
90 703 : return Error(llvm::make_unique<ECError>(ECError(EC)));
91 : }
92 :
93 4932 : std::error_code errorToErrorCode(Error Err) {
94 : std::error_code EC;
95 9864 : handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
96 56 : EC = EI.convertToErrorCode();
97 : });
98 9864 : if (EC == inconvertibleErrorCode())
99 0 : report_fatal_error(EC.message());
100 4932 : return EC;
101 : }
102 :
103 : #if LLVM_ENABLE_ABI_BREAKING_CHECKS
104 : void Error::fatalUncheckedError() const {
105 : dbgs() << "Program aborted due to an unhandled Error:\n";
106 : if (getPtr())
107 : getPtr()->log(dbgs());
108 : else
109 : dbgs() << "Error value was Success. (Note: Success values must still be "
110 : "checked prior to being destroyed).\n";
111 : abort();
112 : }
113 : #endif
114 :
115 20 : StringError::StringError(std::error_code EC, const Twine &S)
116 20 : : Msg(S.str()), EC(EC) {}
117 :
118 31905 : StringError::StringError(const Twine &S, std::error_code EC)
119 31905 : : Msg(S.str()), EC(EC), PrintMsgOnly(true) {}
120 :
121 3064 : void StringError::log(raw_ostream &OS) const {
122 3064 : if (PrintMsgOnly) {
123 : OS << Msg;
124 : } else {
125 17 : OS << EC.message();
126 17 : if (!Msg.empty())
127 22 : OS << (" " + Msg);
128 : }
129 3064 : }
130 :
131 46 : std::error_code StringError::convertToErrorCode() const {
132 46 : return EC;
133 : }
134 :
135 49 : Error createStringError(std::error_code EC, char const *Msg) {
136 49 : return make_error<StringError>(Msg, EC);
137 : }
138 :
139 0 : void report_fatal_error(Error Err, bool GenCrashDiag) {
140 : assert(Err && "report_fatal_error called with success value");
141 : std::string ErrMsg;
142 : {
143 0 : raw_string_ostream ErrStream(ErrMsg);
144 0 : logAllUnhandledErrors(std::move(Err), ErrStream, "");
145 : }
146 0 : report_fatal_error(ErrMsg);
147 : }
148 :
149 : } // end namespace llvm
150 :
151 1 : LLVMErrorTypeId LLVMGetErrorTypeId(LLVMErrorRef Err) {
152 1 : return reinterpret_cast<ErrorInfoBase *>(Err)->dynamicClassID();
153 : }
154 :
155 0 : void LLVMConsumeError(LLVMErrorRef Err) { consumeError(unwrap(Err)); }
156 :
157 1 : char *LLVMGetErrorMessage(LLVMErrorRef Err) {
158 1 : std::string Tmp = toString(unwrap(Err));
159 1 : char *ErrMsg = new char[Tmp.size() + 1];
160 1 : memcpy(ErrMsg, Tmp.data(), Tmp.size());
161 1 : ErrMsg[Tmp.size()] = '\0';
162 1 : return ErrMsg;
163 : }
164 :
165 1 : void LLVMDisposeErrorMessage(char *ErrMsg) { delete[] ErrMsg; }
166 :
167 1 : LLVMErrorTypeId LLVMGetStringErrorTypeId() {
168 1 : return reinterpret_cast<void *>(&StringError::ID);
169 : }
170 :
171 : #ifndef _MSC_VER
172 : namespace llvm {
173 :
174 : // One of these two variables will be referenced by a symbol defined in
175 : // llvm-config.h. We provide a link-time (or load time for DSO) failure when
176 : // there is a mismatch in the build configuration of the API client and LLVM.
177 : #if LLVM_ENABLE_ABI_BREAKING_CHECKS
178 : int EnableABIBreakingChecks;
179 : #else
180 : int DisableABIBreakingChecks;
181 : #endif
182 :
183 : } // end namespace llvm
184 : #endif
|