13#ifndef LLVM_SUPPORT_ERROR_H
14#define LLVM_SUPPORT_ERROR_H
20#include "llvm/Config/abi-breaking.h"
36#include <system_error>
76 virtual bool isA(
const void *
const ClassID)
const {
81 template <
typename ErrorInfoT>
bool isA()
const {
82 return isA(ErrorInfoT::classID());
86 virtual void anchor();
163 template <
typename... HandlerTs>
192 *
this = std::move(
Other);
197 Error(std::unique_ptr<ErrorInfoBase> Payload) {
198 setPtr(Payload.release());
212 setPtr(
Other.getPtr());
218 Other.setPtr(
nullptr);
219 Other.setChecked(
true);
235 setChecked(
getPtr() ==
nullptr);
236 return getPtr() !=
nullptr;
240 template <
typename ErrT>
bool isA()
const {
249 return getPtr()->dynamicClassID();
253#if LLVM_ENABLE_ABI_BREAKING_CHECKS
259 [[noreturn]]
void fatalUncheckedError()
const;
262 void assertIsChecked() {
263#if LLVM_ENABLE_ABI_BREAKING_CHECKS
265 fatalUncheckedError();
269 ErrorInfoBase *
getPtr()
const {
270#if LLVM_ENABLE_ABI_BREAKING_CHECKS
271 return reinterpret_cast<ErrorInfoBase*
>(
272 reinterpret_cast<uintptr_t
>(Payload) &
273 ~
static_cast<uintptr_t
>(0x1));
279 void setPtr(ErrorInfoBase *EI) {
280#if LLVM_ENABLE_ABI_BREAKING_CHECKS
281 Payload =
reinterpret_cast<ErrorInfoBase*
>(
282 (
reinterpret_cast<uintptr_t
>(EI) &
283 ~
static_cast<uintptr_t
>(0x1)) |
284 (
reinterpret_cast<uintptr_t
>(Payload) & 0x1));
290 bool getChecked()
const {
291#if LLVM_ENABLE_ABI_BREAKING_CHECKS
292 return (
reinterpret_cast<uintptr_t
>(Payload) & 0x1) == 0;
298 void setChecked(
bool V) {
299#if LLVM_ENABLE_ABI_BREAKING_CHECKS
300 Payload =
reinterpret_cast<ErrorInfoBase*
>(
301 (
reinterpret_cast<uintptr_t
>(Payload) &
302 ~
static_cast<uintptr_t
>(0x1)) |
307 std::unique_ptr<ErrorInfoBase> takePayload() {
308 std::unique_ptr<ErrorInfoBase> Tmp(
getPtr());
315 if (
auto *
P =
E.getPtr())
335 return Error(std::make_unique<ErrT>(std::forward<ArgTs>(Args)...));
347template <
typename ThisErrT,
typename ParentErrT = ErrorInfoBase>
350 using ParentErrT::ParentErrT;
352 static const void *
classID() {
return &ThisErrT::ID; }
356 bool isA(
const void *
const ClassID)
const override {
357 return ClassID ==
classID() || ParentErrT::isA(ClassID);
366 template <
typename... HandlerTs>
374 OS <<
"Multiple errors:\n";
375 for (
const auto &ErrPayload : Payloads) {
387 ErrorList(std::unique_ptr<ErrorInfoBase> Payload1,
388 std::unique_ptr<ErrorInfoBase> Payload2) {
390 "ErrorList constructor payloads should be singleton errors");
391 Payloads.push_back(std::move(Payload1));
392 Payloads.push_back(std::move(Payload2));
401 auto &E1List =
static_cast<ErrorList &
>(*E1.getPtr());
403 auto E2Payload = E2.takePayload();
404 auto &E2List =
static_cast<ErrorList &
>(*E2Payload);
405 for (
auto &Payload : E2List.Payloads)
406 E1List.Payloads.push_back(std::move(Payload));
408 E1List.Payloads.push_back(E2.takePayload());
412 if (E2.
isA<ErrorList>()) {
413 auto &E2List =
static_cast<ErrorList &
>(*E2.getPtr());
414 E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload());
417 return Error(std::unique_ptr<ErrorList>(
418 new ErrorList(E1.takePayload(), E2.takePayload())));
421 std::vector<std::unique_ptr<ErrorInfoBase>> Payloads;
428 return ErrorList::join(std::move(E1), std::move(E2));
474 static constexpr bool isRef = std::is_reference<T>::value;
476 using wrap = std::reference_wrapper<std::remove_reference_t<T>>;
478 using error_type = std::unique_ptr<ErrorInfoBase>;
485 using reference = std::remove_reference_t<T> &;
486 using const_reference =
const std::remove_reference_t<T> &;
487 using pointer = std::remove_reference_t<T> *;
488 using const_pointer =
const std::remove_reference_t<T> *;
494#
if LLVM_ENABLE_ABI_BREAKING_CHECKS
499 assert(Err &&
"Cannot create Expected<T> from Error success value.");
500 new (getErrorStorage()) error_type(Err.takePayload());
510 template <
typename OtherT>
512 std::enable_if_t<std::is_convertible_v<OtherT, T>> * =
nullptr)
514#
if LLVM_ENABLE_ABI_BREAKING_CHECKS
520 new (getStorage())
storage_type(std::forward<OtherT>(Val));
528 template <
class OtherT>
530 std::enable_if_t<std::is_convertible_v<OtherT, T>> * =
nullptr) {
531 moveConstruct(std::move(
Other));
536 template <
class OtherT>
539 std::enable_if_t<!std::is_convertible_v<OtherT, T>> * =
nullptr) {
540 moveConstruct(std::move(
Other));
545 moveAssign(std::move(
Other));
553 getStorage()->~storage_type();
555 getErrorStorage()->~error_type();
560#if LLVM_ENABLE_ABI_BREAKING_CHECKS
561 Unchecked = HasError;
569 return *getStorage();
573 const_reference
get()
const {
579 template <
class OtherT>
581 std::enable_if_t<std::is_assignable<OtherT &, T &&>::value> * =
590 return HasError && (*getErrorStorage())->
template isA<ErrT>();
598#if LLVM_ENABLE_ABI_BREAKING_CHECKS
601 return HasError ?
Error(std::move(*getErrorStorage())) : Error::success();
607 return toPointer(getStorage());
613 return toPointer(getStorage());
619 return *getStorage();
625 return *getStorage();
630 static bool compareThisIfSameType(
const T1 &a,
const T1 &b) {
634 template <
class T1,
class T2>
635 static bool compareThisIfSameType(
const T1 &,
const T2 &) {
639 template <
class OtherT>
void moveConstruct(Expected<OtherT> &&
Other) {
640 HasError =
Other.HasError;
641#if LLVM_ENABLE_ABI_BREAKING_CHECKS
643 Other.Unchecked =
false;
647 new (getStorage()) storage_type(std::move(*
Other.getStorage()));
649 new (getErrorStorage()) error_type(std::move(*
Other.getErrorStorage()));
652 template <
class OtherT>
void moveAssign(Expected<OtherT> &&
Other) {
655 if (compareThisIfSameType(*
this,
Other))
659 new (
this) Expected(std::move(
Other));
664 const_pointer toPointer(const_pointer Val)
const {
return Val; }
666 pointer toPointer(
wrap *Val) {
return &Val->get(); }
668 const_pointer toPointer(
const wrap *Val)
const {
return &Val->get(); }
670 storage_type *getStorage() {
671 assert(!HasError &&
"Cannot get value when an error exists!");
672 return reinterpret_cast<storage_type *
>(&TStorage);
675 const storage_type *getStorage()
const {
676 assert(!HasError &&
"Cannot get value when an error exists!");
677 return reinterpret_cast<const storage_type *
>(&TStorage);
680 error_type *getErrorStorage() {
681 assert(HasError &&
"Cannot get error when a value exists!");
682 return reinterpret_cast<error_type *
>(&ErrorStorage);
685 const error_type *getErrorStorage()
const {
686 assert(HasError &&
"Cannot get error when a value exists!");
687 return reinterpret_cast<const error_type *
>(&ErrorStorage);
691 void setUnchecked() {
692#if LLVM_ENABLE_ABI_BREAKING_CHECKS
697#if LLVM_ENABLE_ABI_BREAKING_CHECKS
699 dbgs() <<
"Expected<T> must be checked before access or destruction.\n";
701 dbgs() <<
"Unchecked Expected<T> contained error:\n";
702 (*getErrorStorage())->log(
dbgs());
704 dbgs() <<
"Expected<T> value was in success state. (Note: Expected<T> "
705 "values in success mode must still be checked prior to being "
711 void assertIsChecked()
const {
712#if LLVM_ENABLE_ABI_BREAKING_CHECKS
714 fatalUncheckedExpected();
723#if LLVM_ENABLE_ABI_BREAKING_CHECKS
748 Msg =
"Failure value returned from cantFail wrapped call";
752 OS << Msg <<
"\n" << Err;
753 Msg =
OS.str().c_str();
775 return std::move(*ValOrErr);
778 Msg =
"Failure value returned from cantFail wrapped call";
782 auto E = ValOrErr.takeError();
783 OS << Msg <<
"\n" <<
E;
784 Msg =
OS.str().c_str();
809 Msg =
"Failure value returned from cantFail wrapped call";
813 auto E = ValOrErr.takeError();
814 OS << Msg <<
"\n" <<
E;
815 Msg =
OS.str().c_str();
823template <
typename HandlerT>
826 decltype(&std::remove_reference_t<HandlerT>::operator())> {};
832 return E.template isA<ErrT>();
835 template <
typename HandlerT>
837 assert(appliesTo(*
E) &&
"Applying incorrect handler");
838 return H(
static_cast<ErrT &
>(*
E));
846 return E.template isA<ErrT>();
849 template <
typename HandlerT>
851 assert(appliesTo(*
E) &&
"Applying incorrect handler");
852 H(
static_cast<ErrT &
>(*
E));
858template <
typename ErrT>
862 return E.template isA<ErrT>();
865 template <
typename HandlerT>
867 assert(appliesTo(*
E) &&
"Applying incorrect handler");
868 std::unique_ptr<ErrT> SubE(
static_cast<ErrT *
>(
E.release()));
869 return H(std::move(SubE));
874template <
typename ErrT>
878 return E.template isA<ErrT>();
881 template <
typename HandlerT>
883 assert(appliesTo(*
E) &&
"Applying incorrect handler");
884 std::unique_ptr<ErrT> SubE(
static_cast<ErrT *
>(
E.release()));
891template <
typename C,
typename RetT,
typename ErrT>
896template <
typename C,
typename RetT,
typename ErrT>
901template <
typename C,
typename RetT,
typename ErrT>
906template <
typename C,
typename RetT,
typename ErrT>
912template <
typename C,
typename RetT,
typename ErrT>
918template <
typename C,
typename RetT,
typename ErrT>
923 return Error(std::move(Payload));
926template <
typename HandlerT,
typename... HandlerTs>
928 HandlerT &&Handler, HandlerTs &&... Handlers) {
933 std::forward<HandlerTs>(Handlers)...);
942template <
typename... HandlerTs>
947 std::unique_ptr<ErrorInfoBase> Payload =
E.takePayload();
952 for (
auto &
P :
List.Payloads)
959 return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...);
965template <
typename... HandlerTs>
1000template <
typename T,
typename RecoveryFtor,
typename... HandlerTs>
1002 HandlerTs &&... Handlers) {
1007 std::forward<HandlerTs>(Handlers)...))
1008 return std::move(Err);
1010 return RecoveryPath();
1033 return join(Errors.
begin(), Errors.
end(),
"\n");
1056 return std::move(*
E);
1058 return std::nullopt;
1063 return std::move(*
E);
1065 return std::nullopt;
1074 bool IsError =
static_cast<bool>(Err);
1125template <
typename T>
1129 : ValOrErr(ValOrErr) {
1136 ValOrErr->setUnchecked();
1151 void anchor()
override;
1187 if (
auto EC = EO.getError())
1189 return std::move(*EO);
1194 if (
auto Err =
E.takeError())
1196 return std::move(*
E);
1241 const bool PrintMsgOnly =
false;
1245template <
typename... Ts>
1247 const Ts &... Vals) {
1250 Stream <<
format(Fmt, Vals...);
1251 return make_error<StringError>(Stream.
str(), EC);
1260template <
typename... Ts>
1262 const Ts &... Vals) {
1277 assert(Err &&
"Trying to log after takeError().");
1278 OS <<
"'" << FileName <<
"': ";
1280 OS <<
"line " << *Line <<
": ";
1302 std::unique_ptr<ErrorInfoBase>
E) {
1303 assert(
E &&
"Cannot create FileError from Error success value.");
1306 Line = std::move(LineNum);
1310 std::unique_ptr<ErrorInfoBase> Payload;
1312 [&](std::unique_ptr<ErrorInfoBase> EIB) ->
Error {
1313 Payload = std::move(EIB);
1317 std::unique_ptr<FileError>(
new FileError(
F, Line, std::move(Payload))));
1320 std::string FileName;
1321 std::optional<size_t>
Line;
1322 std::unique_ptr<ErrorInfoBase> Err;
1328 return FileError::build(
F, std::optional<size_t>(), std::move(
E));
1334 return FileError::build(
F, std::optional<size_t>(Line), std::move(
E));
1360 GetExitCode([=](
const Error &) {
return DefaultErrorExitCode; }) {}
1363 void setBanner(std::string Banner) { this->Banner = std::move(Banner); }
1367 this->GetExitCode = std::move(GetExitCode);
1376 checkError(
E.takeError());
1377 return std::move(*
E);
1383 checkError(
E.takeError());
1388 void checkError(
Error Err)
const {
1390 int ExitCode = GetExitCode(Err);
1397 std::function<int(
const Error &)> GetExitCode;
1402 return reinterpret_cast<LLVMErrorRef>(Err.takePayload().release());
1407 return Error(std::unique_ptr<ErrorInfoBase>(
Replace within non kernel function use of LDS with pointer
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)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
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)
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.
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.
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.
Error moveInto(OtherT &Value, std::enable_if_t< std::is_assignable< OtherT &, T && >::value > *=nullptr) &&
Returns takeError() after moving the held T (if any) into V.
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...
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(Error Err)
Create an Expected<T> error value from the given Error.
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.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
std::string & str()
Returns the string's reference.
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.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
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.
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.
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)
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
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.
A suitably aligned and sized character array member which can hold elements of any type.