/home/arjun/llvm-project/llvm/lib/Support/Error.cpp
Line | Count | Source (jump to first uncovered line) |
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-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #include "llvm/Support/Error.h" |
10 | | #include "llvm/ADT/Twine.h" |
11 | | #include "llvm/Support/ErrorHandling.h" |
12 | | #include "llvm/Support/ManagedStatic.h" |
13 | | #include <system_error> |
14 | | |
15 | | using namespace llvm; |
16 | | |
17 | | namespace { |
18 | | |
19 | | enum class ErrorErrorCode : int { |
20 | | MultipleErrors = 1, |
21 | | FileError, |
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 | 0 | const char *name() const noexcept override { return "Error"; } |
31 | | |
32 | 0 | std::string message(int condition) const override { |
33 | 0 | switch (static_cast<ErrorErrorCode>(condition)) { |
34 | 0 | case ErrorErrorCode::MultipleErrors: |
35 | 0 | return "Multiple errors"; |
36 | 0 | case ErrorErrorCode::InconvertibleError: |
37 | 0 | return "Inconvertible error value. An error has occurred that could " |
38 | 0 | "not be converted to a known std::error_code. Please file a " |
39 | 0 | "bug."; |
40 | 0 | case ErrorErrorCode::FileError: |
41 | 0 | return "A file error occurred."; |
42 | 0 | } |
43 | 0 | llvm_unreachable("Unhandled error code"); |
44 | 0 | } |
45 | | }; |
46 | | |
47 | | } |
48 | | |
49 | | static ManagedStatic<ErrorErrorCategory> ErrorErrorCat; |
50 | | |
51 | | namespace llvm { |
52 | | |
53 | 0 | void ErrorInfoBase::anchor() {} |
54 | | char ErrorInfoBase::ID = 0; |
55 | | char ErrorList::ID = 0; |
56 | 0 | void ECError::anchor() {} |
57 | | char ECError::ID = 0; |
58 | | char StringError::ID = 0; |
59 | | char FileError::ID = 0; |
60 | | |
61 | 0 | void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner) { |
62 | 0 | if (!E) |
63 | 0 | return; |
64 | 0 | OS << ErrorBanner; |
65 | 0 | handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) { |
66 | 0 | EI.log(OS); |
67 | 0 | OS << "\n"; |
68 | 0 | }); |
69 | 0 | } |
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 | 0 | } |
76 | | |
77 | 0 | std::error_code inconvertibleErrorCode() { |
78 | 0 | return std::error_code(static_cast<int>(ErrorErrorCode::InconvertibleError), |
79 | 0 | *ErrorErrorCat); |
80 | 0 | } |
81 | | |
82 | 0 | std::error_code FileError::convertToErrorCode() const { |
83 | 0 | return std::error_code(static_cast<int>(ErrorErrorCode::FileError), |
84 | 0 | *ErrorErrorCat); |
85 | 0 | } |
86 | | |
87 | 0 | Error errorCodeToError(std::error_code EC) { |
88 | 0 | if (!EC) |
89 | 0 | return Error::success(); |
90 | 0 | return Error(std::make_unique<ECError>(ECError(EC))); |
91 | 0 | } |
92 | | |
93 | 0 | std::error_code errorToErrorCode(Error Err) { |
94 | 0 | std::error_code EC; |
95 | 0 | handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) { |
96 | 0 | EC = EI.convertToErrorCode(); |
97 | 0 | }); |
98 | 0 | if (EC == inconvertibleErrorCode()) |
99 | 0 | report_fatal_error(EC.message()); |
100 | 0 | return EC; |
101 | 0 | } |
102 | | |
103 | | #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
104 | 0 | void Error::fatalUncheckedError() const { |
105 | 0 | dbgs() << "Program aborted due to an unhandled Error:\n"; |
106 | 0 | if (getPtr()) { |
107 | 0 | getPtr()->log(dbgs()); |
108 | 0 | dbgs() << "\n"; |
109 | 0 | }else |
110 | 0 | dbgs() << "Error value was Success. (Note: Success values must still be " |
111 | 0 | "checked prior to being destroyed).\n"; |
112 | 0 | abort(); |
113 | 0 | } |
114 | | #endif |
115 | | |
116 | | StringError::StringError(std::error_code EC, const Twine &S) |
117 | 0 | : Msg(S.str()), EC(EC) {} |
118 | | |
119 | | StringError::StringError(const Twine &S, std::error_code EC) |
120 | 0 | : Msg(S.str()), EC(EC), PrintMsgOnly(true) {} |
121 | | |
122 | 0 | void StringError::log(raw_ostream &OS) const { |
123 | 0 | if (PrintMsgOnly) { |
124 | 0 | OS << Msg; |
125 | 0 | } else { |
126 | 0 | OS << EC.message(); |
127 | 0 | if (!Msg.empty()) |
128 | 0 | OS << (" " + Msg); |
129 | 0 | } |
130 | 0 | } |
131 | | |
132 | 0 | std::error_code StringError::convertToErrorCode() const { |
133 | 0 | return EC; |
134 | 0 | } |
135 | | |
136 | 0 | Error createStringError(std::error_code EC, char const *Msg) { |
137 | 0 | return make_error<StringError>(Msg, EC); |
138 | 0 | } |
139 | | |
140 | 0 | void report_fatal_error(Error Err, bool GenCrashDiag) { |
141 | 0 | assert(Err && "report_fatal_error called with success value"); |
142 | 0 | std::string ErrMsg; |
143 | 0 | { |
144 | 0 | raw_string_ostream ErrStream(ErrMsg); |
145 | 0 | logAllUnhandledErrors(std::move(Err), ErrStream); |
146 | 0 | } |
147 | 0 | report_fatal_error(ErrMsg); |
148 | 0 | } |
149 | | |
150 | | } // end namespace llvm |
151 | | |
152 | 0 | LLVMErrorTypeId LLVMGetErrorTypeId(LLVMErrorRef Err) { |
153 | 0 | return reinterpret_cast<ErrorInfoBase *>(Err)->dynamicClassID(); |
154 | 0 | } |
155 | | |
156 | 0 | void LLVMConsumeError(LLVMErrorRef Err) { consumeError(unwrap(Err)); } |
157 | | |
158 | 0 | char *LLVMGetErrorMessage(LLVMErrorRef Err) { |
159 | 0 | std::string Tmp = toString(unwrap(Err)); |
160 | 0 | char *ErrMsg = new char[Tmp.size() + 1]; |
161 | 0 | memcpy(ErrMsg, Tmp.data(), Tmp.size()); |
162 | 0 | ErrMsg[Tmp.size()] = '\0'; |
163 | 0 | return ErrMsg; |
164 | 0 | } |
165 | | |
166 | 0 | void LLVMDisposeErrorMessage(char *ErrMsg) { delete[] ErrMsg; } |
167 | | |
168 | 0 | LLVMErrorTypeId LLVMGetStringErrorTypeId() { |
169 | 0 | return reinterpret_cast<void *>(&StringError::ID); |
170 | 0 | } |