13#ifndef LLVM_SUPPORT_ERROR_H
14#define LLVM_SUPPORT_ERROR_H
18#include "llvm/Config/abi-breaking.h"
33#include <system_error>
73 virtual bool isA(
const void *
const ClassID)
const {
74 return ClassID == classID();
78 template <
typename ErrorInfoT>
bool isA()
const {
79 return isA(ErrorInfoT::classID());
83 virtual void anchor();
166 template <
typename... HandlerTs>
169 template <
typename HandlerT>
198 *
this = std::move(
Other);
203 Error(std::unique_ptr<ErrorInfoBase> Payload) {
204 setPtr(Payload.release());
218 setPtr(
Other.getPtr());
224 Other.setPtr(
nullptr);
225 Other.setChecked(
true);
241 setChecked(
getPtr() ==
nullptr);
242 return getPtr() !=
nullptr;
246 template <
typename ErrT>
bool isA()
const {
255 return getPtr()->dynamicClassID();
259#if LLVM_ENABLE_ABI_BREAKING_CHECKS
265 [[noreturn]]
LLVM_ABI void fatalUncheckedError()
const;
268 void assertIsChecked() {
269#if LLVM_ENABLE_ABI_BREAKING_CHECKS
271 fatalUncheckedError();
275 ErrorInfoBase *
getPtr()
const {
276#if LLVM_ENABLE_ABI_BREAKING_CHECKS
277 return reinterpret_cast<ErrorInfoBase*
>(
278 reinterpret_cast<uintptr_t
>(Payload) &
279 ~
static_cast<uintptr_t
>(0x1));
285 void setPtr(ErrorInfoBase *EI) {
286#if LLVM_ENABLE_ABI_BREAKING_CHECKS
287 Payload =
reinterpret_cast<ErrorInfoBase*
>(
288 (
reinterpret_cast<uintptr_t
>(EI) &
289 ~
static_cast<uintptr_t
>(0x1)) |
290 (
reinterpret_cast<uintptr_t
>(Payload) & 0x1));
296 bool getChecked()
const {
297#if LLVM_ENABLE_ABI_BREAKING_CHECKS
298 return (
reinterpret_cast<uintptr_t
>(Payload) & 0x1) == 0;
304 void setChecked(
bool V) {
305#if LLVM_ENABLE_ABI_BREAKING_CHECKS
306 Payload =
reinterpret_cast<ErrorInfoBase*
>(
307 (
reinterpret_cast<uintptr_t
>(Payload) &
308 ~
static_cast<uintptr_t
>(0x1)) |
313 std::unique_ptr<ErrorInfoBase> takePayload() {
314 std::unique_ptr<ErrorInfoBase> Tmp(
getPtr());
321 if (
auto *
P =
E.getPtr())
341 return Error(std::make_unique<ErrT>(std::forward<ArgTs>(Args)...));
353template <
typename ThisErrT,
typename ParentErrT = ErrorInfoBase>
356 using ParentErrT::ParentErrT;
358 static const void *
classID() {
return &ThisErrT::ID; }
362 bool isA(
const void *
const ClassID)
const override {
363 return ClassID ==
classID() || ParentErrT::isA(ClassID);
372 template <
typename... HandlerTs>
376 template <
typename HandlerT>
384 OS <<
"Multiple errors:\n";
385 for (
const auto &ErrPayload : Payloads) {
391 std::error_code convertToErrorCode()
const override;
397 ErrorList(std::unique_ptr<ErrorInfoBase> Payload1,
398 std::unique_ptr<ErrorInfoBase> Payload2) {
400 "ErrorList constructor payloads should be singleton errors");
401 Payloads.push_back(std::move(Payload1));
402 Payloads.push_back(std::move(Payload2));
415 auto &E1List =
static_cast<ErrorList &
>(*E1.getPtr());
417 auto E2Payload = E2.takePayload();
418 auto &E2List =
static_cast<ErrorList &
>(*E2Payload);
419 for (
auto &Payload : E2List.Payloads)
420 E1List.Payloads.push_back(std::move(Payload));
422 E1List.Payloads.push_back(E2.takePayload());
427 if (E2.
isA<ErrorList>()) {
428 auto &E2List =
static_cast<ErrorList &
>(*E2.getPtr());
429 E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload());
432 return Error(std::unique_ptr<ErrorList>(
433 new ErrorList(E1.takePayload(), E2.takePayload())));
436 std::vector<std::unique_ptr<ErrorInfoBase>> Payloads;
443 return ErrorList::join(std::move(E1), std::move(E2));
489 static constexpr bool isRef = std::is_reference_v<T>;
491 using wrap = std::reference_wrapper<std::remove_reference_t<T>>;
493 using error_type = std::unique_ptr<ErrorInfoBase>;
500 using reference = std::remove_reference_t<T> &;
501 using const_reference =
const std::remove_reference_t<T> &;
502 using pointer = std::remove_reference_t<T> *;
503 using const_pointer =
const std::remove_reference_t<T> *;
509#
if LLVM_ENABLE_ABI_BREAKING_CHECKS
514 assert(Err &&
"Cannot create Expected<T> from Error success value.");
515 new (getErrorStorage()) error_type(Err.takePayload());
525 template <
typename OtherT>
527 std::enable_if_t<std::is_convertible_v<OtherT, T>> * =
nullptr)
529#
if LLVM_ENABLE_ABI_BREAKING_CHECKS
535 new (getStorage())
storage_type(std::forward<OtherT>(Val));
543 template <
class OtherT>
545 std::enable_if_t<std::is_convertible_v<OtherT, T>> * =
nullptr) {
546 moveConstruct(std::move(
Other));
551 template <
class OtherT>
554 std::enable_if_t<!std::is_convertible_v<OtherT, T>> * =
nullptr) {
555 moveConstruct(std::move(
Other));
560 moveAssign(std::move(
Other));
568 getStorage()->~storage_type();
570 getErrorStorage()->~error_type();
575#if LLVM_ENABLE_ABI_BREAKING_CHECKS
584 return *getStorage();
588 const_reference
get()
const {
594 template <
class OtherT>
597 std::enable_if_t<std::is_assignable_v<OtherT &, T &&>> * =
nullptr) && {
605 return HasError && (*getErrorStorage())->
template isA<ErrT>();
613#if LLVM_ENABLE_ABI_BREAKING_CHECKS
616 return HasError ?
Error(std::move(*getErrorStorage())) : Error::success();
622 return toPointer(getStorage());
628 return toPointer(getStorage());
634 return *getStorage();
640 return *getStorage();
645 static bool compareThisIfSameType(
const T1 &a,
const T1 &b) {
649 template <
class T1,
class T2>
650 static bool compareThisIfSameType(
const T1 &,
const T2 &) {
654 template <
class OtherT>
void moveConstruct(Expected<OtherT> &&
Other) {
655 HasError =
Other.HasError;
656#if LLVM_ENABLE_ABI_BREAKING_CHECKS
658 Other.Unchecked =
false;
662 new (getStorage()) storage_type(std::move(*
Other.getStorage()));
664 new (getErrorStorage()) error_type(std::move(*
Other.getErrorStorage()));
667 template <
class OtherT>
void moveAssign(Expected<OtherT> &&
Other) {
670 if (compareThisIfSameType(*
this,
Other))
674 new (
this) Expected(std::move(
Other));
677 pointer toPointer(pointer Val) {
return Val; }
679 const_pointer toPointer(const_pointer Val)
const {
return Val; }
681 pointer toPointer(
wrap *Val) {
return &Val->get(); }
683 const_pointer toPointer(
const wrap *Val)
const {
return &Val->get(); }
685 storage_type *getStorage() {
686 assert(!HasError &&
"Cannot get value when an error exists!");
690 const storage_type *getStorage()
const {
691 assert(!HasError &&
"Cannot get value when an error exists!");
695 error_type *getErrorStorage() {
696 assert(HasError &&
"Cannot get error when a value exists!");
697 return &ErrorStorage;
700 const error_type *getErrorStorage()
const {
701 assert(HasError &&
"Cannot get error when a value exists!");
702 return &ErrorStorage;
706 void setUnchecked() {
707#if LLVM_ENABLE_ABI_BREAKING_CHECKS
712#if LLVM_ENABLE_ABI_BREAKING_CHECKS
714 dbgs() <<
"Expected<T> must be checked before access or destruction.\n";
716 dbgs() <<
"Unchecked Expected<T> contained error:\n";
717 (*getErrorStorage())->log(
dbgs());
719 dbgs() <<
"Expected<T> value was in success state. (Note: Expected<T> "
720 "values in success mode must still be checked prior to being "
727 void assertIsChecked()
const {
728#if LLVM_ENABLE_ABI_BREAKING_CHECKS
730 fatalUncheckedExpected();
739#if LLVM_ENABLE_ABI_BREAKING_CHECKS
747 bool gen_crash_diag =
true);
772 Msg =
"Failure value returned from cantFail wrapped call";
776 OS << Msg <<
"\n" << Err;
799 return std::move(*ValOrErr);
802 Msg =
"Failure value returned from cantFail wrapped call";
806 auto E = ValOrErr.takeError();
807 OS << Msg <<
"\n" <<
E;
833 Msg =
"Failure value returned from cantFail wrapped call";
837 auto E = ValOrErr.takeError();
838 OS << Msg <<
"\n" <<
E;
847template <
typename HandlerT>
850 decltype(&std::remove_reference_t<HandlerT>::operator())> {};
856 return E.template isA<ErrT>();
859 template <
typename HandlerT>
861 assert(appliesTo(*
E) &&
"Applying incorrect handler");
862 return H(
static_cast<ErrT &
>(*
E));
870 return E.template isA<ErrT>();
873 template <
typename HandlerT>
875 assert(appliesTo(*
E) &&
"Applying incorrect handler");
876 H(
static_cast<ErrT &
>(*
E));
882template <
typename ErrT>
886 return E.template isA<ErrT>();
889 template <
typename HandlerT>
891 assert(appliesTo(*
E) &&
"Applying incorrect handler");
892 std::unique_ptr<ErrT> SubE(
static_cast<ErrT *
>(
E.release()));
893 return H(std::move(SubE));
898template <
typename ErrT>
902 return E.template isA<ErrT>();
905 template <
typename HandlerT>
907 assert(appliesTo(*
E) &&
"Applying incorrect handler");
908 std::unique_ptr<ErrT> SubE(
static_cast<ErrT *
>(
E.release()));
915template <
typename C,
typename RetT,
typename ErrT>
920template <
typename C,
typename RetT,
typename ErrT>
925template <
typename C,
typename RetT,
typename ErrT>
930template <
typename C,
typename RetT,
typename ErrT>
936template <
typename C,
typename RetT,
typename ErrT>
942template <
typename C,
typename RetT,
typename ErrT>
947 return Error(std::move(Payload));
950template <
typename HandlerT,
typename... HandlerTs>
952 HandlerT &&Handler, HandlerTs &&... Handlers) {
957 std::forward<HandlerTs>(Handlers)...);
966template <
typename... HandlerTs>
971 std::unique_ptr<ErrorInfoBase> Payload =
E.takePayload();
976 for (
auto &
P :
List.Payloads)
983 return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...);
989template <
typename... HandlerTs>
1009 for (
const auto &
P :
List.Payloads)
1041template <
typename T,
typename RecoveryFtor,
typename... HandlerTs>
1043 HandlerTs &&... Handlers) {
1048 std::forward<HandlerTs>(Handlers)...))
1049 return std::move(Err);
1051 return RecoveryPath();
1066 Twine ErrorBanner = {});
1096 return std::move(*
E);
1098 return std::nullopt;
1103 return std::move(*
E);
1105 return std::nullopt;
1114 bool IsError =
static_cast<bool>(Err);
1170template <
typename T>
1174 : ValOrErr(ValOrErr) {
1181 ValOrErr->setUnchecked();
1196 void anchor()
override;
1241 return std::error_code(errno, std::generic_category());
1246 if (
auto EC = EO.getError())
1248 return std::move(*EO);
1253 if (
auto Err =
E.takeError())
1255 return std::move(*
E);
1286 StringError(std::string &&S, std::error_code EC,
bool PrintMsgOnly);
1293 std::error_code convertToErrorCode()
const override;
1300 const bool PrintMsgOnly =
false;
1304template <
typename... Ts>
1306 const Ts &... Vals) {
1309 return make_error<StringError>(Buffer, EC);
1327template <
typename... Ts>
1332template <
typename... Ts>
1334 const Ts &... Vals) {
1349 assert(Err &&
"Trying to log after takeError().");
1350 OS <<
"'" << FileName <<
"': ";
1352 OS <<
"line " << *Line <<
": ";
1367 std::error_code convertToErrorCode()
const override;
1374 std::unique_ptr<ErrorInfoBase>
E) {
1375 assert(
E &&
"Cannot create FileError from Error success value.");
1378 Line = std::move(LineNum);
1382 std::unique_ptr<ErrorInfoBase> Payload;
1384 [&](std::unique_ptr<ErrorInfoBase> EIB) ->
Error {
1385 Payload = std::move(EIB);
1386 return Error::success();
1389 std::unique_ptr<FileError>(
new FileError(
F, Line, std::move(Payload))));
1392 std::string FileName;
1393 std::optional<size_t>
Line;
1394 std::unique_ptr<ErrorInfoBase> Err;
1400 return FileError::build(
F, std::optional<size_t>(), std::move(
E));
1406 return FileError::build(
F, std::optional<size_t>(Line), std::move(
E));
1431template <
typename... Ts>
1433 char const *Fmt,
const Ts &...Vals) {
1449 GetExitCode([=](
const Error &) {
return DefaultErrorExitCode; }) {}
1452 void setBanner(std::string Banner) { this->Banner = std::move(Banner); }
1456 this->GetExitCode = std::move(GetExitCode);
1465 checkError(
E.takeError());
1466 return std::move(*
E);
1472 checkError(
E.takeError());
1477 void checkError(
Error Err)
const {
1479 int ExitCode = GetExitCode(Err);
1486 std::function<int(
const Error &)> GetExitCode;
1491 return reinterpret_cast<LLVMErrorRef>(Err.takePayload().release());
1496 return Error(std::unique_ptr<ErrorInfoBase>(
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
#define LLVM_ATTRIBUTE_NOINLINE
LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, mark a method "not for inl...
std::optional< std::vector< StOtherPiece > > Other
Provides ErrorOr<T> smart pointer.
static LLVMTargetMachineRef wrap(const TargetMachine *P)
static const char * getPtr(const MachOObjectFile &O, size_t Offset, size_t MachOFilesetEntryOffset=0)
This class wraps a std::error_code in a Error.
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
ECError(std::error_code EC)
void setErrorCode(std::error_code EC)
void log(raw_ostream &OS) const override
Print an error message to an output stream.
Helper for Errors used as out-parameters.
ErrorAsOutParameter(Error *Err)
ErrorAsOutParameter(Error &Err)
static bool appliesTo(const ErrorInfoBase &E)
static Error apply(HandlerT &&H, std::unique_ptr< ErrorInfoBase > E)
static Error apply(HandlerT &&H, std::unique_ptr< ErrorInfoBase > E)
static bool appliesTo(const ErrorInfoBase &E)
static bool appliesTo(const ErrorInfoBase &E)
static Error apply(HandlerT &&H, std::unique_ptr< ErrorInfoBase > E)
static bool appliesTo(const ErrorInfoBase &E)
static Error apply(HandlerT &&H, std::unique_ptr< ErrorInfoBase > E)
Helper for testing applicability of, and applying, handlers for ErrorInfo types.
Base class for error info classes.
virtual ~ErrorInfoBase()=default
virtual std::string message() const
Return the error message as a string.
static const void * classID()
virtual const void * dynamicClassID() const =0
virtual bool isA(const void *const ClassID) const
virtual std::error_code convertToErrorCode() const =0
Convert this error to a std::error_code.
virtual void log(raw_ostream &OS) const =0
Print an error message to an output stream.
Base class for user error types.
bool isA(const void *const ClassID) const override
const void * dynamicClassID() const override
static const void * classID()
Special ErrorInfo subclass representing a list of ErrorInfos.
void log(raw_ostream &OS) const override
Print an error message to an output stream.
Represents either an error or a value T.
Subclass of Error for the sole purpose of identifying the success path in the type system.
Lightweight error class with error context and mandatory checking.
Error(Error &&Other)
Move-construct an error value.
const void * dynamicClassID() const
Returns the dynamic class id of this error, or null if this is a success value.
friend raw_ostream & operator<<(raw_ostream &OS, const Error &E)
static ErrorSuccess success()
Create a success value.
Error(std::unique_ptr< ErrorInfoBase > Payload)
Create an error value.
Error & operator=(const Error &Other)=delete
Error()
Create a success value. Prefer using 'Error::success()' for readability.
Error(const Error &Other)=delete
Error & operator=(Error &&Other)
Move-assign an error value.
bool isA() const
Check whether one error is a subclass of another.
Helper for check-and-exit error handling.
void setBanner(std::string Banner)
Set the banner string for any errors caught by operator().
ExitOnError(std::string Banner="", int DefaultErrorExitCode=1)
Create an error on exit helper.
T operator()(Expected< T > &&E) const
Check E.
T & operator()(Expected< T & > &&E) const
Check E.
void operator()(Error Err) const
Check Err. If it's in a failure state log the error(s) and exit.
void setExitCodeMapper(std::function< int(const Error &)> GetExitCode)
Set the exit-code mapper function.
Helper for Expected<T>s used as out-parameters.
~ExpectedAsOutParameter()
ExpectedAsOutParameter(Expected< T > *ValOrErr)
Tagged union holding either a T or a Error.
const_reference operator*() const
Returns a const reference to the stored T value.
Expected(Expected< OtherT > &&Other, std::enable_if_t<!std::is_convertible_v< OtherT, T > > *=nullptr)
Move construct an Expected<T> value from an Expected<OtherT>, where OtherT isn't convertible to T.
Error moveInto(OtherT &Value, std::enable_if_t< std::is_assignable_v< OtherT &, T && > > *=nullptr) &&
Returns takeError() after moving the held T (if any) into V.
pointer operator->()
Returns a pointer to the stored T value.
reference operator*()
Returns a reference to the stored T value.
Expected(OtherT &&Val, std::enable_if_t< std::is_convertible_v< OtherT, T > > *=nullptr)
Create an Expected<T> success value from the given OtherT value, which must be convertible to T.
~Expected()
Destroy an Expected<T>.
const_reference get() const
Returns a const reference to the stored T value.
bool errorIsA() const
Check that this Expected<T> is an error of type ErrT.
Expected(ErrorSuccess)=delete
Forbid to convert from Error::success() implicitly, this avoids having Expected<T> foo() { return Err...
Expected(Error &&Err)
Create an Expected<T> error value from the given Error.
Error takeError()
Take ownership of the stored error.
const_pointer operator->() const
Returns a const pointer to the stored T value.
Expected & operator=(Expected &&Other)
Move-assign from another Expected<T>.
reference get()
Returns a reference to the stored T value.
std::conditional_t< isRef, wrap, T > storage_type
Expected(Expected &&Other)
Move construct an Expected<T> value.
Expected(Expected< OtherT > &&Other, std::enable_if_t< std::is_convertible_v< OtherT, T > > *=nullptr)
Move construct an Expected<T> value from an Expected<OtherT>, where OtherT must be convertible to T.
This class wraps a filename and another Error.
std::string messageWithoutFileInfo() const
StringRef getFileName() const
void log(raw_ostream &OS) const override
Print an error message to an output stream.
This class wraps a string in an Error.
const std::string & getMessage() const
StringRef - Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
struct LLVMOpaqueError * LLVMErrorRef
Opaque reference to an error instance.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
LLVM_ABI void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
void visitErrors(const Error &E, HandlerT H)
Visit all the ErrorInfo(s) contained in E by passing them to the respective handler,...
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
std::optional< T > expectedToStdOptional(Expected< T > &&E)
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
ErrorOr< T > expectedToErrorOr(Expected< T > &&E)
Convert an Expected<T> to an ErrorOr<T>.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
std::optional< T > expectedToOptional(Expected< T > &&E)
Convert an Expected to an Optional without doing anything.
LLVM_ABI std::string toStringWithoutConsuming(const Error &E)
Like toString(), but does not consume the error.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Expected< T > handleExpected(Expected< T > ValOrErr, RecoveryFtor &&RecoveryPath, HandlerTs &&... Handlers)
Handle any errors (if present) in an Expected<T>, then try a recovery path.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Error handleErrorImpl(std::unique_ptr< ErrorInfoBase > Payload)
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Attribute unwrap(LLVMAttributeRef Attr)
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
LLVMAttributeRef wrap(Attribute Attr)
const char * toString(DWARFSectionKind Kind)
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
std::error_code errnoAsErrorCode()
Helper to get errno as an std::error_code.
LogicalResult success(bool IsSuccess=true)
Utility function to generate a LogicalResult.
LLVM_ABI std::error_code errorToErrorCode(Error Err)
Helper for converting an ECError to a std::error_code.
void consumeError(Error Err)
Consume a Error without doing anything.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Implement std::hash so that hash_code can be used in STL containers.