|
@@ -27,38 +27,6 @@
|
|
|
#endif
|
|
|
|
|
|
namespace llvm {
|
|
|
-struct ErrorHolderBase {
|
|
|
- error_code Error;
|
|
|
- uint16_t RefCount;
|
|
|
- bool HasUserData;
|
|
|
-
|
|
|
- ErrorHolderBase() : RefCount(1) {}
|
|
|
-
|
|
|
- void acquire() {
|
|
|
- ++RefCount;
|
|
|
- }
|
|
|
-
|
|
|
- void release() {
|
|
|
- if (--RefCount == 0)
|
|
|
- delete this;
|
|
|
- }
|
|
|
-
|
|
|
-protected:
|
|
|
- virtual ~ErrorHolderBase() {}
|
|
|
-};
|
|
|
-
|
|
|
-template<class T>
|
|
|
-struct ErrorHolder : ErrorHolderBase {
|
|
|
-#if LLVM_HAS_RVALUE_REFERENCES
|
|
|
- ErrorHolder(T &&UD) : UserData(llvm_move(UD)) {}
|
|
|
-#else
|
|
|
- ErrorHolder(T &UD) : UserData(UD) {}
|
|
|
-#endif
|
|
|
- T UserData;
|
|
|
-};
|
|
|
-
|
|
|
-template<class Tp> struct ErrorOrUserDataTraits : llvm::false_type {};
|
|
|
-
|
|
|
#if LLVM_HAS_CXX11_TYPETRAITS && LLVM_HAS_RVALUE_REFERENCES
|
|
|
template<class T, class V>
|
|
|
typename std::enable_if< std::is_constructible<T, V>::value
|
|
@@ -111,44 +79,6 @@ public:
|
|
|
/// buffer->write("adena");
|
|
|
/// \endcode
|
|
|
///
|
|
|
-/// ErrorOr<T> also supports user defined data for specific error_codes. To use
|
|
|
-/// this feature you must first add a template specialization of
|
|
|
-/// ErrorOrUserDataTraits derived from std::true_type for your type in the lld
|
|
|
-/// namespace. This specialization must have a static error_code error()
|
|
|
-/// function that returns the error_code this data is used with.
|
|
|
-///
|
|
|
-/// getError<UserData>() may be called to get either the stored user data, or
|
|
|
-/// a default constructed UserData if none was stored.
|
|
|
-///
|
|
|
-/// Example:
|
|
|
-/// \code
|
|
|
-/// struct InvalidArgError {
|
|
|
-/// InvalidArgError() {}
|
|
|
-/// InvalidArgError(std::string S) : ArgName(S) {}
|
|
|
-/// std::string ArgName;
|
|
|
-/// };
|
|
|
-///
|
|
|
-/// namespace llvm {
|
|
|
-/// template<>
|
|
|
-/// struct ErrorOrUserDataTraits<InvalidArgError> : std::true_type {
|
|
|
-/// static error_code error() {
|
|
|
-/// return make_error_code(errc::invalid_argument);
|
|
|
-/// }
|
|
|
-/// };
|
|
|
-/// } // end namespace llvm
|
|
|
-///
|
|
|
-/// using namespace llvm;
|
|
|
-///
|
|
|
-/// ErrorOr<int> foo() {
|
|
|
-/// return InvalidArgError("adena");
|
|
|
-/// }
|
|
|
-///
|
|
|
-/// int main() {
|
|
|
-/// auto a = foo();
|
|
|
-/// if (!a && error_code(a) == errc::invalid_argument)
|
|
|
-/// llvm::errs() << a.getError<InvalidArgError>().ArgName << "\n";
|
|
|
-/// }
|
|
|
-/// \endcode
|
|
|
///
|
|
|
/// An implicit conversion to bool provides a way to check if there was an
|
|
|
/// error. The unary * and -> operators provide pointer like access to the
|
|
@@ -185,24 +115,11 @@ public:
|
|
|
is_error_condition_enum<E>::value,
|
|
|
void *>::type = 0)
|
|
|
: HasError(true), IsValid(true) {
|
|
|
- Error = new ErrorHolderBase;
|
|
|
- Error->Error = make_error_code(ErrorCode);
|
|
|
- Error->HasUserData = false;
|
|
|
+ Error = make_error_code(ErrorCode);
|
|
|
}
|
|
|
|
|
|
ErrorOr(llvm::error_code EC) : HasError(true), IsValid(true) {
|
|
|
- Error = new ErrorHolderBase;
|
|
|
- Error->Error = EC;
|
|
|
- Error->HasUserData = false;
|
|
|
- }
|
|
|
-
|
|
|
- template<class UserDataT>
|
|
|
- ErrorOr(UserDataT UD, typename
|
|
|
- enable_if_c<ErrorOrUserDataTraits<UserDataT>::value>::type* = 0)
|
|
|
- : HasError(true), IsValid(true) {
|
|
|
- Error = new ErrorHolder<UserDataT>(llvm_move(UD));
|
|
|
- Error->Error = ErrorOrUserDataTraits<UserDataT>::error();
|
|
|
- Error->HasUserData = true;
|
|
|
+ Error = EC;
|
|
|
}
|
|
|
|
|
|
ErrorOr(T Val) : HasError(false), IsValid(true) {
|
|
@@ -254,23 +171,10 @@ public:
|
|
|
~ErrorOr() {
|
|
|
if (!IsValid)
|
|
|
return;
|
|
|
- if (HasError)
|
|
|
- Error->release();
|
|
|
- else
|
|
|
+ if (!HasError)
|
|
|
get()->~storage_type();
|
|
|
}
|
|
|
|
|
|
- template<class ET>
|
|
|
- ET getError() const {
|
|
|
- assert(IsValid && "Cannot get the error of a default constructed ErrorOr!");
|
|
|
- assert(HasError && "Cannot get an error if none exists!");
|
|
|
- assert(ErrorOrUserDataTraits<ET>::error() == Error->Error &&
|
|
|
- "Incorrect user error data type for error!");
|
|
|
- if (!Error->HasUserData)
|
|
|
- return ET();
|
|
|
- return reinterpret_cast<const ErrorHolder<ET>*>(Error)->UserData;
|
|
|
- }
|
|
|
-
|
|
|
typedef void (*unspecified_bool_type)();
|
|
|
static void unspecified_bool_true() {}
|
|
|
|
|
@@ -282,7 +186,7 @@ public:
|
|
|
|
|
|
operator llvm::error_code() const {
|
|
|
assert(IsValid && "Can't do anything on a default constructed ErrorOr!");
|
|
|
- return HasError ? Error->Error : llvm::error_code::success();
|
|
|
+ return HasError ? Error : llvm::error_code::success();
|
|
|
}
|
|
|
|
|
|
pointer operator ->() {
|
|
@@ -308,7 +212,6 @@ private:
|
|
|
// Get other's error.
|
|
|
Error = Other.Error;
|
|
|
HasError = true;
|
|
|
- Error->acquire();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -385,124 +288,12 @@ private:
|
|
|
|
|
|
union {
|
|
|
AlignedCharArrayUnion<storage_type> TStorage;
|
|
|
- ErrorHolderBase *Error;
|
|
|
+ error_code Error;
|
|
|
};
|
|
|
bool HasError : 1;
|
|
|
bool IsValid : 1;
|
|
|
};
|
|
|
|
|
|
-// ErrorOr specialization for void.
|
|
|
-template <>
|
|
|
-class ErrorOr<void> {
|
|
|
-public:
|
|
|
- ErrorOr() : Error(0, 0) {}
|
|
|
-
|
|
|
- template <class E>
|
|
|
- ErrorOr(E ErrorCode, typename enable_if_c<is_error_code_enum<E>::value ||
|
|
|
- is_error_condition_enum<E>::value,
|
|
|
- void *> ::type = 0)
|
|
|
- : Error(0, 0) {
|
|
|
- error_code EC = make_error_code(ErrorCode);
|
|
|
- if (EC == errc::success) {
|
|
|
- Error.setInt(1);
|
|
|
- return;
|
|
|
- }
|
|
|
- ErrorHolderBase *EHB = new ErrorHolderBase;
|
|
|
- EHB->Error = EC;
|
|
|
- EHB->HasUserData = false;
|
|
|
- Error.setPointer(EHB);
|
|
|
- }
|
|
|
-
|
|
|
- ErrorOr(llvm::error_code EC) : Error(0, 0) {
|
|
|
- if (EC == errc::success) {
|
|
|
- Error.setInt(1);
|
|
|
- return;
|
|
|
- }
|
|
|
- ErrorHolderBase *E = new ErrorHolderBase;
|
|
|
- E->Error = EC;
|
|
|
- E->HasUserData = false;
|
|
|
- Error.setPointer(E);
|
|
|
- }
|
|
|
-
|
|
|
- template<class UserDataT>
|
|
|
- ErrorOr(UserDataT UD, typename
|
|
|
- enable_if_c<ErrorOrUserDataTraits<UserDataT>::value>::type* = 0)
|
|
|
- : Error(0, 0) {
|
|
|
- ErrorHolderBase *E = new ErrorHolder<UserDataT>(llvm_move(UD));
|
|
|
- E->Error = ErrorOrUserDataTraits<UserDataT>::error();
|
|
|
- E->HasUserData = true;
|
|
|
- Error.setPointer(E);
|
|
|
- }
|
|
|
-
|
|
|
- ErrorOr(const ErrorOr &Other) : Error(0, 0) {
|
|
|
- Error = Other.Error;
|
|
|
- if (Other.Error.getPointer()->Error) {
|
|
|
- Error.getPointer()->acquire();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- ErrorOr &operator =(const ErrorOr &Other) {
|
|
|
- if (this == &Other)
|
|
|
- return *this;
|
|
|
-
|
|
|
- this->~ErrorOr();
|
|
|
- new (this) ErrorOr(Other);
|
|
|
-
|
|
|
- return *this;
|
|
|
- }
|
|
|
-
|
|
|
-#if LLVM_HAS_RVALUE_REFERENCES
|
|
|
- ErrorOr(ErrorOr &&Other) : Error(0) {
|
|
|
- // Get other's error.
|
|
|
- Error = Other.Error;
|
|
|
- // Tell other not to do any destruction.
|
|
|
- Other.Error.setPointer(0);
|
|
|
- }
|
|
|
-
|
|
|
- ErrorOr &operator =(ErrorOr &&Other) {
|
|
|
- if (this == &Other)
|
|
|
- return *this;
|
|
|
-
|
|
|
- this->~ErrorOr();
|
|
|
- new (this) ErrorOr(std::move(Other));
|
|
|
-
|
|
|
- return *this;
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- ~ErrorOr() {
|
|
|
- if (Error.getPointer())
|
|
|
- Error.getPointer()->release();
|
|
|
- }
|
|
|
-
|
|
|
- template<class ET>
|
|
|
- ET getError() const {
|
|
|
- assert(ErrorOrUserDataTraits<ET>::error() == *this &&
|
|
|
- "Incorrect user error data type for error!");
|
|
|
- if (!Error.getPointer()->HasUserData)
|
|
|
- return ET();
|
|
|
- return reinterpret_cast<const ErrorHolder<ET> *>(
|
|
|
- Error.getPointer())->UserData;
|
|
|
- }
|
|
|
-
|
|
|
- typedef void (*unspecified_bool_type)();
|
|
|
- static void unspecified_bool_true() {}
|
|
|
-
|
|
|
- /// \brief Return false if there is an error.
|
|
|
- operator unspecified_bool_type() const {
|
|
|
- return Error.getInt() ? unspecified_bool_true : 0;
|
|
|
- }
|
|
|
-
|
|
|
- operator llvm::error_code() const {
|
|
|
- return Error.getInt() ? make_error_code(errc::success)
|
|
|
- : Error.getPointer()->Error;
|
|
|
- }
|
|
|
-
|
|
|
-private:
|
|
|
- // If the bit is 1, the error is success.
|
|
|
- llvm::PointerIntPair<ErrorHolderBase *, 1> Error;
|
|
|
-};
|
|
|
-
|
|
|
template<class T, class E>
|
|
|
typename enable_if_c<is_error_code_enum<E>::value ||
|
|
|
is_error_condition_enum<E>::value, bool>::type
|