14 #ifndef LLVM_SUPPORT_ERROR_H 15 #define LLVM_SUPPORT_ERROR_H 22 #include "llvm/Config/abi-breaking.h" 38 #include <system_error> 39 #include <type_traits> 71 static const void *
classID() {
return &ID; }
78 virtual bool isA(
const void *
const ClassID)
const {
83 template <
typename ErrorInfoT>
bool isA()
const {
84 return isA(ErrorInfoT::classID());
88 virtual void anchor();
165 template <
typename... HandlerTs>
194 *
this = std::move(Other);
199 Error(std::unique_ptr<ErrorInfoBase> Payload) {
200 setPtr(Payload.release());
205 Error &operator=(
const Error &Other) =
delete;
214 setPtr(Other.getPtr());
220 Other.setPtr(
nullptr);
221 Other.setChecked(
true);
237 setChecked(
getPtr() ==
nullptr);
238 return getPtr() !=
nullptr;
242 template <
typename ErrT>
bool isA()
const {
251 return getPtr()->dynamicClassID();
255 #if LLVM_ENABLE_ABI_BREAKING_CHECKS 262 void fatalUncheckedError()
const;
265 void assertIsChecked() {
266 #if LLVM_ENABLE_ABI_BREAKING_CHECKS 268 fatalUncheckedError();
274 reinterpret_cast<uintptr_t
>(Payload) &
275 ~static_cast<uintptr_t>(0x1));
279 #if LLVM_ENABLE_ABI_BREAKING_CHECKS 281 (
reinterpret_cast<uintptr_t
>(EI) &
282 ~static_cast<uintptr_t>(0x1)) |
283 (reinterpret_cast<uintptr_t>(Payload) & 0x1));
289 bool getChecked()
const {
290 #if LLVM_ENABLE_ABI_BREAKING_CHECKS 291 return (reinterpret_cast<uintptr_t>(Payload) & 0x1) == 0;
297 void setChecked(
bool V) {
299 (
reinterpret_cast<uintptr_t
>(Payload) &
300 ~static_cast<uintptr_t>(0x1)) |
304 std::unique_ptr<ErrorInfoBase> takePayload() {
305 std::unique_ptr<ErrorInfoBase> Tmp(
getPtr());
312 if (
auto P = E.getPtr())
332 return Error(llvm::make_unique<ErrT>(std::forward<ArgTs>(
Args)...));
344 template <
typename ThisErrT,
typename ParentErrT = ErrorInfoBase>
347 using ParentErrT::ParentErrT;
353 bool isA(
const void *
const ClassID)
const override {
354 return ClassID ==
classID() || ParentErrT::isA(ClassID);
363 template <
typename... HandlerTs>
371 OS <<
"Multiple errors:\n";
372 for (
auto &ErrPayload : Payloads) {
384 ErrorList(std::unique_ptr<ErrorInfoBase> Payload1,
385 std::unique_ptr<ErrorInfoBase> Payload2) {
387 "ErrorList constructor payloads should be singleton errors");
388 Payloads.push_back(std::move(Payload1));
389 Payloads.push_back(std::move(Payload2));
398 auto &E1List =
static_cast<ErrorList &
>(*E1.getPtr());
400 auto E2Payload = E2.takePayload();
401 auto &E2List =
static_cast<ErrorList &
>(*E2Payload);
402 for (
auto &Payload : E2List.Payloads)
403 E1List.Payloads.push_back(std::move(Payload));
405 E1List.Payloads.push_back(E2.takePayload());
410 auto &E2List =
static_cast<ErrorList &
>(*E2.getPtr());
411 E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload());
414 return Error(std::unique_ptr<ErrorList>(
415 new ErrorList(E1.takePayload(), E2.takePayload())));
418 std::vector<std::unique_ptr<ErrorInfoBase>> Payloads;
425 return ErrorList::join(std::move(E1), std::move(E2));
436 template <
class OtherT>
friend class Expected;
438 static const bool isRef = std::is_reference<T>::value;
440 using wrap = std::reference_wrapper<typename std::remove_reference<T>::type>;
442 using error_type = std::unique_ptr<ErrorInfoBase>;
449 using reference =
typename std::remove_reference<T>::type &;
450 using const_reference =
const typename std::remove_reference<T>::type &;
451 using pointer =
typename std::remove_reference<T>::type *;
452 using const_pointer =
const typename std::remove_reference<T>::type *;
458 #
if LLVM_ENABLE_ABI_BREAKING_CHECKS
463 assert(Err &&
"Cannot create Expected<T> from Error success value.");
464 new (getErrorStorage()) error_type(Err.takePayload());
474 template <
typename OtherT>
476 typename std::enable_if<std::is_convertible<OtherT, T>::value>::
type 479 #
if LLVM_ENABLE_ABI_BREAKING_CHECKS
484 new (getStorage())
storage_type(std::forward<OtherT>(Val));
492 template <
class OtherT>
494 typename std::enable_if<std::is_convertible<OtherT, T>::value>::
type 496 moveConstruct(std::move(
Other));
501 template <
class OtherT>
504 typename std::enable_if<!std::is_convertible<OtherT, T>::value>::
type * =
506 moveConstruct(std::move(
Other));
511 moveAssign(std::move(
Other));
519 getStorage()->~storage_type();
521 getErrorStorage()->~error_type();
526 #if LLVM_ENABLE_ABI_BREAKING_CHECKS 527 Unchecked = HasError;
535 return *getStorage();
539 const_reference
get()
const {
546 return HasError && (*getErrorStorage())->
template isA<ErrT>();
554 #if LLVM_ENABLE_ABI_BREAKING_CHECKS 563 return toPointer(getStorage());
569 return toPointer(getStorage());
575 return *getStorage();
581 return *getStorage();
586 static bool compareThisIfSameType(
const T1 &a,
const T1 &b) {
590 template <
class T1,
class T2>
591 static bool compareThisIfSameType(
const T1 &a,
const T2 &b) {
596 HasError =
Other.HasError;
597 #if LLVM_ENABLE_ABI_BREAKING_CHECKS 599 Other.Unchecked =
false;
605 new (getErrorStorage()) error_type(std::move(*
Other.getErrorStorage()));
611 if (compareThisIfSameType(*
this,
Other))
615 new (
this) Expected(std::move(
Other));
618 pointer toPointer(pointer Val) {
return Val; }
620 const_pointer toPointer(const_pointer Val)
const {
return Val; }
622 pointer toPointer(wrap *Val) {
return &Val->get(); }
624 const_pointer toPointer(
const wrap *Val)
const {
return &Val->get(); }
627 assert(!HasError &&
"Cannot get value when an error exists!");
628 return reinterpret_cast<storage_type *
>(TStorage.buffer);
632 assert(!HasError &&
"Cannot get value when an error exists!");
633 return reinterpret_cast<const storage_type *
>(TStorage.buffer);
636 error_type *getErrorStorage() {
637 assert(HasError &&
"Cannot get error when a value exists!");
638 return reinterpret_cast<error_type *
>(ErrorStorage.buffer);
641 const error_type *getErrorStorage()
const {
642 assert(HasError &&
"Cannot get error when a value exists!");
643 return reinterpret_cast<const error_type *
>(ErrorStorage.buffer);
647 void setUnchecked() {
648 #if LLVM_ENABLE_ABI_BREAKING_CHECKS 653 #if LLVM_ENABLE_ABI_BREAKING_CHECKS 656 void fatalUncheckedExpected()
const {
657 dbgs() <<
"Expected<T> must be checked before access or destruction.\n";
659 dbgs() <<
"Unchecked Expected<T> contained error:\n";
660 (*getErrorStorage())->
log(
dbgs());
662 dbgs() <<
"Expected<T> value was in success state. (Note: Expected<T> " 663 "values in success mode must still be checked prior to being " 669 void assertIsChecked() {
670 #if LLVM_ENABLE_ABI_BREAKING_CHECKS 672 fatalUncheckedExpected();
681 #if LLVM_ENABLE_ABI_BREAKING_CHECKS 689 bool gen_crash_diag =
true);
707 Msg =
"Failure value returned from cantFail wrapped call";
725 template <
typename T>
728 return std::move(*ValOrErr);
731 Msg =
"Failure value returned from cantFail wrapped call";
749 template <
typename T>
755 Msg =
"Failure value returned from cantFail wrapped call";
762 template <
typename HandlerT>
765 &std::remove_reference<HandlerT>::type::operator())> {};
771 return E.template isA<ErrT>();
774 template <
typename HandlerT>
776 assert(appliesTo(*E) &&
"Applying incorrect handler");
777 return H(static_cast<ErrT &>(*E));
785 return E.template isA<ErrT>();
788 template <
typename HandlerT>
790 assert(appliesTo(*E) &&
"Applying incorrect handler");
791 H(static_cast<ErrT &>(*E));
797 template <
typename ErrT>
801 return E.template isA<ErrT>();
804 template <
typename HandlerT>
806 assert(appliesTo(*E) &&
"Applying incorrect handler");
807 std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
808 return H(std::move(SubE));
813 template <
typename ErrT>
817 return E.template isA<ErrT>();
820 template <
typename HandlerT>
822 assert(appliesTo(*E) &&
"Applying incorrect handler");
823 std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
830 template <
typename C,
typename RetT,
typename ErrT>
835 template <
typename C,
typename RetT,
typename ErrT>
840 template <
typename C,
typename RetT,
typename ErrT>
845 template <
typename C,
typename RetT,
typename ErrT>
851 template <
typename C,
typename RetT,
typename ErrT>
857 template <
typename C,
typename RetT,
typename ErrT>
862 return Error(std::move(Payload));
865 template <
typename HandlerT,
typename... HandlerTs>
867 HandlerT &&Handler, HandlerTs &&... Handlers) {
872 std::forward<HandlerTs>(Handlers)...);
881 template <
typename... HandlerTs>
886 std::unique_ptr<ErrorInfoBase> Payload = E.takePayload();
891 for (
auto &
P : List.Payloads)
898 return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...);
904 template <
typename... HandlerTs>
939 template <
typename T,
typename RecoveryFtor,
typename... HandlerTs>
941 HandlerTs &&... Handlers) {
946 std::forward<HandlerTs>(Handlers)...))
947 return std::move(Err);
949 return RecoveryPath();
992 bool IsError =
static_cast<bool>(Err);
1043 template <
typename T>
1047 : ValOrErr(ValOrErr) {
1054 ValOrErr->setUnchecked();
1069 virtual void anchor()
override;
1105 if (
auto EC = EO.getError())
1107 return std::move(*EO);
1112 if (
auto Err = E.takeError())
1114 return std::move(*E);
1159 const bool PrintMsgOnly =
false;
1163 template <
typename... Ts>
1165 const Ts &... Vals) {
1168 Stream <<
format(Fmt, Vals...);
1169 return make_error<StringError>(Stream.
str(), EC);
1184 assert(Err && !FileName.empty() &&
"Trying to log after takeError().");
1185 OS <<
"'" << FileName <<
"': ";
1197 FileError(std::string
F, std::unique_ptr<ErrorInfoBase> E) {
1198 assert(E &&
"Cannot create FileError from Error success value.");
1200 "The file name provided to FileError must not be empty.");
1206 return Error(std::unique_ptr<FileError>(
new FileError(F, E.takePayload())));
1209 std::string FileName;
1210 std::unique_ptr<ErrorInfoBase> Err;
1216 return FileError::build(F, std::move(E));
1229 : Banner(
std::move(Banner)),
1230 GetExitCode([=](
const Error &) {
return DefaultErrorExitCode; }) {}
1233 void setBanner(std::string Banner) { this->Banner = std::move(Banner); }
1237 this->GetExitCode = std::move(GetExitCode);
1246 checkError(E.takeError());
1247 return std::move(*E);
1253 checkError(E.takeError());
1258 void checkError(
Error Err)
const {
1260 int ExitCode = GetExitCode(Err);
1267 std::function<int(const Error &)> GetExitCode;
1272 return reinterpret_cast<LLVMErrorRef>(Err.takePayload().release());
1277 return Error(std::unique_ptr<ErrorInfoBase>(
1278 reinterpret_cast<ErrorInfoBase *>(ErrRef)));
1283 #endif // LLVM_SUPPORT_ERROR_H reference operator*()
Returns a reference to the stored T value.
static const void * classID()
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
bool errorIsA() const
Check that this Expected<T> is an error of type ErrT.
Represents either an error or a value T.
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
const void * dynamicClassID() const
Returns the dynamic class id of this error, or null if this is a success value.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This class represents lattice values for constants.
Subclass of Error for the sole purpose of identifying the success path in the type system...
void push_back(const T &Elt)
AlignedCharArrayUnion< storage_type > TStorage
Helper for check-and-exit error handling.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
void log(raw_ostream &OS) const override
Print an error message to an output stream.
static const char * getPtr(const MachOObjectFile &O, size_t Offset)
T & operator()(Expected< T &> &&E) const
Check E.
static bool appliesTo(const ErrorInfoBase &E)
Helper for Expected<T>s used as out-parameters.
virtual std::string message() const
Return the error message as a string.
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.
block Block Frequency true
Error takeError()
Take ownership of the stored error.
Expected< T > handleExpected(Expected< T > ValOrErr, RecoveryFtor &&RecoveryPath, HandlerTs &&... Handlers)
Handle any errors (if present) in an Expected<T>, then try a recovery path.
Base class for error info classes.
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
#define LLVM_ATTRIBUTE_NOINLINE
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...
#define LLVM_UNLIKELY(EXPR)
#define LLVM_NODISCARD
LLVM_NODISCARD - Warn if a type or return value is discarded.
static Error apply(HandlerT &&H, std::unique_ptr< ErrorInfoBase > E)
This class wraps a filename and another Error.
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...
Attribute unwrap(LLVMAttributeRef Attr)
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 apply(Opt *O, const Mod &M, const Mods &... Ms)
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
const_reference operator*() const
Returns a const reference to the stored T value.
Error createFileError(std::string F, Error E)
Concatenate a source file path and/or name with an Error.
const void * dynamicClassID() const override
Error & operator=(Error &&Other)
Move-assign an error value.
ErrorAsOutParameter(Error *Err)
virtual const void * dynamicClassID() const =0
struct LLVMOpaqueError * LLVMErrorRef
Opaque reference to an error instance.
Error build(ArrayRef< Module *> Mods, SmallVector< char, 0 > &Symtab, StringTableBuilder &StrtabBuilder, BumpPtrAllocator &Alloc)
Fills in Symtab and StrtabBuilder with a valid symbol and string table for Mods.
ECError(std::error_code EC)
void setExitCodeMapper(std::function< int(const Error &)> GetExitCode)
Set the exit-code mapper function.
const_pointer operator->() const
Returns a const pointer to the stored T value.
Expected(Error Err)
Create an Expected<T> error value from the given Error.
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
void operator()(Error Err) const
Check Err. If it's in a failure state log the error(s) and exit.
AlignedCharArrayUnion< error_type > ErrorStorage
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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>.
void consumeError(Error Err)
Consume a Error without doing anything.
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
const std::string & getMessage() const
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static Error apply(HandlerT &&H, std::unique_ptr< ErrorInfoBase > E)
Special ErrorInfo subclass representing a list of ErrorInfos.
static const void * classID()
Error(std::unique_ptr< ErrorInfoBase > Payload)
Create an error value.
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
static ErrorSuccess success()
Create a success value.
static bool appliesTo(const ErrorInfoBase &E)
friend raw_ostream & operator<<(raw_ostream &OS, const Error &E)
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...
virtual std::error_code convertToErrorCode() const =0
Convert this error to a std::error_code.
T operator()(Expected< T > &&E) const
Check E.
Expected & operator=(Expected &&Other)
Move-assign from another Expected<T>.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void setBanner(std::string Banner)
Set the banner string for any errors caught by operator().
Base class for user error types.
Helper for Errors used as out-parameters.
static Error apply(HandlerT &&H, std::unique_ptr< ErrorInfoBase > E)
#define LLVM_ATTRIBUTE_NORETURN
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.
bool isA(const void *const ClassID) const override
bool isA() const
Check whether one error is a subclass of another.
void setErrorCode(std::error_code EC)
typename std::conditional< isRef, wrap, T >::type storage_type
ExpectedAsOutParameter(Expected< T > *ValOrErr)
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.
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
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.
print Print MemDeps of function
~ExpectedAsOutParameter()
std::error_code errorToErrorCode(Error Err)
Helper for converting an ECError to a std::error_code.
virtual bool isA(const void *const ClassID) const
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...