LLVM: include/llvm/Support/ErrorOr.h Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#ifndef LLVM_SUPPORT_ERROROR_H
16#define LLVM_SUPPORT_ERROROR_H
17
19#include
20#include <system_error>
21#include <type_traits>
22#include
23
24namespace llvm {
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55template
57 template friend class ErrorOr;
58
59 static constexpr bool isRef = std::is_reference_v;
60
61 using wrap = std::reference_wrapper<std::remove_reference_t>;
62
63public:
64 using storage_type = std::conditional_t<isRef, wrap, T>;
65
66private:
67 using reference = std::remove_reference_t &;
68 using const_reference = const std::remove_reference_t &;
69 using pointer = std::remove_reference_t *;
70 using const_pointer = const std::remove_reference_t *;
71
72public:
73 template
75 std::enable_if_t<std::is_error_code_enum::value ||
76 std::is_error_condition_enum::value,
77 void *> = nullptr)
78 : HasError(true) {
79 new (getErrorStorage()) std::error_code(make_error_code(ErrorCode));
80 }
81
83 new (getErrorStorage()) std::error_code(EC);
84 }
85
86 template
88 std::enable_if_t<std::is_convertible_v<OtherT, T>> * = nullptr)
89 : HasError(false) {
90 new (getStorage()) storage_type(std::forward(Val));
91 }
92
94 copyConstruct(Other);
95 }
96
97 template
99 std::enable_if_t<std::is_convertible_v<OtherT, T>> * = nullptr) {
100 copyConstruct(Other);
101 }
102
103 template
106 std::enable_if_t<!std::is_convertible_v<OtherT, const T &>> * = nullptr) {
107 copyConstruct(Other);
108 }
109
111 moveConstruct(std::move(Other));
112 }
113
114 template
116 std::enable_if_t<std::is_convertible_v<OtherT, T>> * = nullptr) {
117 moveConstruct(std::move(Other));
118 }
119
120
121
122 template
125 std::enable_if_t<!std::is_convertible_v<OtherT, T>> * = nullptr) {
126 moveConstruct(std::move(Other));
127 }
128
130 copyAssign(Other);
131 return *this;
132 }
133
135 moveAssign(std::move(Other));
136 return *this;
137 }
138
140 if (!HasError)
141 getStorage()->~storage_type();
142 }
143
144
145 explicit operator bool() const {
146 return !HasError;
147 }
148
149 reference get() { return *getStorage(); }
150 const_reference get() const { return const_cast<ErrorOr *>(this)->get(); }
151
153 return HasError ? *getErrorStorage() : std::error_code();
154 }
155
157 return toPointer(getStorage());
158 }
159
160 const_pointer operator->() const { return toPointer(getStorage()); }
161
163 return *getStorage();
164 }
165
166 const_reference operator*() const { return *getStorage(); }
167
168private:
169 template
171 if (.HasError) {
172
173 HasError = false;
175 } else {
176
177 HasError = true;
178 new (getErrorStorage()) std::error_code(Other.getError());
179 }
180 }
181
182 template
183 static bool compareThisIfSameType(const T1 &a, const T1 &b) {
184 return &a == &b;
185 }
186
187 template <class T1, class T2>
188 static bool compareThisIfSameType(const T1 &a, const T2 &b) {
189 return false;
190 }
191
192 template
193 void copyAssign(const ErrorOr &Other) {
194 if (compareThisIfSameType(*this, Other))
195 return;
196
198 new (this) ErrorOr(Other);
199 }
200
201 template
202 void moveConstruct(ErrorOr &&Other) {
203 if (.HasError) {
204
205 HasError = false;
207 } else {
208
209 HasError = true;
210 new (getErrorStorage()) std::error_code(Other.getError());
211 }
212 }
213
214 template
215 void moveAssign(ErrorOr &&Other) {
216 if (compareThisIfSameType(*this, Other))
217 return;
218
221 }
222
223 pointer toPointer(pointer Val) {
224 return Val;
225 }
226
227 const_pointer toPointer(const_pointer Val) const { return Val; }
228
229 pointer toPointer(wrap *Val) {
230 return &Val->get();
231 }
232
233 const_pointer toPointer(const wrap *Val) const { return &Val->get(); }
234
236 assert(!HasError && "Cannot get value when an error exists!");
238 }
239
241 assert(!HasError && "Cannot get value when an error exists!");
243 }
244
245 std::error_code *getErrorStorage() {
246 assert(HasError && "Cannot get error when a value exists!");
247 return reinterpret_cast<std::error_code *>(&ErrorStorage);
248 }
249
250 const std::error_code *getErrorStorage() const {
251 return const_cast<ErrorOr *>(this)->getErrorStorage();
252 }
253
254 union {
257 };
258 bool HasError : 1;
259};
260
261template <class T, class E>
262std::enable_if_t<std::is_error_code_enum::value ||
263 std::is_error_condition_enum::value,
264 bool>
266 return Err.getError() == Code;
267}
268
269}
270
271#endif
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static LLVMTargetMachineRef wrap(const TargetMachine *P)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Represents either an error or a value T.
std::conditional_t< isRef, wrap, T > storage_type
const_reference get() const
ErrorOr(std::error_code EC)
ErrorOr(OtherT &&Val, std::enable_if_t< std::is_convertible_v< OtherT, T > > *=nullptr)
AlignedCharArrayUnion< std::error_code > ErrorStorage
ErrorOr(const ErrorOr &Other)
ErrorOr(E ErrorCode, std::enable_if_t< std::is_error_code_enum< E >::value||std::is_error_condition_enum< E >::value, void * >=nullptr)
const_reference operator*() const
ErrorOr(ErrorOr< OtherT > &&Other, std::enable_if_t< std::is_convertible_v< OtherT, T > > *=nullptr)
ErrorOr & operator=(const ErrorOr &Other)
std::error_code getError() const
ErrorOr(const ErrorOr< OtherT > &Other, std::enable_if_t< std::is_convertible_v< OtherT, T > > *=nullptr)
ErrorOr(const ErrorOr< OtherT > &Other, std::enable_if_t<!std::is_convertible_v< OtherT, const T & > > *=nullptr)
ErrorOr(ErrorOr< OtherT > &&Other, std::enable_if_t<!std::is_convertible_v< OtherT, T > > *=nullptr)
const_pointer operator->() const
ErrorOr & operator=(ErrorOr &&Other)
AlignedCharArrayUnion< storage_type > TStorage
This is an optimization pass for GlobalISel generic memory operations.
std::error_code make_error_code(BitcodeError E)
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
A suitably aligned and sized character array member which can hold elements of any type.