WPILibC++  2020.3.2
Error.h
1 //===- llvm/Support/Error.h - Recoverable error handling --------*- C++ -*-===//
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 // This file defines an API used to report recoverable errors.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef WPIUTIL_WPI_ERROR_H
15 #define WPIUTIL_WPI_ERROR_H
16 
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"
24 #include "wpi/ErrorOr.h"
25 #include "wpi/Format.h"
26 #include "wpi/raw_ostream.h"
27 #include <algorithm>
28 #include <cassert>
29 #include <cstdint>
30 #include <cstdlib>
31 #include <functional>
32 #include <memory>
33 #include <new>
34 #include <string>
35 #include <system_error>
36 #include <type_traits>
37 #include <utility>
38 #include <vector>
39 
40 namespace wpi {
41 
42 class ErrorSuccess;
43 
47 public:
48  virtual ~ErrorInfoBase() = default;
49 
51  virtual void log(raw_ostream &OS) const = 0;
52 
54  virtual std::string message() const {
55  std::string Msg;
56  raw_string_ostream OS(Msg);
57  log(OS);
58  return OS.str();
59  }
60 
65  virtual std::error_code convertToErrorCode() const = 0;
66 
67  // Returns the class ID for this type.
68  static const void *classID() { return &ID; }
69 
70  // Returns the class ID for the dynamic type of this ErrorInfoBase instance.
71  virtual const void *dynamicClassID() const = 0;
72 
73  // Check whether this instance is a subclass of the class identified by
74  // ClassID.
75  virtual bool isA(const void *const ClassID) const {
76  return ClassID == classID();
77  }
78 
79  // Check whether this instance is a subclass of ErrorInfoT.
80  template <typename ErrorInfoT> bool isA() const {
81  return isA(ErrorInfoT::classID());
82  }
83 
84 private:
85  virtual void anchor();
86 
87  static char ID;
88 };
89 
155 class LLVM_NODISCARD Error {
156  // Both ErrorList and FileError need to be able to yank ErrorInfoBase
157  // pointers out of this class to add to the error list.
158  friend class ErrorList;
159  friend class FileError;
160 
161  // handleErrors needs to be able to set the Checked flag.
162  template <typename... HandlerTs>
163  friend Error handleErrors(Error E, HandlerTs &&... Handlers);
164 
165  // Expected<T> needs to be able to steal the payload when constructed from an
166  // error.
167  template <typename T> friend class Expected;
168 
169 protected:
171  Error() {
172  setPtr(nullptr);
173  setChecked(false);
174  }
175 
176 public:
178  static ErrorSuccess success();
179 
180  // Errors are not copy-constructable.
181  Error(const Error &Other) = delete;
182 
186  Error(Error &&Other) noexcept {
187  setChecked(true);
188  *this = std::move(Other);
189  }
190 
193  Error(std::unique_ptr<ErrorInfoBase> Payload) {
194  setPtr(Payload.release());
195  setChecked(false);
196  }
197 
198  // Errors are not copy-assignable.
199  Error &operator=(const Error &Other) = delete;
200 
205  Error &operator=(Error &&Other) noexcept {
206  // Don't allow overwriting of unchecked values.
207  assertIsChecked();
208  setPtr(Other.getPtr());
209 
210  // This Error is unchecked, even if the source error was checked.
211  setChecked(false);
212 
213  // Null out Other's payload and set its checked bit.
214  Other.setPtr(nullptr);
215  Other.setChecked(true);
216 
217  return *this;
218  }
219 
222  ~Error() {
223  assertIsChecked();
224  delete getPtr();
225  }
226 
230  explicit operator bool() {
231  setChecked(getPtr() == nullptr);
232  return getPtr() != nullptr;
233  }
234 
236  template <typename ErrT> bool isA() const {
237  return getPtr() && getPtr()->isA(ErrT::classID());
238  }
239 
242  const void* dynamicClassID() const {
243  if (!getPtr())
244  return nullptr;
245  return getPtr()->dynamicClassID();
246  }
247 
248 private:
249  void assertIsChecked() {
250  }
251 
252  ErrorInfoBase *getPtr() const {
253  return reinterpret_cast<ErrorInfoBase*>(
254  reinterpret_cast<uintptr_t>(Payload) &
255  ~static_cast<uintptr_t>(0x1));
256  }
257 
258  void setPtr(ErrorInfoBase *EI) {
259  Payload = EI;
260  }
261 
262  bool getChecked() const {
263  return true;
264  }
265 
266  void setChecked(bool V) {
267  Payload = reinterpret_cast<ErrorInfoBase*>(
268  (reinterpret_cast<uintptr_t>(Payload) &
269  ~static_cast<uintptr_t>(0x1)) |
270  (V ? 0 : 1));
271  }
272 
273  std::unique_ptr<ErrorInfoBase> takePayload() {
274  std::unique_ptr<ErrorInfoBase> Tmp(getPtr());
275  setPtr(nullptr);
276  setChecked(true);
277  return Tmp;
278  }
279 
280  friend raw_ostream &operator<<(raw_ostream &OS, const Error &E) {
281  if (auto P = E.getPtr())
282  P->log(OS);
283  else
284  OS << "success";
285  return OS;
286  }
287 
288  ErrorInfoBase *Payload = nullptr;
289 };
290 
294 class ErrorSuccess final : public Error {};
295 
297 
300 template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) {
301  return Error(std::make_unique<ErrT>(std::forward<ArgTs>(Args)...));
302 }
303 
313 template <typename ThisErrT, typename ParentErrT = ErrorInfoBase>
314 class ErrorInfo : public ParentErrT {
315 public:
316  using ParentErrT::ParentErrT; // inherit constructors
317 
318  static const void *classID() { return &ThisErrT::ID; }
319 
320  const void *dynamicClassID() const override { return &ThisErrT::ID; }
321 
322  bool isA(const void *const ClassID) const override {
323  return ClassID == classID() || ParentErrT::isA(ClassID);
324  }
325 };
326 
329 class ErrorList final : public ErrorInfo<ErrorList> {
330  // handleErrors needs to be able to iterate the payload list of an
331  // ErrorList.
332  template <typename... HandlerTs>
333  friend Error handleErrors(Error E, HandlerTs &&... Handlers);
334 
335  // joinErrors is implemented in terms of join.
336  friend Error joinErrors(Error, Error);
337 
338 public:
339  void log(raw_ostream &OS) const override {
340  OS << "Multiple errors:\n";
341  for (auto &ErrPayload : Payloads) {
342  ErrPayload->log(OS);
343  OS << "\n";
344  }
345  }
346 
347  std::error_code convertToErrorCode() const override;
348 
349  // Used by ErrorInfo::classID.
350  static char ID;
351 
352 private:
353  ErrorList(std::unique_ptr<ErrorInfoBase> Payload1,
354  std::unique_ptr<ErrorInfoBase> Payload2) {
355  assert(!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() &&
356  "ErrorList constructor payloads should be singleton errors");
357  Payloads.push_back(std::move(Payload1));
358  Payloads.push_back(std::move(Payload2));
359  }
360 
361  static Error join(Error E1, Error E2) {
362  if (!E1)
363  return E2;
364  if (!E2)
365  return E1;
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));
373  } else
374  E1List.Payloads.push_back(E2.takePayload());
375 
376  return E1;
377  }
378  if (E2.isA<ErrorList>()) {
379  auto &E2List = static_cast<ErrorList &>(*E2.getPtr());
380  E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload());
381  return E2;
382  }
383  return Error(std::unique_ptr<ErrorList>(
384  new ErrorList(E1.takePayload(), E2.takePayload())));
385  }
386 
387  std::vector<std::unique_ptr<ErrorInfoBase>> Payloads;
388 };
389 
393 inline Error joinErrors(Error E1, Error E2) {
394  return ErrorList::join(std::move(E1), std::move(E2));
395 }
396 
403 template <class T> class LLVM_NODISCARD Expected {
404  template <class T1> friend class ExpectedAsOutParameter;
405  template <class OtherT> friend class Expected;
406 
407  static const bool isRef = std::is_reference<T>::value;
408 
409  using wrap = std::reference_wrapper<typename std::remove_reference<T>::type>;
410 
411  using error_type = std::unique_ptr<ErrorInfoBase>;
412 
413 public:
414  using storage_type = typename std::conditional<isRef, wrap, T>::type;
415  using value_type = T;
416 
417 private:
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 *;
422 
423 public:
426  : HasError(true)
427  {
428  assert(Err && "Cannot create Expected<T> from Error success value.");
429  new (getErrorStorage()) error_type(Err.takePayload());
430  }
431 
435  Expected(ErrorSuccess) = delete;
436 
439  template <typename OtherT>
440  Expected(OtherT &&Val,
441  typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
442  * = nullptr)
443  : HasError(false)
444  {
445  new (getStorage()) storage_type(std::forward<OtherT>(Val));
446  }
447 
449  Expected(Expected &&Other) { moveConstruct(std::move(Other)); }
450 
453  template <class OtherT>
455  typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
456  * = nullptr) {
457  moveConstruct(std::move(Other));
458  }
459 
462  template <class OtherT>
463  explicit Expected(
464  Expected<OtherT> &&Other,
465  typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
466  nullptr) {
467  moveConstruct(std::move(Other));
468  }
469 
472  moveAssign(std::move(Other));
473  return *this;
474  }
475 
478  assertIsChecked();
479  if (!HasError)
480  getStorage()->~storage_type();
481  else
482  getErrorStorage()->~error_type();
483  }
484 
486  explicit operator bool() {
487  return !HasError;
488  }
489 
491  reference get() {
492  assertIsChecked();
493  return *getStorage();
494  }
495 
497  const_reference get() const {
498  assertIsChecked();
499  return const_cast<Expected<T> *>(this)->get();
500  }
501 
503  template <typename ErrT> bool errorIsA() const {
504  return HasError && (*getErrorStorage())->template isA<ErrT>();
505  }
506 
512  return HasError ? Error(std::move(*getErrorStorage())) : Error::success();
513  }
514 
516  pointer operator->() {
517  assertIsChecked();
518  return toPointer(getStorage());
519  }
520 
522  const_pointer operator->() const {
523  assertIsChecked();
524  return toPointer(getStorage());
525  }
526 
528  reference operator*() {
529  assertIsChecked();
530  return *getStorage();
531  }
532 
534  const_reference operator*() const {
535  assertIsChecked();
536  return *getStorage();
537  }
538 
539 private:
540  template <class T1>
541  static bool compareThisIfSameType(const T1 &a, const T1 &b) {
542  return &a == &b;
543  }
544 
545  template <class T1, class T2>
546  static bool compareThisIfSameType(const T1 &a, const T2 &b) {
547  return false;
548  }
549 
550  template <class OtherT> void moveConstruct(Expected<OtherT> &&Other) {
551  HasError = Other.HasError;
552 
553  if (!HasError)
554  new (getStorage()) storage_type(std::move(*Other.getStorage()));
555  else
556  new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage()));
557  }
558 
559  template <class OtherT> void moveAssign(Expected<OtherT> &&Other) {
560  assertIsChecked();
561 
562  if (compareThisIfSameType(*this, Other))
563  return;
564 
565  this->~Expected();
566  new (this) Expected(std::move(Other));
567  }
568 
569  pointer toPointer(pointer Val) { return Val; }
570 
571  const_pointer toPointer(const_pointer Val) const { return Val; }
572 
573  pointer toPointer(wrap *Val) { return &Val->get(); }
574 
575  const_pointer toPointer(const wrap *Val) const { return &Val->get(); }
576 
577  storage_type *getStorage() {
578  assert(!HasError && "Cannot get value when an error exists!");
579  return reinterpret_cast<storage_type *>(TStorage.buffer);
580  }
581 
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);
585  }
586 
587  error_type *getErrorStorage() {
588  assert(HasError && "Cannot get error when a value exists!");
589  return reinterpret_cast<error_type *>(ErrorStorage.buffer);
590  }
591 
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);
595  }
596 
597  // Used by ExpectedAsOutParameter to reset the checked flag.
598  void setUnchecked() {
599  }
600 
601  void assertIsChecked() {
602  }
603 
604  union {
605  AlignedCharArrayUnion<storage_type> TStorage;
606  AlignedCharArrayUnion<error_type> ErrorStorage;
607  };
608  bool HasError : 1;
609 };
610 
613 LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err,
614  bool gen_crash_diag = true);
615 
629 inline void cantFail(Error Err, const char *Msg = nullptr) {
630  if (Err) {
631  if (!Msg)
632  Msg = "Failure value returned from cantFail wrapped call";
633  wpi_unreachable(Msg);
634  }
635 }
636 
650 template <typename T>
651 T cantFail(Expected<T> ValOrErr, const char *Msg = nullptr) {
652  if (ValOrErr)
653  return std::move(*ValOrErr);
654  else {
655  if (!Msg)
656  Msg = "Failure value returned from cantFail wrapped call";
657  wpi_unreachable(Msg);
658  }
659 }
660 
674 template <typename T>
675 T& cantFail(Expected<T&> ValOrErr, const char *Msg = nullptr) {
676  if (ValOrErr)
677  return *ValOrErr;
678  else {
679  if (!Msg)
680  Msg = "Failure value returned from cantFail wrapped call";
681  wpi_unreachable(Msg);
682  }
683 }
684 
687 template <typename HandlerT>
689  : public ErrorHandlerTraits<decltype(
690  &std::remove_reference<HandlerT>::type::operator())> {};
691 
692 // Specialization functions of the form 'Error (const ErrT&)'.
693 template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> {
694 public:
695  static bool appliesTo(const ErrorInfoBase &E) {
696  return E.template isA<ErrT>();
697  }
698 
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));
703  }
704 };
705 
706 // Specialization functions of the form 'void (const ErrT&)'.
707 template <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> {
708 public:
709  static bool appliesTo(const ErrorInfoBase &E) {
710  return E.template isA<ErrT>();
711  }
712 
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));
717  return Error::success();
718  }
719 };
720 
722 template <typename ErrT>
723 class ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> {
724 public:
725  static bool appliesTo(const ErrorInfoBase &E) {
726  return E.template isA<ErrT>();
727  }
728 
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));
734  }
735 };
736 
738 template <typename ErrT>
739 class ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> {
740 public:
741  static bool appliesTo(const ErrorInfoBase &E) {
742  return E.template isA<ErrT>();
743  }
744 
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()));
749  H(std::move(SubE));
750  return Error::success();
751  }
752 };
753 
754 // Specialization for member functions of the form 'RetT (const ErrT&)'.
755 template <typename C, typename RetT, typename ErrT>
756 class ErrorHandlerTraits<RetT (C::*)(ErrT &)>
757  : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
758 
759 // Specialization for member functions of the form 'RetT (const ErrT&) const'.
760 template <typename C, typename RetT, typename ErrT>
761 class ErrorHandlerTraits<RetT (C::*)(ErrT &) const>
762  : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
763 
764 // Specialization for member functions of the form 'RetT (const ErrT&)'.
765 template <typename C, typename RetT, typename ErrT>
766 class ErrorHandlerTraits<RetT (C::*)(const ErrT &)>
767  : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
768 
769 // Specialization for member functions of the form 'RetT (const ErrT&) const'.
770 template <typename C, typename RetT, typename ErrT>
771 class ErrorHandlerTraits<RetT (C::*)(const ErrT &) const>
772  : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
773 
776 template <typename C, typename RetT, typename ErrT>
777 class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>)>
778  : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {};
779 
782 template <typename C, typename RetT, typename ErrT>
783 class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const>
784  : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {};
785 
786 inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) {
787  return Error(std::move(Payload));
788 }
789 
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),
795  std::move(Payload));
796  return handleErrorImpl(std::move(Payload),
797  std::forward<HandlerTs>(Handlers)...);
798 }
799 
806 template <typename... HandlerTs>
807 Error handleErrors(Error E, HandlerTs &&... Hs) {
808  if (!E)
809  return Error::success();
810 
811  std::unique_ptr<ErrorInfoBase> Payload = E.takePayload();
812 
813  if (Payload->isA<ErrorList>()) {
814  ErrorList &List = static_cast<ErrorList &>(*Payload);
815  Error R;
816  for (auto &P : List.Payloads)
817  R = ErrorList::join(
818  std::move(R),
819  handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...));
820  return R;
821  }
822 
823  return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...);
824 }
825 
829 template <typename... HandlerTs>
830 void handleAllErrors(Error E, HandlerTs &&... Handlers) {
831  cantFail(handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...));
832 }
833 
836 inline void handleAllErrors(Error E) {
837  cantFail(std::move(E));
838 }
839 
864 template <typename T, typename RecoveryFtor, typename... HandlerTs>
865 Expected<T> handleExpected(Expected<T> ValOrErr, RecoveryFtor &&RecoveryPath,
866  HandlerTs &&... Handlers) {
867  if (ValOrErr)
868  return ValOrErr;
869 
870  if (auto Err = handleErrors(ValOrErr.takeError(),
871  std::forward<HandlerTs>(Handlers)...))
872  return std::move(Err);
873 
874  return RecoveryPath();
875 }
876 
888 void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner = {});
889 
892 inline std::string toString(Error E) {
894  handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) {
895  Errors.push_back(EI.message());
896  });
897  return join(Errors.begin(), Errors.end(), "\n");
898 }
899 
907 inline void consumeError(Error Err) {
908  handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {});
909 }
910 
916 inline bool errorToBool(Error Err) {
917  bool IsError = static_cast<bool>(Err);
918  if (IsError)
919  consumeError(std::move(Err));
920  return IsError;
921 }
922 
948 public:
949  ErrorAsOutParameter(Error *Err) : Err(Err) {
950  // Raise the checked bit if Err is success.
951  if (Err)
952  (void)!!*Err;
953  }
954 
956  // Clear the checked bit.
957  if (Err && !*Err)
958  *Err = Error::success();
959  }
960 
961 private:
962  Error *Err;
963 };
964 
968 template <typename T>
970 public:
972  : ValOrErr(ValOrErr) {
973  if (ValOrErr)
974  (void)!!*ValOrErr;
975  }
976 
978  if (ValOrErr)
979  ValOrErr->setUnchecked();
980  }
981 
982 private:
983  Expected<T> *ValOrErr;
984 };
985 
991 class ECError : public ErrorInfo<ECError> {
992  friend Error errorCodeToError(std::error_code);
993 
994  virtual void anchor() override;
995 
996 public:
997  void setErrorCode(std::error_code EC) { this->EC = EC; }
998  std::error_code convertToErrorCode() const override { return EC; }
999  void log(raw_ostream &OS) const override { OS << EC.message(); }
1000 
1001  // Used by ErrorInfo::classID.
1002  static char ID;
1003 
1004 protected:
1005  ECError() = default;
1006  ECError(std::error_code EC) : EC(EC) {}
1007 
1008  std::error_code EC;
1009 };
1010 
1017 std::error_code inconvertibleErrorCode();
1018 
1020 Error errorCodeToError(std::error_code EC);
1021 
1026 std::error_code errorToErrorCode(Error Err);
1027 
1029 template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) {
1030  if (auto EC = EO.getError())
1031  return errorCodeToError(EC);
1032  return std::move(*EO);
1033 }
1034 
1036 template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) {
1037  if (auto Err = E.takeError())
1038  return errorToErrorCode(std::move(Err));
1039  return std::move(*E);
1040 }
1041 
1066 class StringError : public ErrorInfo<StringError> {
1067 public:
1068  static char ID;
1069 
1070  // Prints EC + S and converts to EC
1071  StringError(std::error_code EC, const Twine &S = Twine());
1072 
1073  // Prints S and converts to EC
1074  StringError(const Twine &S, std::error_code EC);
1075 
1076  void log(raw_ostream &OS) const override;
1077  std::error_code convertToErrorCode() const override;
1078 
1079  const std::string &getMessage() const { return Msg; }
1080 
1081 private:
1082  std::string Msg;
1083  std::error_code EC;
1084  const bool PrintMsgOnly = false;
1085 };
1086 
1088 template <typename... Ts>
1089 Error createStringError(std::error_code EC, char const *Fmt,
1090  const Ts &... Vals) {
1091  std::string Buffer;
1092  raw_string_ostream Stream(Buffer);
1093  Stream << format(Fmt, Vals...);
1094  return make_error<StringError>(Stream.str(), EC);
1095 }
1096 
1097 Error createStringError(std::error_code EC, char const *Msg);
1098 
1103 class FileError final : public ErrorInfo<FileError> {
1104 
1105  friend Error createFileError(std::string, Error);
1106 
1107 public:
1108  void log(raw_ostream &OS) const override {
1109  assert(Err && !FileName.empty() && "Trying to log after takeError().");
1110  OS << "'" << FileName << "': ";
1111  Err->log(OS);
1112  }
1113 
1114  Error takeError() { return Error(std::move(Err)); }
1115 
1116  std::error_code convertToErrorCode() const override;
1117 
1118  // Used by ErrorInfo::classID.
1119  static char ID;
1120 
1121 private:
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.");
1126  FileName = F;
1127  Err = std::move(E);
1128  }
1129 
1130  static Error build(std::string F, Error E) {
1131  return Error(std::unique_ptr<FileError>(new FileError(F, E.takePayload())));
1132  }
1133 
1134  std::string FileName;
1135  std::unique_ptr<ErrorInfoBase> Err;
1136 };
1137 
1140 inline Error createFileError(std::string F, Error E) {
1141  return FileError::build(F, std::move(E));
1142 }
1143 
1144 Error createFileError(std::string F, ErrorSuccess) = delete;
1145 
1151 public:
1153  ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1)
1154  : Banner(std::move(Banner)),
1155  GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {}
1156 
1158  void setBanner(std::string Banner) { this->Banner = std::move(Banner); }
1159 
1161  void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) {
1162  this->GetExitCode = std::move(GetExitCode);
1163  }
1164 
1166  void operator()(Error Err) const { checkError(std::move(Err)); }
1167 
1170  template <typename T> T operator()(Expected<T> &&E) const {
1171  checkError(E.takeError());
1172  return std::move(*E);
1173  }
1174 
1177  template <typename T> T& operator()(Expected<T&> &&E) const {
1178  checkError(E.takeError());
1179  return *E;
1180  }
1181 
1182 private:
1183  void checkError(Error Err) const {
1184  if (Err) {
1185  int ExitCode = GetExitCode(Err);
1186  logAllUnhandledErrors(std::move(Err), errs(), Banner);
1187  exit(ExitCode);
1188  }
1189  }
1190 
1191  std::string Banner;
1192  std::function<int(const Error &)> GetExitCode;
1193 };
1194 
1195 } // end namespace wpi
1196 
1197 #endif // WPIUTIL_WPI_ERROR_H
wpi::errorToErrorCode
std::error_code errorToErrorCode(Error Err)
Helper for converting an ECError to a std::error_code.
wpi::report_fatal_error
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
wpi::make_error
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition: Error.h:300
wpi::ECError::convertToErrorCode
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
Definition: Error.h:998
wpi::ExitOnError::ExitOnError
ExitOnError(std::string Banner="", int DefaultErrorExitCode=1)
Create an error on exit helper.
Definition: Error.h:1153
wpi::StringError::log
void log(raw_ostream &OS) const override
Print an error message to an output stream.
wpi::Expected::operator->
const_pointer operator->() const
Returns a const pointer to the stored T value.
Definition: Error.h:522
wpi::errorOrToExpected
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
Definition: Error.h:1029
wpi::handleErrors
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
Definition: Error.h:807
wpi::ExitOnError::operator()
void operator()(Error Err) const
Check Err. If it's in a failure state log the error(s) and exit.
Definition: Error.h:1166
wpi::Expected::get
const_reference get() const
Returns a const reference to the stored T value.
Definition: Error.h:497
wpi::Expected::Expected
Expected(Error Err)
Create an Expected<T> error value from the given Error.
Definition: Error.h:425
wpi::expectedToErrorOr
ErrorOr< T > expectedToErrorOr(Expected< T > &&E)
Convert an Expected<T> to an ErrorOr<T>.
Definition: Error.h:1036
wpi::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:132
wpi::ErrorInfoBase::convertToErrorCode
virtual std::error_code convertToErrorCode() const =0
Convert this error to a std::error_code.
wpi::ECError
This class wraps a std::error_code in a Error.
Definition: Error.h:991
wpi::Error::Error
Error(Error &&Other) noexcept
Move-construct an error value.
Definition: Error.h:186
wpi::ErrorInfo
Base class for user error types.
Definition: Error.h:314
wpi::Expected::Expected
Expected(Expected< OtherT > &&Other, typename std::enable_if< std::is_convertible< OtherT, T >::value >::type *=nullptr)
Move construct an Expected<T> value from an Expected<OtherT>, where OtherT must be convertible to T.
Definition: Error.h:454
wpi::Expected::get
reference get()
Returns a reference to the stored T value.
Definition: Error.h:491
wpi::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:511
wpi::Expected::errorIsA
bool errorIsA() const
Check that this Expected<T> is an error of type ErrT.
Definition: Error.h:503
wpi::ExpectedAsOutParameter
Helper for Expected<T>s used as out-parameters.
Definition: Error.h:969
wpi::ErrorList::handleErrors
friend Error handleErrors(Error E, HandlerTs &&... Handlers)
Pass the ErrorInfo(s) contained in E to their respective handlers.
Definition: Error.h:807
wpi::Expected::operator*
const_reference operator*() const
Returns a const reference to the stored T value.
Definition: Error.h:534
wpi::FileError::createFileError
friend Error createFileError(std::string, Error)
Concatenate a source file path and/or name with an Error.
Definition: Error.h:1140
wpi::ExitOnError::setExitCodeMapper
void setExitCodeMapper(std::function< int(const Error &)> GetExitCode)
Set the exit-code mapper function.
Definition: Error.h:1161
wpi::toString
std::string toString(Error E)
Write all error messages (if any) in E to a string.
Definition: Error.h:892
wpi::ErrorOr
Represents either an error or a value T.
Definition: ErrorOr.h:57
wpi::errorToBool
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
Definition: Error.h:916
wpi::raw_string_ostream::str
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
Definition: raw_ostream.h:513
wpi::ErrorAsOutParameter
Helper for Errors used as out-parameters.
Definition: Error.h:947
wpi::FileError::log
void log(raw_ostream &OS) const override
Print an error message to an output stream.
Definition: Error.h:1108
wpi::Expected::~Expected
~Expected()
Destroy an Expected<T>.
Definition: Error.h:477
wpi::Error::operator=
Error & operator=(Error &&Other) noexcept
Move-assign an error value.
Definition: Error.h:205
wpi::errorCodeToError
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
wpi::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
wpi::ErrorInfoBase::log
virtual void log(raw_ostream &OS) const =0
Print an error message to an output stream.
wpi::handleExpected
Expected< T > handleExpected(Expected< T > ValOrErr, RecoveryFtor &&RecoveryPath, HandlerTs &&... Handlers)
Handle any errors (if present) in an Expected<T>, then try a recovery path.
Definition: Error.h:865
wpi
WPILib C++ utilities (wpiutil) namespace.
Definition: EventLoopRunner.h:17
wpi::Error::~Error
~Error()
Destroy a Error.
Definition: Error.h:222
wpi::Expected
Tagged union holding either a T or a Error.
Definition: Error.h:403
wpi::StringError
This class wraps a string in an Error.
Definition: Error.h:1066
wpi::Expected::Expected
Expected(Expected< OtherT > &&Other, typename std::enable_if<!std::is_convertible< OtherT, T >::value >::type *=nullptr)
Move construct an Expected<T> value from an Expected<OtherT>, where OtherT isn't convertible to T.
Definition: Error.h:463
wpi::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:497
wpi::ExitOnError::operator()
T & operator()(Expected< T & > &&E) const
Check E.
Definition: Error.h:1177
wpi::ErrorHandlerTraits
Helper for testing applicability of, and applying, handlers for ErrorInfo types.
Definition: Error.h:688
wpi::Expected::Expected
Expected(Expected &&Other)
Move construct an Expected<T> value.
Definition: Error.h:449
wpi::cantFail
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:629
ErrorOr.h
wpi::Error::Error
Error()
Create a success value. Prefer using 'Error::success()' for readability.
Definition: Error.h:171
wpi::operator<<
raw_ostream & operator<<(raw_ostream &Out, const VersionTuple &V)
Print a version number.
wpi::Expected::Expected
Expected(OtherT &&Val, typename std::enable_if< std::is_convertible< OtherT, T >::value >::type *=nullptr)
Create an Expected<T> success value from the given OtherT value, which must be convertible to T.
Definition: Error.h:440
wpi::Expected::operator=
Expected & operator=(Expected &&Other)
Move-assign from another Expected<T>.
Definition: Error.h:471
wpi::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1089
wpi::FileError
This class wraps a filename and another Error.
Definition: Error.h:1103
wpi::ErrorList
Special ErrorInfo subclass representing a list of ErrorInfos.
Definition: Error.h:329
wpi::ErrorInfoBase::message
virtual std::string message() const
Return the error message as a string.
Definition: Error.h:54
wpi::Expected::operator*
reference operator*()
Returns a reference to the stored T value.
Definition: Error.h:528
wpi::handleAllErrors
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Definition: Error.h:830
wpi::join
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
Definition: StringExtras.h:374
wpi::ExitOnError::setBanner
void setBanner(std::string Banner)
Set the banner string for any errors caught by operator().
Definition: Error.h:1158
wpi::ErrorList::convertToErrorCode
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
wpi::errs
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
wpi::joinErrors
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:393
wpi::FileError::convertToErrorCode
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
wpi::createFileError
Error createFileError(std::string F, Error E)
Concatenate a source file path and/or name with an Error.
Definition: Error.h:1140
wpi::ErrorList::log
void log(raw_ostream &OS) const override
Print an error message to an output stream.
Definition: Error.h:339
wpi::inconvertibleErrorCode
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
wpi::logAllUnhandledErrors
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
wpi::ECError::errorCodeToError
friend Error errorCodeToError(std::error_code)
Helper for converting an std::error_code to a Error.
wpi::Expected::operator->
pointer operator->()
Returns a pointer to the stored T value.
Definition: Error.h:516
wpi::ErrorList::joinErrors
friend Error joinErrors(Error, Error)
Concatenate errors.
Definition: Error.h:393
wpi::ExitOnError::operator()
T operator()(Expected< T > &&E) const
Check E.
Definition: Error.h:1170
wpi::SmallVector< std::string, 2 >
wpi::ErrorInfoBase
Base class for error info classes.
Definition: Error.h:46
wpi::Error::Error
Error(std::unique_ptr< ErrorInfoBase > Payload)
Create an error value.
Definition: Error.h:193
wpi::ExitOnError
Helper for check-and-exit error handling.
Definition: Error.h:1150
wpi::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:47
wpi::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:85
wpi::StringError::convertToErrorCode
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
wpi::consumeError
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:907
wpi::Error::isA
bool isA() const
Check whether one error is a subclass of another.
Definition: Error.h:236
wpi::ErrorSuccess
Subclass of Error for the sole purpose of identifying the success path in the type system.
Definition: Error.h:294
wpi::ECError::log
void log(raw_ostream &OS) const override
Print an error message to an output stream.
Definition: Error.h:999
wpi::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:296
wpi::Error::dynamicClassID
const void * dynamicClassID() const
Returns the dynamic class id of this error, or null if this is a success value.
Definition: Error.h:242