13#ifndef LLVM_SUPPORT_ERROR_H
14#define LLVM_SUPPORT_ERROR_H
18#include "llvm/Config/abi-breaking.h"
34#include <system_error>
74 virtual bool isA(
const void *
const ClassID)
const {
79 template <
typename ErrorInfoT>
bool isA()
const {
80 return isA(ErrorInfoT::classID());
84 virtual void anchor();
167 template <
typename... HandlerTs>
170 template <
typename HandlerT>
199 *
this = std::move(
Other);
204 Error(std::unique_ptr<ErrorInfoBase> Payload) {
205 setPtr(Payload.release());
219 setPtr(
Other.getPtr());
225 Other.setPtr(
nullptr);
226 Other.setChecked(
true);
242 setChecked(
getPtr() ==
nullptr);
243 return getPtr() !=
nullptr;
247 template <
typename ErrT>
bool isA()
const {
256 return getPtr()->dynamicClassID();
260#if LLVM_ENABLE_ABI_BREAKING_CHECKS
266 [[noreturn]]
void fatalUncheckedError()
const;
269 void assertIsChecked() {
270#if LLVM_ENABLE_ABI_BREAKING_CHECKS
272 fatalUncheckedError();
276 ErrorInfoBase *
getPtr()
const {
277#if LLVM_ENABLE_ABI_BREAKING_CHECKS
278 return reinterpret_cast<ErrorInfoBase*
>(
279 reinterpret_cast<uintptr_t
>(Payload) &
280 ~
static_cast<uintptr_t
>(0x1));
286 void setPtr(ErrorInfoBase *EI) {
287#if LLVM_ENABLE_ABI_BREAKING_CHECKS
288 Payload =
reinterpret_cast<ErrorInfoBase*
>(
289 (
reinterpret_cast<uintptr_t
>(EI) &
290 ~
static_cast<uintptr_t
>(0x1)) |
291 (
reinterpret_cast<uintptr_t
>(Payload) & 0x1));
297 bool getChecked()
const {
298#if LLVM_ENABLE_ABI_BREAKING_CHECKS
299 return (
reinterpret_cast<uintptr_t
>(Payload) & 0x1) == 0;
305 void setChecked(
bool V) {
306#if LLVM_ENABLE_ABI_BREAKING_CHECKS
307 Payload =
reinterpret_cast<ErrorInfoBase*
>(
308 (
reinterpret_cast<uintptr_t
>(Payload) &
309 ~
static_cast<uintptr_t
>(0x1)) |
314 std::unique_ptr<ErrorInfoBase> takePayload() {
315 std::unique_ptr<ErrorInfoBase> Tmp(
getPtr());
322 if (
auto *
P =
E.getPtr())
342 return Error(std::make_unique<ErrT>(std::forward<ArgTs>(Args)...));
354template <
typename ThisErrT,
typename ParentErrT = ErrorInfoBase>
357 using ParentErrT::ParentErrT;
359 static const void *
classID() {
return &ThisErrT::ID; }
363 bool isA(
const void *
const ClassID)
const override {
364 return ClassID ==
classID() || ParentErrT::isA(ClassID);
373 template <
typename... HandlerTs>
377 template <
typename HandlerT>
385 OS <<
"Multiple errors:\n";
386 for (
const auto &ErrPayload : Payloads) {
398 ErrorList(std::unique_ptr<ErrorInfoBase> Payload1,
399 std::unique_ptr<ErrorInfoBase> Payload2) {
401 "ErrorList constructor payloads should be singleton errors");
402 Payloads.push_back(std::move(Payload1));
403 Payloads.push_back(std::move(Payload2));
412 auto &E1List =
static_cast<ErrorList &
>(*E1.getPtr());
414 auto E2Payload = E2.takePayload();
415 auto &E2List =
static_cast<ErrorList &
>(*E2Payload);
416 for (
auto &Payload : E2List.Payloads)
417 E1List.Payloads.push_back(std::move(Payload));
419 E1List.Payloads.push_back(E2.takePayload());
423 if (E2.
isA<ErrorList>()) {
424 auto &E2List =
static_cast<ErrorList &
>(*E2.getPtr());
425 E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload());
428 return Error(std::unique_ptr<ErrorList>(
429 new ErrorList(E1.takePayload(), E2.takePayload())));
432 std::vector<std::unique_ptr<ErrorInfoBase>> Payloads;
439 return ErrorList::join(std::move(E1), std::move(E2));
485 static constexpr bool isRef = std::is_reference_v<T>;
487 using wrap = std::reference_wrapper<std::remove_reference_t<T>>;
489 using error_type = std::unique_ptr<ErrorInfoBase>;
496 using reference = std::remove_reference_t<T> &;
497 using const_reference =
const std::remove_reference_t<T> &;
498 using pointer = std::remove_reference_t<T> *;
499 using const_pointer =
const std::remove_reference_t<T> *;
505#
if LLVM_ENABLE_ABI_BREAKING_CHECKS
510 assert(Err &&
"Cannot create Expected<T> from Error success value.");
511 new (getErrorStorage()) error_type(Err.takePayload());
521 template <
typename OtherT>
523 std::enable_if_t<std::is_convertible_v<OtherT, T>> * =
nullptr)
525#
if LLVM_ENABLE_ABI_BREAKING_CHECKS
531 new (getStorage())
storage_type(std::forward<OtherT>(Val));
539 template <
class OtherT>
541 std::enable_if_t<std::is_convertible_v<OtherT, T>> * =
nullptr) {
542 moveConstruct(std::move(
Other));
547 template <
class OtherT>
550 std::enable_if_t<!std::is_convertible_v<OtherT, T>> * =
nullptr) {
551 moveConstruct(std::move(
Other));
556 moveAssign(std::move(
Other));
564 getStorage()->~storage_type();
566 getErrorStorage()->~error_type();
571#if LLVM_ENABLE_ABI_BREAKING_CHECKS
580 return *getStorage();
584 const_reference
get()
const {
590 template <
class OtherT>
593 std::enable_if_t<std::is_assignable_v<OtherT &, T &&>> * =
nullptr) && {
601 return HasError && (*getErrorStorage())->
template isA<ErrT>();
609#if LLVM_ENABLE_ABI_BREAKING_CHECKS
612 return HasError ?
Error(std::move(*getErrorStorage())) : Error::success();
618 return toPointer(getStorage());
624 return toPointer(getStorage());
630 return *getStorage();
636 return *getStorage();
641 static bool compareThisIfSameType(
const T1 &a,
const T1 &b) {
645 template <
class T1,
class T2>
646 static bool compareThisIfSameType(
const T1 &,
const T2 &) {
650 template <
class OtherT>
void moveConstruct(Expected<OtherT> &&
Other) {
651 HasError =
Other.HasError;
652#if LLVM_ENABLE_ABI_BREAKING_CHECKS
654 Other.Unchecked =
false;
658 new (getStorage()) storage_type(std::move(*
Other.getStorage()));
660 new (getErrorStorage()) error_type(std::move(*
Other.getErrorStorage()));
663 template <
class OtherT>
void moveAssign(Expected<OtherT> &&
Other) {
666 if (compareThisIfSameType(*
this,
Other))
670 new (
this) Expected(std::move(
Other));
673 pointer toPointer(pointer Val) {
return Val; }
675 const_pointer toPointer(const_pointer Val)
const {
return Val; }
677 pointer toPointer(
wrap *Val) {
return &Val->get(); }
679 const_pointer toPointer(
const wrap *Val)
const {
return &Val->get(); }
681 storage_type *getStorage() {
682 assert(!HasError &&
"Cannot get value when an error exists!");
683 return reinterpret_cast<storage_type *
>(&TStorage);
686 const storage_type *getStorage()
const {
687 assert(!HasError &&
"Cannot get value when an error exists!");
688 return reinterpret_cast<const storage_type *
>(&TStorage);
691 error_type *getErrorStorage() {
692 assert(HasError &&
"Cannot get error when a value exists!");
693 return reinterpret_cast<error_type *
>(&ErrorStorage);
696 const error_type *getErrorStorage()
const {
697 assert(HasError &&
"Cannot get error when a value exists!");
698 return reinterpret_cast<const error_type *
>(&ErrorStorage);
702 void setUnchecked() {
703#if LLVM_ENABLE_ABI_BREAKING_CHECKS
708#if LLVM_ENABLE_ABI_BREAKING_CHECKS
710 dbgs() <<
"Expected<T> must be checked before access or destruction.\n";
712 dbgs() <<
"Unchecked Expected<T> contained error:\n";
713 (*getErrorStorage())->log(
dbgs());
715 dbgs() <<
"Expected<T> value was in success state. (Note: Expected<T> "
716 "values in success mode must still be checked prior to being "
722 void assertIsChecked()
const {
723#if LLVM_ENABLE_ABI_BREAKING_CHECKS
725 fatalUncheckedExpected();
734#if LLVM_ENABLE_ABI_BREAKING_CHECKS
759 Msg =
"Failure value returned from cantFail wrapped call";
763 OS << Msg <<
"\n" << Err;
786 return std::move(*ValOrErr);
789 Msg =
"Failure value returned from cantFail wrapped call";
793 auto E = ValOrErr.takeError();
794 OS << Msg <<
"\n" <<
E;
820 Msg =
"Failure value returned from cantFail wrapped call";
824 auto E = ValOrErr.takeError();
825 OS << Msg <<
"\n" <<
E;
834template <
typename HandlerT>
837 decltype(&std::remove_reference_t<HandlerT>::operator())> {};
843 return E.template isA<ErrT>();
846 template <
typename HandlerT>
848 assert(appliesTo(*
E) &&
"Applying incorrect handler");
849 return H(
static_cast<ErrT &
>(*
E));
857 return E.template isA<ErrT>();
860 template <
typename HandlerT>
862 assert(appliesTo(*
E) &&
"Applying incorrect handler");
863 H(
static_cast<ErrT &
>(*
E));
869template <
typename ErrT>
873 return E.template isA<ErrT>();
876 template <
typename HandlerT>
878 assert(appliesTo(*
E) &&
"Applying incorrect handler");
879 std::unique_ptr<ErrT> SubE(
static_cast<ErrT *
>(
E.release()));
880 return H(std::move(SubE));
885template <
typename ErrT>
889 return E.template isA<ErrT>();
892 template <
typename HandlerT>
894 assert(appliesTo(*
E) &&
"Applying incorrect handler");
895 std::unique_ptr<ErrT> SubE(
static_cast<ErrT *
>(
E.release()));
902template <
typename C,
typename RetT,
typename ErrT>
907template <
typename C,
typename RetT,
typename ErrT>
912template <
typename C,
typename RetT,
typename ErrT>
917template <
typename C,
typename RetT,
typename ErrT>
923template <
typename C,
typename RetT,
typename ErrT>
929template <
typename C,
typename RetT,
typename ErrT>
934 return Error(std::move(Payload));
937template <
typename HandlerT,
typename... HandlerTs>
939 HandlerT &&Handler, HandlerTs &&... Handlers) {
944 std::forward<HandlerTs>(Handlers)...);
953template <
typename... HandlerTs>
958 std::unique_ptr<ErrorInfoBase> Payload =
E.takePayload();
963 for (
auto &
P :
List.Payloads)
970 return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...);
976template <
typename... HandlerTs>
996 for (
const auto &
P :
List.Payloads)
1028template <
typename T,
typename RecoveryFtor,
typename... HandlerTs>
1030 HandlerTs &&... Handlers) {
1035 std::forward<HandlerTs>(Handlers)...))
1036 return std::move(Err);
1038 return RecoveryPath();
1082 return std::move(*
E);
1084 return std::nullopt;
1089 return std::move(*
E);
1091 return std::nullopt;
1100 bool IsError =
static_cast<bool>(Err);
1156template <
typename T>
1160 : ValOrErr(ValOrErr) {
1167 ValOrErr->setUnchecked();
1182 void anchor()
override;
1227 return std::error_code(errno, std::generic_category());
1232 if (
auto EC = EO.getError())
1234 return std::move(*EO);
1239 if (
auto Err =
E.takeError())
1241 return std::move(*
E);
1272 StringError(std::string &&S, std::error_code EC,
bool PrintMsgOnly);
1286 const bool PrintMsgOnly =
false;
1290template <
typename... Ts>
1292 const Ts &... Vals) {
1295 return make_error<StringError>(Buffer, EC);
1313template <
typename... Ts>
1318template <
typename... Ts>
1320 const Ts &... Vals) {
1335 assert(Err &&
"Trying to log after takeError().");
1336 OS <<
"'" << FileName <<
"': ";
1338 OS <<
"line " << *Line <<
": ";
1360 std::unique_ptr<ErrorInfoBase>
E) {
1361 assert(
E &&
"Cannot create FileError from Error success value.");
1364 Line = std::move(LineNum);
1368 std::unique_ptr<ErrorInfoBase> Payload;
1370 [&](std::unique_ptr<ErrorInfoBase> EIB) ->
Error {
1371 Payload = std::move(EIB);
1375 std::unique_ptr<FileError>(
new FileError(
F, Line, std::move(Payload))));
1378 std::string FileName;
1379 std::optional<size_t>
Line;
1380 std::unique_ptr<ErrorInfoBase> Err;
1386 return FileError::build(
F, std::optional<size_t>(), std::move(
E));
1392 return FileError::build(
F, std::optional<size_t>(Line), std::move(
E));
1418 GetExitCode([=](
const Error &) {
return DefaultErrorExitCode; }) {}
1421 void setBanner(std::string Banner) { this->Banner = std::move(Banner); }
1425 this->GetExitCode = std::move(GetExitCode);
1434 checkError(
E.takeError());
1435 return std::move(*
E);
1441 checkError(
E.takeError());
1446 void checkError(
Error Err)
const {
1448 int ExitCode = GetExitCode(Err);
1455 std::function<int(
const Error &)> GetExitCode;
1460 return reinterpret_cast<LLVMErrorRef>(Err.takePayload().release());
1465 return Error(std::unique_ptr<ErrorInfoBase>(
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)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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)
friend Error errorCodeToError(std::error_code)
Helper for converting an std::error_code to a Error.
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.
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
friend Error handleErrors(Error E, HandlerTs &&... Handlers)
Pass the ErrorInfo(s) contained in E to their respective handlers.
void log(raw_ostream &OS) const override
Print an error message to an output stream.
friend Error joinErrors(Error, Error)
Concatenate errors.
friend void visitErrors(const Error &E, HandlerT H)
Visit all the ErrorInfo(s) contained in E by passing them to the respective handler,...
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.
AlignedCharArrayUnion< storage_type > TStorage
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.
AlignedCharArrayUnion< error_type > ErrorStorage
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::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
std::string messageWithoutFileInfo() const
StringRef getFileName() const
void log(raw_ostream &OS) const override
Print an error message to an output stream.
friend Error createFileError(const Twine &, Error)
Concatenate a source file path and/or name with an Error.
This class wraps a string in an Error.
void log(raw_ostream &OS) const override
Print an error message to an output stream.
const std::string & getMessage() const
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
StringRef - Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
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.
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...
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.
std::optional< T > expectedToOptional(Expected< T > &&E)
Convert an Expected to an Optional without doing anything.
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)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
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.
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)
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.
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.
Implement std::hash so that hash_code can be used in STL containers.
A suitably aligned and sized character array member which can hold elements of any type.