14 #ifndef LLVM_SUPPORT_ERROR_H
15 #define LLVM_SUPPORT_ERROR_H
21 #include "llvm/Config/abi-breaking.h"
35 #include <system_error>
36 #include <type_traits>
69 virtual bool isA(
const void *
const ClassID)
const {
74 template <
typename ErrorInfoT>
bool isA()
const {
75 return isA(ErrorInfoT::classID());
79 static const void *
classID() {
return &ID; }
82 virtual void anchor();
158 template <
typename... HandlerTs>
184 *
this = std::move(
Other);
189 Error(std::unique_ptr<ErrorInfoBase> Payload) {
190 setPtr(Payload.release());
204 setPtr(
Other.getPtr());
210 Other.setPtr(
nullptr);
211 Other.setChecked(
true);
227 setChecked(
getPtr() ==
nullptr);
228 return getPtr() !=
nullptr;
232 template <
typename ErrT>
bool isA()
const {
237 void assertIsChecked() {
238 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
239 if (!getChecked() ||
getPtr()) {
240 dbgs() <<
"Program aborted due to an unhandled Error:\n";
245 <<
"Error value was Success. (Note: Success values must still be "
246 "checked prior to being destroyed).\n";
252 ErrorInfoBase *
getPtr()
const {
253 return reinterpret_cast<ErrorInfoBase*
>(
254 reinterpret_cast<uintptr_t
>(Payload) &
255 ~static_cast<uintptr_t>(0x1));
258 void setPtr(ErrorInfoBase *EI) {
259 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
260 Payload =
reinterpret_cast<ErrorInfoBase*
>(
261 (
reinterpret_cast<uintptr_t
>(EI) &
262 ~static_cast<uintptr_t>(0x1)) |
263 (reinterpret_cast<uintptr_t>(Payload) & 0x1));
269 bool getChecked()
const {
270 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
271 return (reinterpret_cast<uintptr_t>(Payload) & 0x1) == 0;
277 void setChecked(
bool V) {
278 Payload =
reinterpret_cast<ErrorInfoBase*
>(
279 (
reinterpret_cast<uintptr_t
>(Payload) &
280 ~static_cast<uintptr_t>(0x1)) |
284 std::unique_ptr<ErrorInfoBase> takePayload() {
285 std::unique_ptr<ErrorInfoBase> Tmp(
getPtr());
291 ErrorInfoBase *Payload;
304 return Error(llvm::make_unique<ErrT>(std::forward<ArgTs>(
Args)...));
316 template <
typename ThisErrT,
typename ParentErrT = ErrorInfoBase>
319 bool isA(
const void *
const ClassID)
const override {
320 return ClassID ==
classID() || ParentErrT::isA(ClassID);
331 template <
typename... HandlerTs>
339 OS <<
"Multiple errors:\n";
340 for (
auto &ErrPayload : Payloads) {
352 ErrorList(std::unique_ptr<ErrorInfoBase> Payload1,
353 std::unique_ptr<ErrorInfoBase> Payload2) {
355 "ErrorList constructor payloads should be singleton errors");
356 Payloads.push_back(std::move(Payload1));
357 Payloads.push_back(std::move(Payload2));
366 auto &E1List =
static_cast<ErrorList &
>(*E1.getPtr());
368 auto E2Payload = E2.takePayload();
369 auto &E2List =
static_cast<ErrorList &
>(*E2Payload);
370 for (
auto &Payload : E2List.Payloads)
371 E1List.Payloads.push_back(std::move(Payload));
373 E1List.Payloads.push_back(E2.takePayload());
377 if (E2.
isA<ErrorList>()) {
378 auto &E2List =
static_cast<ErrorList &
>(*E2.getPtr());
379 E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload());
382 return Error(std::unique_ptr<ErrorList>(
383 new ErrorList(E1.takePayload(), E2.takePayload())));
386 std::vector<std::unique_ptr<ErrorInfoBase>> Payloads;
393 return ErrorList::join(std::move(E1), std::move(E2));
398 template <
typename HandlerT>
401 &std::remove_reference<HandlerT>::type::operator())> {};
407 return E.template isA<ErrT>();
410 template <
typename HandlerT>
411 static Error apply(HandlerT &&
H, std::unique_ptr<ErrorInfoBase> E) {
412 assert(appliesTo(*E) &&
"Applying incorrect handler");
413 return H(static_cast<ErrT &>(*E));
421 return E.template isA<ErrT>();
424 template <
typename HandlerT>
425 static Error apply(HandlerT &&
H, std::unique_ptr<ErrorInfoBase> E) {
426 assert(appliesTo(*E) &&
"Applying incorrect handler");
427 H(static_cast<ErrT &>(*E));
433 template <
typename ErrT>
437 return E.template isA<ErrT>();
440 template <
typename HandlerT>
441 static Error apply(HandlerT &&
H, std::unique_ptr<ErrorInfoBase> E) {
442 assert(appliesTo(*E) &&
"Applying incorrect handler");
443 std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
444 return H(std::move(SubE));
449 template <
typename ErrT>
453 return E.template isA<ErrT>();
456 template <
typename HandlerT>
457 static Error apply(HandlerT &&
H, std::unique_ptr<ErrorInfoBase> E) {
458 assert(appliesTo(*E) &&
"Applying incorrect handler");
459 std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
466 template <
typename C,
typename RetT,
typename ErrT>
471 template <
typename C,
typename RetT,
typename ErrT>
476 template <
typename C,
typename RetT,
typename ErrT>
481 template <
typename C,
typename RetT,
typename ErrT>
487 template <
typename C,
typename RetT,
typename ErrT>
493 template <
typename C,
typename RetT,
typename ErrT>
498 return Error(std::move(Payload));
501 template <
typename HandlerT,
typename... HandlerTs>
503 HandlerT &&Handler, HandlerTs &&... Handlers) {
508 std::forward<HandlerTs>(Handlers)...);
517 template <
typename... HandlerTs>
522 std::unique_ptr<ErrorInfoBase> Payload = E.takePayload();
527 for (
auto &
P : List.Payloads)
534 return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...);
540 template <
typename... HandlerTs>
542 auto F =
handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...);
633 static const bool isRef = std::is_reference<T>::value;
636 typedef std::unique_ptr<ErrorInfoBase> error_type;
643 typedef typename std::remove_reference<T>::type &reference;
644 typedef const typename std::remove_reference<T>::type &const_reference;
645 typedef typename std::remove_reference<T>::type *pointer;
646 typedef const typename std::remove_reference<T>::type *const_pointer;
652 #
if LLVM_ENABLE_ABI_BREAKING_CHECKS
657 assert(Err &&
"Cannot create Expected<T> from Error success value.");
658 new (getErrorStorage()) error_type(Err.takePayload());
668 template <
typename OtherT>
670 typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
673 #
if LLVM_ENABLE_ABI_BREAKING_CHECKS
678 new (getStorage())
storage_type(std::forward<OtherT>(Val));
686 template <
class OtherT>
688 typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
690 moveConstruct(std::move(
Other));
695 template <
class OtherT>
698 typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
700 moveConstruct(std::move(
Other));
705 moveAssign(std::move(
Other));
713 getStorage()->~storage_type();
715 getErrorStorage()->~error_type();
720 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
721 Unchecked = HasError;
729 return *getStorage();
733 const_reference
get()
const {
740 return HasError && getErrorStorage()->template isA<ErrT>();
748 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
757 return toPointer(getStorage());
763 return toPointer(getStorage());
769 return *getStorage();
775 return *getStorage();
780 static bool compareThisIfSameType(
const T1 &a,
const T1 &b) {
784 template <
class T1,
class T2>
785 static bool compareThisIfSameType(
const T1 &a,
const T2 &b) {
789 template <
class OtherT>
void moveConstruct(Expected<OtherT> &&
Other) {
790 HasError =
Other.HasError;
791 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
793 Other.Unchecked =
false;
797 new (getStorage()) storage_type(std::move(*
Other.getStorage()));
799 new (getErrorStorage()) error_type(std::move(*
Other.getErrorStorage()));
802 template <
class OtherT>
void moveAssign(Expected<OtherT> &&
Other) {
805 if (compareThisIfSameType(*
this,
Other))
809 new (
this) Expected(std::move(
Other));
812 pointer toPointer(pointer Val) {
return Val; }
814 const_pointer toPointer(const_pointer Val)
const {
return Val; }
816 pointer toPointer(
wrap *Val) {
return &Val->get(); }
818 const_pointer toPointer(
const wrap *Val)
const {
return &Val->get(); }
820 storage_type *getStorage() {
821 assert(!HasError &&
"Cannot get value when an error exists!");
822 return reinterpret_cast<storage_type *
>(TStorage.buffer);
825 const storage_type *getStorage()
const {
826 assert(!HasError &&
"Cannot get value when an error exists!");
827 return reinterpret_cast<const storage_type *
>(TStorage.buffer);
830 error_type *getErrorStorage() {
831 assert(HasError &&
"Cannot get error when a value exists!");
832 return reinterpret_cast<error_type *
>(ErrorStorage.buffer);
835 void assertIsChecked() {
836 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
838 dbgs() <<
"Expected<T> must be checked before access or destruction.\n";
840 dbgs() <<
"Unchecked Expected<T> contained error:\n";
841 (*getErrorStorage())->log(
dbgs());
843 dbgs() <<
"Expected<T> value was in success state. (Note: Expected<T> "
844 "values in success mode must still be checked prior to being "
856 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
903 if (
auto EC = EO.getError())
905 return std::move(*EO);
910 if (
auto Err = E.takeError())
912 return std::move(*E);
941 ExitOnError(std::string Banner =
"",
int DefaultErrorExitCode = 1)
942 : Banner(std::move(Banner)),
946 void setBanner(std::string Banner) { this->Banner = std::move(Banner); }
954 void operator()(
Error Err)
const { checkError(std::move(Err)); }
958 template <
typename T>
T operator()(Expected<T> &&E)
const {
959 checkError(E.takeError());
960 return std::move(*E);
965 template <
typename T>
T& operator()(Expected<T&> &&E)
const {
966 checkError(E.takeError());
971 void checkError(
Error Err)
const {
986 bool gen_crash_diag =
true);
990 #endif // LLVM_SUPPORT_ERROR_H
reference operator*()
Returns a reference to the stored T value.
static const void * classID()
void push_back(const T &Elt)
Represents either an error or a value T.
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Error handleErrors(Error E, HandlerTs &&...Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner)
Log all errors (if any) in E to OS.
Subclass of Error for the sole purpose of identifying the success path in the type system...
AlignedCharArrayUnion< storage_type > TStorage
Helper for check-and-exit error handling.
static const char * getPtr(const MachOObjectFile &O, size_t Offset)
static bool appliesTo(const ErrorInfoBase &E)
void log(raw_ostream &OS) const override
Print an error message to an output stream.
ErrorOr< T > expectedToErrorOr(Expected< T > &&E)
Convert an Expected<T> to an ErrorOr<T>.
pointer operator->()
Returns a pointer to the stored T value.
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
bool errorIsA() const
Check that this Expected<T> is an error of type ErrT.
Error takeError()
Take ownership of the stored error.
friend Error handleErrors(Error E, HandlerTs &&...Handlers)
Pass the ErrorInfo(s) contained in E to their respective handlers.
Base class for error info classes.
virtual bool isA(const void *const ClassID) const
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
Expected(Expected< OtherT > &&Other, typename std::enable_if<!std::is_convertible< OtherT, T >::value >::type *=nullptr)
Move construct an Expected<T> value from an Expected<OtherT>, where OtherT isn't convertible to T...
static Error apply(HandlerT &&H, std::unique_ptr< ErrorInfoBase > E)
std::string toString(Error E)
Write all error messages (if any) in E to a string.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Expected(Expected &&Other)
Move construct an Expected<T> value.
Expected(Expected< OtherT > &&Other, typename std::enable_if< std::is_convertible< OtherT, T >::value >::type *=nullptr)
Move construct an Expected<T> value from an Expected<OtherT>, where OtherT must be convertible to T...
virtual void log(raw_ostream &OS) const =0
Print an error message to an output stream.
void log(raw_ostream &OS) const override
Print an error message to an output stream.
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
~Expected()
Destroy an Expected<T>.
Tagged union holding either a T or a Error.
virtual ~ErrorInfoBase()=default
Function Alias Analysis false
friend Error joinErrors(Error, Error)
Concatenate errors.
Error & operator=(Error &&Other)
Move-assign an error value.
Error make_error(ArgTs &&...Args)
Make a Error instance representing failure using the given error info type.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
std::function< int(const Error &)> GetExitCode
ErrorAsOutParameter(Error *Err)
ECError(std::error_code EC)
Expected(Error Err)
Create an Expected<T> error value from the given Error.
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
AlignedCharArrayUnion< error_type > ErrorStorage
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
ExitOnError(std::string Banner="", int DefaultErrorExitCode=1)
Create an error on exit helper.
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
bool isA() const
Check whether one error is a subclass of another.
void handleAllErrors(Error E, HandlerTs &&...Handlers)
Behaves the same as handleErrors, except that it requires that all errors be handled by the given han...
void apply(Opt *O, const Mod &M, const Mods &...Ms)
void consumeError(Error Err)
Consume a Error without doing anything.
StringError(const Twine &S, std::error_code EC)
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
static Error apply(HandlerT &&H, std::unique_ptr< ErrorInfoBase > E)
Special ErrorInfo subclass representing a list of ErrorInfos.
static const void * classID()
const_reference operator*() const
Returns a const reference to the stored T value.
Error(std::unique_ptr< ErrorInfoBase > Payload)
Create an error value.
static ErrorSuccess success()
Create a success value.
static bool appliesTo(const ErrorInfoBase &E)
std::conditional< isRef, wrap, T >::type storage_type
Expected(OtherT &&Val, typename std::enable_if< std::is_convertible< OtherT, T >::value >::type *=nullptr)
Create an Expected<T> success value from the given OtherT value, which must be convertible to T...
static bool appliesTo(const ErrorInfoBase &E)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
#define LLVM_ATTRIBUTE_NORETURN
virtual std::error_code convertToErrorCode() const =0
Convert this error to a std::error_code.
Expected & operator=(Expected &&Other)
Move-assign from another Expected<T>.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Base class for user error types.
Helper for Errors used as out-parameters.
static Error apply(HandlerT &&H, std::unique_ptr< ErrorInfoBase > E)
Error handleErrorImpl(std::unique_ptr< ErrorInfoBase > Payload)
Error(Error &&Other)
Move-construct an error value.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
LLVMAttributeRef wrap(Attribute Attr)
This class wraps a string in an Error.
void log(raw_ostream &OS) const override
Print an error message to an output stream.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
bool isA(const void *const ClassID) const override
void setErrorCode(std::error_code EC)
Stores a reference that can be changed.
friend Error errorCodeToError(std::error_code)
Helper for converting an std::error_code to a Error.
#define LLVM_NODISCARD
LLVM_NODISCARD - Warn if a type or return value is discarded.
static Error apply(HandlerT &&H, std::unique_ptr< ErrorInfoBase > E)
Provides ErrorOr<T> smart pointer.
Error()
Create a success value. Prefer using 'Error::success()' for readability.
static bool appliesTo(const ErrorInfoBase &E)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
Lightweight error class with error context and mandatory checking.
This class wraps a std::error_code in a Error.
This class implements an extremely fast bulk output stream that can only output to a stream...
Helper for testing applicability of, and applying, handlers for ErrorInfo types.
virtual std::string message() const
Return the error message as a string.
print Print MemDeps of function
std::error_code errorToErrorCode(Error Err)
Helper for converting an ECError to a std::error_code.
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
const_pointer operator->() const
Returns a const pointer to the stored T value.