llvm.org GIT mirror llvm / a69b2ae
[Support] Rewrite handleAllErrors in terms of cantFail. This just switches handleAllErrors from using custom assertions that all errors have been handled to using cantFail. This change involves moving some of the class and function definitions around though. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@311631 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 2 years ago
2 changed file(s) with 375 addition(s) and 376 deletion(s). Raw diff Collapse all Expand all
406406 return ErrorList::join(std::move(E1), std::move(E2));
407407 }
408408
409 /// Helper for testing applicability of, and applying, handlers for
410 /// ErrorInfo types.
411 template
412 class ErrorHandlerTraits
413 : public ErrorHandlerTraits
414 &std::remove_reference::type::operator())> {};
415
416 // Specialization functions of the form 'Error (const ErrT&)'.
417 template class ErrorHandlerTraits {
418 public:
419 static bool appliesTo(const ErrorInfoBase &E) {
420 return E.template isA();
421 }
422
423 template
424 static Error apply(HandlerT &&H, std::unique_ptr E) {
425 assert(appliesTo(*E) && "Applying incorrect handler");
426 return H(static_cast(*E));
427 }
428 };
429
430 // Specialization functions of the form 'void (const ErrT&)'.
431 template class ErrorHandlerTraits {
432 public:
433 static bool appliesTo(const ErrorInfoBase &E) {
434 return E.template isA();
435 }
436
437 template
438 static Error apply(HandlerT &&H, std::unique_ptr E) {
439 assert(appliesTo(*E) && "Applying incorrect handler");
440 H(static_cast(*E));
441 return Error::success();
442 }
443 };
444
445 /// Specialization for functions of the form 'Error (std::unique_ptr)'.
446 template
447 class ErrorHandlerTraits)> {
448 public:
449 static bool appliesTo(const ErrorInfoBase &E) {
450 return E.template isA();
451 }
452
453 template
454 static Error apply(HandlerT &&H, std::unique_ptr E) {
455 assert(appliesTo(*E) && "Applying incorrect handler");
456 std::unique_ptr SubE(static_cast(E.release()));
457 return H(std::move(SubE));
458 }
459 };
460
461 /// Specialization for functions of the form 'Error (std::unique_ptr)'.
462 template
463 class ErrorHandlerTraits)> {
464 public:
465 static bool appliesTo(const ErrorInfoBase &E) {
466 return E.template isA();
467 }
468
469 template
470 static Error apply(HandlerT &&H, std::unique_ptr E) {
471 assert(appliesTo(*E) && "Applying incorrect handler");
472 std::unique_ptr SubE(static_cast(E.release()));
473 H(std::move(SubE));
474 return Error::success();
475 }
476 };
477
478 // Specialization for member functions of the form 'RetT (const ErrT&)'.
479 template
480 class ErrorHandlerTraits
481 : public ErrorHandlerTraits {};
482
483 // Specialization for member functions of the form 'RetT (const ErrT&) const'.
484 template
485 class ErrorHandlerTraits
486 : public ErrorHandlerTraits {};
487
488 // Specialization for member functions of the form 'RetT (const ErrT&)'.
489 template
490 class ErrorHandlerTraits
491 : public ErrorHandlerTraits {};
492
493 // Specialization for member functions of the form 'RetT (const ErrT&) const'.
494 template
495 class ErrorHandlerTraits
496 : public ErrorHandlerTraits {};
497
498 /// Specialization for member functions of the form
499 /// 'RetT (std::unique_ptr) const'.
500 template
501 class ErrorHandlerTraits)>
502 : public ErrorHandlerTraits)> {};
503
504 /// Specialization for member functions of the form
505 /// 'RetT (std::unique_ptr) const'.
506 template
507 class ErrorHandlerTraits) const>
508 : public ErrorHandlerTraits)> {};
509
510 inline Error handleErrorImpl(std::unique_ptr Payload) {
511 return Error(std::move(Payload));
512 }
513
514 template
515 Error handleErrorImpl(std::unique_ptr Payload,
516 HandlerT &&Handler, HandlerTs &&... Handlers) {
517 if (ErrorHandlerTraits::appliesTo(*Payload))
518 return ErrorHandlerTraits::apply(std::forward(Handler),
519 std::move(Payload));
520 return handleErrorImpl(std::move(Payload),
521 std::forward(Handlers)...);
522 }
523
524 /// Pass the ErrorInfo(s) contained in E to their respective handlers. Any
525 /// unhandled errors (or Errors returned by handlers) are re-concatenated and
526 /// returned.
527 /// Because this function returns an error, its result must also be checked
528 /// or returned. If you intend to handle all errors use handleAllErrors
529 /// (which returns void, and will abort() on unhandled errors) instead.
530 template
531 Error handleErrors(Error E, HandlerTs &&... Hs) {
532 if (!E)
533 return Error::success();
534
535 std::unique_ptr Payload = E.takePayload();
536
537 if (Payload->isA()) {
538 ErrorList &List = static_cast(*Payload);
539 Error R;
540 for (auto &P : List.Payloads)
541 R = ErrorList::join(
542 std::move(R),
543 handleErrorImpl(std::move(P), std::forward(Hs)...));
544 return R;
545 }
546
547 return handleErrorImpl(std::move(Payload), std::forward(Hs)...);
548 }
549
550 /// Behaves the same as handleErrors, except that it requires that all
551 /// errors be handled by the given handlers. If any unhandled error remains
552 /// after the handlers have run, abort() will be called.
553 template
554 void handleAllErrors(Error E, HandlerTs &&... Handlers) {
555 auto F = handleErrors(std::move(E), std::forward(Handlers)...);
556 // Cast 'F' to bool to set the 'Checked' flag if it's a success value:
557 (void)!F;
558 }
559
560 /// Check that E is a non-error, then drop it.
561 inline void handleAllErrors(Error E) {
562 // Cast 'E' to a bool to set the 'Checked' flag if it's a success value:
563 (void)!E;
564 }
565
566 /// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner
567 /// will be printed before the first one is logged. A newline will be printed
568 /// after each error.
569 ///
570 /// This is useful in the base level of your program to allow clean termination
571 /// (allowing clean deallocation of resources, etc.), while reporting error
572 /// information to the user.
573 void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner);
574
575 /// Write all error messages (if any) in E to a string. The newline character
576 /// is used to separate error messages.
577 inline std::string toString(Error E) {
578 SmallVector Errors;
579 handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) {
580 Errors.push_back(EI.message());
581 });
582 return join(Errors.begin(), Errors.end(), "\n");
583 }
584
585 /// Consume a Error without doing anything. This method should be used
586 /// only where an error can be considered a reasonable and expected return
587 /// value.
588 ///
589 /// Uses of this method are potentially indicative of design problems: If it's
590 /// legitimate to do nothing while processing an "error", the error-producer
591 /// might be more clearly refactored to return an Optional.
592 inline void consumeError(Error Err) {
593 handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {});
594 }
595
596 /// Helper for Errors used as out-parameters.
597 ///
598 /// This helper is for use with the Error-as-out-parameter idiom, where an error
599 /// is passed to a function or method by reference, rather than being returned.
600 /// In such cases it is helpful to set the checked bit on entry to the function
601 /// so that the error can be written to (unchecked Errors abort on assignment)
602 /// and clear the checked bit on exit so that clients cannot accidentally forget
603 /// to check the result. This helper performs these actions automatically using
604 /// RAII:
605 ///
606 /// @code{.cpp}
607 /// Result foo(Error &Err) {
608 /// ErrorAsOutParameter ErrAsOutParam(&Err); // 'Checked' flag set
609 /// //
610 /// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed.
611 /// }
612 /// @endcode
613 ///
614 /// ErrorAsOutParameter takes an Error* rather than Error& so that it can be
615 /// used with optional Errors (Error pointers that are allowed to be null). If
616 /// ErrorAsOutParameter took an Error reference, an instance would have to be
617 /// created inside every condition that verified that Error was non-null. By
618 /// taking an Error pointer we can just create one instance at the top of the
619 /// function.
620 class ErrorAsOutParameter {
621 public:
622 ErrorAsOutParameter(Error *Err) : Err(Err) {
623 // Raise the checked bit if Err is success.
624 if (Err)
625 (void)!!*Err;
626 }
627
628 ~ErrorAsOutParameter() {
629 // Clear the checked bit.
630 if (Err && !*Err)
631 *Err = Error::success();
632 }
633
634 private:
635 Error *Err;
636 };
637
638409 /// Tagged union holding either a T or a Error.
639410 ///
640411 /// This class parallels ErrorOr, but replaces error_code with Error. Since
886657 #endif
887658 };
888659
889 /// Helper for Expecteds used as out-parameters.
890 ///
891 /// See ErrorAsOutParameter.
892 template
893 class ExpectedAsOutParameter {
894 public:
895 ExpectedAsOutParameter(Expected *ValOrErr)
896 : ValOrErr(ValOrErr) {
897 if (ValOrErr)
898 (void)!!*ValOrErr;
899 }
900
901 ~ExpectedAsOutParameter() {
902 if (ValOrErr)
903 ValOrErr->setUnchecked();
904 }
905
906 private:
907 Expected *ValOrErr;
908 };
909
910 /// This class wraps a std::error_code in a Error.
911 ///
912 /// This is useful if you're writing an interface that returns a Error
913 /// (or Expected) and you want to call code that still returns
914 /// std::error_codes.
915 class ECError : public ErrorInfo {
916 friend Error errorCodeToError(std::error_code);
917
918 public:
919 void setErrorCode(std::error_code EC) { this->EC = EC; }
920 std::error_code convertToErrorCode() const override { return EC; }
921 void log(raw_ostream &OS) const override { OS << EC.message(); }
922
923 // Used by ErrorInfo::classID.
924 static char ID;
925
926 protected:
927 ECError() = default;
928 ECError(std::error_code EC) : EC(EC) {}
929
930 std::error_code EC;
931 };
932
933 /// The value returned by this function can be returned from convertToErrorCode
934 /// for Error values where no sensible translation to std::error_code exists.
935 /// It should only be used in this situation, and should never be used where a
936 /// sensible conversion to std::error_code is available, as attempts to convert
937 /// to/from this error will result in a fatal error. (i.e. it is a programmatic
938 ///error to try to convert such a value).
939 std::error_code inconvertibleErrorCode();
940
941 /// Helper for converting an std::error_code to a Error.
942 Error errorCodeToError(std::error_code EC);
943
944 /// Helper for converting an ECError to a std::error_code.
945 ///
946 /// This method requires that Err be Error() or an ECError, otherwise it
947 /// will trigger a call to abort().
948 std::error_code errorToErrorCode(Error Err);
949
950 /// Convert an ErrorOr to an Expected.
951 template Expected errorOrToExpected(ErrorOr &&EO) {
952 if (auto EC = EO.getError())
953 return errorCodeToError(EC);
954 return std::move(*EO);
955 }
956
957 /// Convert an Expected to an ErrorOr.
958 template ErrorOr expectedToErrorOr(Expected &&E) {
959 if (auto Err = E.takeError())
960 return errorToErrorCode(std::move(Err));
961 return std::move(*E);
962 }
963
964 /// This class wraps a string in an Error.
965 ///
966 /// StringError is useful in cases where the client is not expected to be able
967 /// to consume the specific error message programmatically (for example, if the
968 /// error message is to be presented to the user).
969 class StringError : public ErrorInfo {
970 public:
971 static char ID;
972
973 StringError(const Twine &S, std::error_code EC);
974
975 void log(raw_ostream &OS) const override;
976 std::error_code convertToErrorCode() const override;
977
978 const std::string &getMessage() const { return Msg; }
979
980 private:
981 std::string Msg;
982 std::error_code EC;
983 };
984
985 /// Helper for check-and-exit error handling.
986 ///
987 /// For tool use only. NOT FOR USE IN LIBRARY CODE.
988 ///
989 class ExitOnError {
990 public:
991 /// Create an error on exit helper.
992 ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1)
993 : Banner(std::move(Banner)),
994 GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {}
995
996 /// Set the banner string for any errors caught by operator().
997 void setBanner(std::string Banner) { this->Banner = std::move(Banner); }
998
999 /// Set the exit-code mapper function.
1000 void setExitCodeMapper(std::function GetExitCode) {
1001 this->GetExitCode = std::move(GetExitCode);
1002 }
1003
1004 /// Check Err. If it's in a failure state log the error(s) and exit.
1005 void operator()(Error Err) const { checkError(std::move(Err)); }
1006
1007 /// Check E. If it's in a success state then return the contained value. If
1008 /// it's in a failure state log the error(s) and exit.
1009 template T operator()(Expected &&E) const {
1010 checkError(E.takeError());
1011 return std::move(*E);
1012 }
1013
1014 /// Check E. If it's in a success state then return the contained reference. If
1015 /// it's in a failure state log the error(s) and exit.
1016 template T& operator()(Expected &&E) const {
1017 checkError(E.takeError());
1018 return *E;
1019 }
1020
1021 private:
1022 void checkError(Error Err) const {
1023 if (Err) {
1024 int ExitCode = GetExitCode(Err);
1025 logAllUnhandledErrors(std::move(Err), errs(), Banner);
1026 exit(ExitCode);
1027 }
1028 }
1029
1030 std::string Banner;
1031 std::function GetExitCode;
1032 };
1033
1034660 /// Report a serious error, calling any installed error handler. See
1035661 /// ErrorHandling.h.
1036662 LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err,
1096722 llvm_unreachable("Failure value returned from cantFail wrapped call");
1097723 }
1098724
725 /// Helper for testing applicability of, and applying, handlers for
726 /// ErrorInfo types.
727 template
728 class ErrorHandlerTraits
729 : public ErrorHandlerTraits
730 &std::remove_reference::type::operator())> {};
731
732 // Specialization functions of the form 'Error (const ErrT&)'.
733 template class ErrorHandlerTraits {
734 public:
735 static bool appliesTo(const ErrorInfoBase &E) {
736 return E.template isA();
737 }
738
739 template
740 static Error apply(HandlerT &&H, std::unique_ptr E) {
741 assert(appliesTo(*E) && "Applying incorrect handler");
742 return H(static_cast(*E));
743 }
744 };
745
746 // Specialization functions of the form 'void (const ErrT&)'.
747 template class ErrorHandlerTraits {
748 public:
749 static bool appliesTo(const ErrorInfoBase &E) {
750 return E.template isA();
751 }
752
753 template
754 static Error apply(HandlerT &&H, std::unique_ptr E) {
755 assert(appliesTo(*E) && "Applying incorrect handler");
756 H(static_cast(*E));
757 return Error::success();
758 }
759 };
760
761 /// Specialization for functions of the form 'Error (std::unique_ptr)'.
762 template
763 class ErrorHandlerTraits)> {
764 public:
765 static bool appliesTo(const ErrorInfoBase &E) {
766 return E.template isA();
767 }
768
769 template
770 static Error apply(HandlerT &&H, std::unique_ptr E) {
771 assert(appliesTo(*E) && "Applying incorrect handler");
772 std::unique_ptr SubE(static_cast(E.release()));
773 return H(std::move(SubE));
774 }
775 };
776
777 /// Specialization for functions of the form 'Error (std::unique_ptr)'.
778 template
779 class ErrorHandlerTraits)> {
780 public:
781 static bool appliesTo(const ErrorInfoBase &E) {
782 return E.template isA();
783 }
784
785 template
786 static Error apply(HandlerT &&H, std::unique_ptr E) {
787 assert(appliesTo(*E) && "Applying incorrect handler");
788 std::unique_ptr SubE(static_cast(E.release()));
789 H(std::move(SubE));
790 return Error::success();
791 }
792 };
793
794 // Specialization for member functions of the form 'RetT (const ErrT&)'.
795 template
796 class ErrorHandlerTraits
797 : public ErrorHandlerTraits {};
798
799 // Specialization for member functions of the form 'RetT (const ErrT&) const'.
800 template
801 class ErrorHandlerTraits
802 : public ErrorHandlerTraits {};
803
804 // Specialization for member functions of the form 'RetT (const ErrT&)'.
805 template
806 class ErrorHandlerTraits
807 : public ErrorHandlerTraits {};
808
809 // Specialization for member functions of the form 'RetT (const ErrT&) const'.
810 template
811 class ErrorHandlerTraits
812 : public ErrorHandlerTraits {};
813
814 /// Specialization for member functions of the form
815 /// 'RetT (std::unique_ptr) const'.
816 template
817 class ErrorHandlerTraits)>
818 : public ErrorHandlerTraits)> {};
819
820 /// Specialization for member functions of the form
821 /// 'RetT (std::unique_ptr) const'.
822 template
823 class ErrorHandlerTraits) const>
824 : public ErrorHandlerTraits)> {};
825
826 inline Error handleErrorImpl(std::unique_ptr Payload) {
827 return Error(std::move(Payload));
828 }
829
830 template
831 Error handleErrorImpl(std::unique_ptr Payload,
832 HandlerT &&Handler, HandlerTs &&... Handlers) {
833 if (ErrorHandlerTraits::appliesTo(*Payload))
834 return ErrorHandlerTraits::apply(std::forward(Handler),
835 std::move(Payload));
836 return handleErrorImpl(std::move(Payload),
837 std::forward(Handlers)...);
838 }
839
840 /// Pass the ErrorInfo(s) contained in E to their respective handlers. Any
841 /// unhandled errors (or Errors returned by handlers) are re-concatenated and
842 /// returned.
843 /// Because this function returns an error, its result must also be checked
844 /// or returned. If you intend to handle all errors use handleAllErrors
845 /// (which returns void, and will abort() on unhandled errors) instead.
846 template
847 Error handleErrors(Error E, HandlerTs &&... Hs) {
848 if (!E)
849 return Error::success();
850
851 std::unique_ptr Payload = E.takePayload();
852
853 if (Payload->isA()) {
854 ErrorList &List = static_cast(*Payload);
855 Error R;
856 for (auto &P : List.Payloads)
857 R = ErrorList::join(
858 std::move(R),
859 handleErrorImpl(std::move(P), std::forward(Hs)...));
860 return R;
861 }
862
863 return handleErrorImpl(std::move(Payload), std::forward(Hs)...);
864 }
865
866 /// Behaves the same as handleErrors, except that it requires that all
867 /// errors be handled by the given handlers. If any unhandled error remains
868 /// after the handlers have run, report_fatal_error() will be called.
869 template
870 void handleAllErrors(Error E, HandlerTs &&... Handlers) {
871 cantFail(handleErrors(std::move(E), std::forward(Handlers)...));
872 }
873
874 /// Check that E is a non-error, then drop it.
875 /// If E is an error report_fatal_error will be called.
876 inline void handleAllErrors(Error E) {
877 cantFail(std::move(E));
878 }
879
880 /// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner
881 /// will be printed before the first one is logged. A newline will be printed
882 /// after each error.
883 ///
884 /// This is useful in the base level of your program to allow clean termination
885 /// (allowing clean deallocation of resources, etc.), while reporting error
886 /// information to the user.
887 void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner);
888
889 /// Write all error messages (if any) in E to a string. The newline character
890 /// is used to separate error messages.
891 inline std::string toString(Error E) {
892 SmallVector Errors;
893 handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) {
894 Errors.push_back(EI.message());
895 });
896 return join(Errors.begin(), Errors.end(), "\n");
897 }
898
899 /// Consume a Error without doing anything. This method should be used
900 /// only where an error can be considered a reasonable and expected return
901 /// value.
902 ///
903 /// Uses of this method are potentially indicative of design problems: If it's
904 /// legitimate to do nothing while processing an "error", the error-producer
905 /// might be more clearly refactored to return an Optional.
906 inline void consumeError(Error Err) {
907 handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {});
908 }
909
910 /// Helper for Errors used as out-parameters.
911 ///
912 /// This helper is for use with the Error-as-out-parameter idiom, where an error
913 /// is passed to a function or method by reference, rather than being returned.
914 /// In such cases it is helpful to set the checked bit on entry to the function
915 /// so that the error can be written to (unchecked Errors abort on assignment)
916 /// and clear the checked bit on exit so that clients cannot accidentally forget
917 /// to check the result. This helper performs these actions automatically using
918 /// RAII:
919 ///
920 /// @code{.cpp}
921 /// Result foo(Error &Err) {
922 /// ErrorAsOutParameter ErrAsOutParam(&Err); // 'Checked' flag set
923 /// //
924 /// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed.
925 /// }
926 /// @endcode
927 ///
928 /// ErrorAsOutParameter takes an Error* rather than Error& so that it can be
929 /// used with optional Errors (Error pointers that are allowed to be null). If
930 /// ErrorAsOutParameter took an Error reference, an instance would have to be
931 /// created inside every condition that verified that Error was non-null. By
932 /// taking an Error pointer we can just create one instance at the top of the
933 /// function.
934 class ErrorAsOutParameter {
935 public:
936 ErrorAsOutParameter(Error *Err) : Err(Err) {
937 // Raise the checked bit if Err is success.
938 if (Err)
939 (void)!!*Err;
940 }
941
942 ~ErrorAsOutParameter() {
943 // Clear the checked bit.
944 if (Err && !*Err)
945 *Err = Error::success();
946 }
947
948 private:
949 Error *Err;
950 };
951
952 /// Helper for Expecteds used as out-parameters.
953 ///
954 /// See ErrorAsOutParameter.
955 template
956 class ExpectedAsOutParameter {
957 public:
958 ExpectedAsOutParameter(Expected *ValOrErr)
959 : ValOrErr(ValOrErr) {
960 if (ValOrErr)
961 (void)!!*ValOrErr;
962 }
963
964 ~ExpectedAsOutParameter() {
965 if (ValOrErr)
966 ValOrErr->setUnchecked();
967 }
968
969 private:
970 Expected *ValOrErr;
971 };
972
973 /// This class wraps a std::error_code in a Error.
974 ///
975 /// This is useful if you're writing an interface that returns a Error
976 /// (or Expected) and you want to call code that still returns
977 /// std::error_codes.
978 class ECError : public ErrorInfo {
979 friend Error errorCodeToError(std::error_code);
980
981 public:
982 void setErrorCode(std::error_code EC) { this->EC = EC; }
983 std::error_code convertToErrorCode() const override { return EC; }
984 void log(raw_ostream &OS) const override { OS << EC.message(); }
985
986 // Used by ErrorInfo::classID.
987 static char ID;
988
989 protected:
990 ECError() = default;
991 ECError(std::error_code EC) : EC(EC) {}
992
993 std::error_code EC;
994 };
995
996 /// The value returned by this function can be returned from convertToErrorCode
997 /// for Error values where no sensible translation to std::error_code exists.
998 /// It should only be used in this situation, and should never be used where a
999 /// sensible conversion to std::error_code is available, as attempts to convert
1000 /// to/from this error will result in a fatal error. (i.e. it is a programmatic
1001 ///error to try to convert such a value).
1002 std::error_code inconvertibleErrorCode();
1003
1004 /// Helper for converting an std::error_code to a Error.
1005 Error errorCodeToError(std::error_code EC);
1006
1007 /// Helper for converting an ECError to a std::error_code.
1008 ///
1009 /// This method requires that Err be Error() or an ECError, otherwise it
1010 /// will trigger a call to abort().
1011 std::error_code errorToErrorCode(Error Err);
1012
1013 /// Convert an ErrorOr to an Expected.
1014 template Expected errorOrToExpected(ErrorOr &&EO) {
1015 if (auto EC = EO.getError())
1016 return errorCodeToError(EC);
1017 return std::move(*EO);
1018 }
1019
1020 /// Convert an Expected to an ErrorOr.
1021 template ErrorOr expectedToErrorOr(Expected &&E) {
1022 if (auto Err = E.takeError())
1023 return errorToErrorCode(std::move(Err));
1024 return std::move(*E);
1025 }
1026
1027 /// This class wraps a string in an Error.
1028 ///
1029 /// StringError is useful in cases where the client is not expected to be able
1030 /// to consume the specific error message programmatically (for example, if the
1031 /// error message is to be presented to the user).
1032 class StringError : public ErrorInfo {
1033 public:
1034 static char ID;
1035
1036 StringError(const Twine &S, std::error_code EC);
1037
1038 void log(raw_ostream &OS) const override;
1039 std::error_code convertToErrorCode() const override;
1040
1041 const std::string &getMessage() const { return Msg; }
1042
1043 private:
1044 std::string Msg;
1045 std::error_code EC;
1046 };
1047
1048 /// Helper for check-and-exit error handling.
1049 ///
1050 /// For tool use only. NOT FOR USE IN LIBRARY CODE.
1051 ///
1052 class ExitOnError {
1053 public:
1054 /// Create an error on exit helper.
1055 ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1)
1056 : Banner(std::move(Banner)),
1057 GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {}
1058
1059 /// Set the banner string for any errors caught by operator().
1060 void setBanner(std::string Banner) { this->Banner = std::move(Banner); }
1061
1062 /// Set the exit-code mapper function.
1063 void setExitCodeMapper(std::function GetExitCode) {
1064 this->GetExitCode = std::move(GetExitCode);
1065 }
1066
1067 /// Check Err. If it's in a failure state log the error(s) and exit.
1068 void operator()(Error Err) const { checkError(std::move(Err)); }
1069
1070 /// Check E. If it's in a success state then return the contained value. If
1071 /// it's in a failure state log the error(s) and exit.
1072 template T operator()(Expected &&E) const {
1073 checkError(E.takeError());
1074 return std::move(*E);
1075 }
1076
1077 /// Check E. If it's in a success state then return the contained reference. If
1078 /// it's in a failure state log the error(s) and exit.
1079 template T& operator()(Expected &&E) const {
1080 checkError(E.takeError());
1081 return *E;
1082 }
1083
1084 private:
1085 void checkError(Error Err) const {
1086 if (Err) {
1087 int ExitCode = GetExitCode(Err);
1088 logAllUnhandledErrors(std::move(Err), errs(), Banner);
1089 exit(ExitCode);
1090 }
1091 }
1092
1093 std::string Banner;
1094 std::function GetExitCode;
1095 };
1096
10991097 } // end namespace llvm
11001098
11011099 #endif // LLVM_SUPPORT_ERROR_H
385385 });
386386 };
387387
388 EXPECT_DEATH(FailToHandle(), "Program aborted due to an unhandled Error:")
388 EXPECT_DEATH(FailToHandle(),
389 "Failure value returned from cantFail wrapped call")
389390 << "Unhandled Error in handleAllErrors call did not cause an "
390391 "abort()";
391392 }
404405 };
405406
406407 EXPECT_DEATH(ReturnErrorFromHandler(),
407 "Program aborted due to an unhandled Error:")
408 "Failure value returned from cantFail wrapped call")
408409 << " Error returned from handler in handleAllErrors call did not "
409410 "cause abort()";
410411 }