14 #ifndef WPIUTIL_WPI_ERROR_H
15 #define WPIUTIL_WPI_ERROR_H
17 #include "wpi/STLExtras.h"
18 #include "wpi/SmallVector.h"
19 #include "wpi/StringExtras.h"
20 #include "wpi/Twine.h"
21 #include "wpi/AlignOf.h"
22 #include "wpi/Compiler.h"
23 #include "wpi/ErrorHandling.h"
25 #include "wpi/Format.h"
26 #include "wpi/raw_ostream.h"
35 #include <system_error>
36 #include <type_traits>
68 static const void *classID() {
return &ID; }
71 virtual const void *dynamicClassID()
const = 0;
75 virtual bool isA(
const void *
const ClassID)
const {
76 return ClassID == classID();
80 template <
typename ErrorInfoT>
bool isA()
const {
81 return isA(ErrorInfoT::classID());
85 virtual void anchor();
162 template <
typename... HandlerTs>
167 template <
typename T>
friend class Expected;
188 *
this = std::move(Other);
193 Error(std::unique_ptr<ErrorInfoBase> Payload) {
194 setPtr(Payload.release());
199 Error &operator=(
const Error &Other) =
delete;
208 setPtr(Other.getPtr());
214 Other.setPtr(
nullptr);
215 Other.setChecked(
true);
230 explicit operator bool() {
231 setChecked(getPtr() ==
nullptr);
232 return getPtr() !=
nullptr;
236 template <
typename ErrT>
bool isA()
const {
237 return getPtr() && getPtr()->isA(ErrT::classID());
245 return getPtr()->dynamicClassID();
249 void assertIsChecked() {
252 ErrorInfoBase *getPtr()
const {
253 return reinterpret_cast<ErrorInfoBase*>(
254 reinterpret_cast<uintptr_t>(Payload) &
255 ~static_cast<uintptr_t>(0x1));
258 void setPtr(ErrorInfoBase *EI) {
262 bool getChecked()
const {
266 void setChecked(
bool V) {
267 Payload = reinterpret_cast<ErrorInfoBase*>(
268 (reinterpret_cast<uintptr_t>(Payload) &
269 ~static_cast<uintptr_t>(0x1)) |
273 std::unique_ptr<ErrorInfoBase> takePayload() {
274 std::unique_ptr<ErrorInfoBase> Tmp(getPtr());
280 friend raw_ostream &
operator<<(raw_ostream &OS,
const Error &E) {
281 if (
auto P = E.getPtr())
288 ErrorInfoBase *Payload =
nullptr;
301 return Error(std::make_unique<ErrT>(std::forward<ArgTs>(Args)...));
313 template <
typename ThisErrT,
typename ParentErrT = ErrorInfoBase>
316 using ParentErrT::ParentErrT;
318 static const void *classID() {
return &ThisErrT::ID; }
320 const void *dynamicClassID()
const override {
return &ThisErrT::ID; }
322 bool isA(
const void *
const ClassID)
const override {
323 return ClassID == classID() || ParentErrT::isA(ClassID);
332 template <
typename... HandlerTs>
340 OS <<
"Multiple errors:\n";
341 for (
auto &ErrPayload : Payloads) {
353 ErrorList(std::unique_ptr<ErrorInfoBase> Payload1,
354 std::unique_ptr<ErrorInfoBase> Payload2) {
356 "ErrorList constructor payloads should be singleton errors");
357 Payloads.push_back(std::move(Payload1));
358 Payloads.push_back(std::move(Payload2));
361 static Error join(Error E1, Error E2) {
366 if (E1.isA<ErrorList>()) {
367 auto &E1List = static_cast<ErrorList &>(*E1.getPtr());
368 if (E2.isA<ErrorList>()) {
369 auto E2Payload = E2.takePayload();
370 auto &E2List = static_cast<ErrorList &>(*E2Payload);
371 for (
auto &Payload : E2List.Payloads)
372 E1List.Payloads.push_back(std::move(Payload));
374 E1List.Payloads.push_back(E2.takePayload());
378 if (E2.isA<ErrorList>()) {
379 auto &E2List = static_cast<ErrorList &>(*E2.getPtr());
380 E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload());
383 return Error(std::unique_ptr<ErrorList>(
384 new ErrorList(E1.takePayload(), E2.takePayload())));
387 std::vector<std::unique_ptr<ErrorInfoBase>> Payloads;
394 return ErrorList::join(std::move(E1), std::move(E2));
405 template <
class OtherT>
friend class Expected;
407 static const bool isRef = std::is_reference<T>::value;
409 using wrap = std::reference_wrapper<typename std::remove_reference<T>::type>;
411 using error_type = std::unique_ptr<ErrorInfoBase>;
414 using storage_type =
typename std::conditional<isRef, wrap, T>::type;
415 using value_type = T;
418 using reference =
typename std::remove_reference<T>::type &;
419 using const_reference =
const typename std::remove_reference<T>::type &;
420 using pointer =
typename std::remove_reference<T>::type *;
421 using const_pointer =
const typename std::remove_reference<T>::type *;
428 assert(Err &&
"Cannot create Expected<T> from Error success value.");
429 new (getErrorStorage()) error_type(Err.takePayload());
439 template <
typename OtherT>
441 typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
445 new (getStorage()) storage_type(std::forward<OtherT>(Val));
453 template <
class OtherT>
455 typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
457 moveConstruct(std::move(Other));
462 template <
class OtherT>
465 typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
467 moveConstruct(std::move(Other));
472 moveAssign(std::move(Other));
480 getStorage()->~storage_type();
482 getErrorStorage()->~error_type();
486 explicit operator bool() {
493 return *getStorage();
497 const_reference
get()
const {
504 return HasError && (*getErrorStorage())->
template isA<ErrT>();
518 return toPointer(getStorage());
524 return toPointer(getStorage());
530 return *getStorage();
536 return *getStorage();
541 static bool compareThisIfSameType(
const T1 &a,
const T1 &b) {
545 template <
class T1,
class T2>
546 static bool compareThisIfSameType(
const T1 &a,
const T2 &b) {
550 template <
class OtherT>
void moveConstruct(Expected<OtherT> &&Other) {
551 HasError = Other.HasError;
554 new (getStorage()) storage_type(std::move(*Other.getStorage()));
556 new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage()));
559 template <
class OtherT>
void moveAssign(Expected<OtherT> &&Other) {
562 if (compareThisIfSameType(*
this, Other))
566 new (
this) Expected(std::move(Other));
569 pointer toPointer(pointer Val) {
return Val; }
571 const_pointer toPointer(const_pointer Val)
const {
return Val; }
573 pointer toPointer(wrap *Val) {
return &Val->get(); }
575 const_pointer toPointer(
const wrap *Val)
const {
return &Val->get(); }
577 storage_type *getStorage() {
578 assert(!HasError &&
"Cannot get value when an error exists!");
579 return reinterpret_cast<storage_type *>(TStorage.buffer);
582 const storage_type *getStorage()
const {
583 assert(!HasError &&
"Cannot get value when an error exists!");
584 return reinterpret_cast<const storage_type *>(TStorage.buffer);
587 error_type *getErrorStorage() {
588 assert(HasError &&
"Cannot get error when a value exists!");
589 return reinterpret_cast<error_type *>(ErrorStorage.buffer);
592 const error_type *getErrorStorage()
const {
593 assert(HasError &&
"Cannot get error when a value exists!");
594 return reinterpret_cast<const error_type *>(ErrorStorage.buffer);
598 void setUnchecked() {
601 void assertIsChecked() {
605 AlignedCharArrayUnion<storage_type> TStorage;
606 AlignedCharArrayUnion<error_type> ErrorStorage;
614 bool gen_crash_diag =
true);
632 Msg =
"Failure value returned from cantFail wrapped call";
633 wpi_unreachable(Msg);
650 template <
typename T>
653 return std::move(*ValOrErr);
656 Msg =
"Failure value returned from cantFail wrapped call";
657 wpi_unreachable(Msg);
674 template <
typename T>
680 Msg =
"Failure value returned from cantFail wrapped call";
681 wpi_unreachable(Msg);
687 template <
typename HandlerT>
690 &std::remove_reference<HandlerT>::type::operator())> {};
696 return E.template isA<ErrT>();
699 template <
typename HandlerT>
700 static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
701 assert(appliesTo(*E) &&
"Applying incorrect handler");
702 return H(static_cast<ErrT &>(*E));
710 return E.template isA<ErrT>();
713 template <
typename HandlerT>
714 static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
715 assert(appliesTo(*E) &&
"Applying incorrect handler");
716 H(static_cast<ErrT &>(*E));
722 template <
typename ErrT>
726 return E.template isA<ErrT>();
729 template <
typename HandlerT>
730 static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
731 assert(appliesTo(*E) &&
"Applying incorrect handler");
732 std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
733 return H(std::move(SubE));
738 template <
typename ErrT>
742 return E.template isA<ErrT>();
745 template <
typename HandlerT>
746 static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
747 assert(appliesTo(*E) &&
"Applying incorrect handler");
748 std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
755 template <
typename C,
typename RetT,
typename ErrT>
760 template <
typename C,
typename RetT,
typename ErrT>
765 template <
typename C,
typename RetT,
typename ErrT>
770 template <
typename C,
typename RetT,
typename ErrT>
776 template <
typename C,
typename RetT,
typename ErrT>
782 template <
typename C,
typename RetT,
typename ErrT>
786 inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) {
787 return Error(std::move(Payload));
790 template <
typename HandlerT,
typename... HandlerTs>
791 Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload,
792 HandlerT &&Handler, HandlerTs &&... Handlers) {
793 if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload))
794 return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler),
796 return handleErrorImpl(std::move(Payload),
797 std::forward<HandlerTs>(Handlers)...);
806 template <
typename... HandlerTs>
811 std::unique_ptr<ErrorInfoBase> Payload = E.takePayload();
814 ErrorList &List = static_cast<ErrorList &>(*Payload);
816 for (
auto &P : List.Payloads)
819 handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...));
823 return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...);
829 template <
typename... HandlerTs>
864 template <
typename T,
typename RecoveryFtor,
typename... HandlerTs>
866 HandlerTs &&... Handlers) {
871 std::forward<HandlerTs>(Handlers)...))
872 return std::move(Err);
874 return RecoveryPath();
895 Errors.push_back(EI.
message());
897 return join(Errors.begin(), Errors.end(),
"\n");
917 bool IsError = static_cast<bool>(Err);
968 template <
typename T>
972 : ValOrErr(ValOrErr) {
979 ValOrErr->setUnchecked();
994 virtual void anchor()
override;
997 void setErrorCode(std::error_code EC) { this->EC = EC; }
1006 ECError(std::error_code EC) : EC(EC) {}
1030 if (
auto EC = EO.getError())
1032 return std::move(*EO);
1037 if (
auto Err = E.takeError())
1039 return std::move(*E);
1079 const std::string &getMessage()
const {
return Msg; }
1084 const bool PrintMsgOnly =
false;
1088 template <
typename... Ts>
1090 const Ts &... Vals) {
1093 Stream <<
format(Fmt, Vals...);
1094 return make_error<StringError>(Stream.
str(), EC);
1109 assert(Err && !FileName.empty() &&
"Trying to log after takeError().");
1110 OS <<
"'" << FileName <<
"': ";
1114 Error takeError() {
return Error(std::move(Err)); }
1122 FileError(std::string F, std::unique_ptr<ErrorInfoBase> E) {
1123 assert(E &&
"Cannot create FileError from Error success value.");
1124 assert(!F.empty() &&
1125 "The file name provided to FileError must not be empty.");
1130 static Error build(std::string F, Error E) {
1131 return Error(std::unique_ptr<FileError>(
new FileError(F, E.takePayload())));
1134 std::string FileName;
1135 std::unique_ptr<ErrorInfoBase> Err;
1141 return FileError::build(F, std::move(E));
1154 : Banner(std::move(Banner)),
1155 GetExitCode([=](const
Error &) {
return DefaultErrorExitCode; }) {}
1158 void setBanner(std::string Banner) { this->Banner = std::move(Banner); }
1162 this->GetExitCode = std::move(GetExitCode);
1171 checkError(E.takeError());
1172 return std::move(*E);
1178 checkError(E.takeError());
1183 void checkError(
Error Err)
const {
1185 int ExitCode = GetExitCode(Err);
1192 std::function<int(
const Error &)> GetExitCode;
1197 #endif // WPIUTIL_WPI_ERROR_H