diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h index 6832e3df2f9..148494c5d87 100644 --- a/include/llvm/Support/ErrorOr.h +++ b/include/llvm/Support/ErrorOr.h @@ -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 -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 struct ErrorOrUserDataTraits : llvm::false_type {}; - #if LLVM_HAS_CXX11_TYPETRAITS && LLVM_HAS_RVALUE_REFERENCES template typename std::enable_if< std::is_constructible::value @@ -111,44 +79,6 @@ public: /// buffer->write("adena"); /// \endcode /// -/// ErrorOr 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() 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 : std::true_type { -/// static error_code error() { -/// return make_error_code(errc::invalid_argument); -/// } -/// }; -/// } // end namespace llvm -/// -/// using namespace llvm; -/// -/// ErrorOr foo() { -/// return InvalidArgError("adena"); -/// } -/// -/// int main() { -/// auto a = foo(); -/// if (!a && error_code(a) == errc::invalid_argument) -/// llvm::errs() << a.getError().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::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 - ErrorOr(UserDataT UD, typename - enable_if_c::value>::type* = 0) - : HasError(true), IsValid(true) { - Error = new ErrorHolder(llvm_move(UD)); - Error->Error = ErrorOrUserDataTraits::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 - 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::error() == Error->Error && - "Incorrect user error data type for error!"); - if (!Error->HasUserData) - return ET(); - return reinterpret_cast*>(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 TStorage; - ErrorHolderBase *Error; + error_code Error; }; bool HasError : 1; bool IsValid : 1; }; -// ErrorOr specialization for void. -template <> -class ErrorOr { -public: - ErrorOr() : Error(0, 0) {} - - template - ErrorOr(E ErrorCode, typename enable_if_c::value || - is_error_condition_enum::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 - ErrorOr(UserDataT UD, typename - enable_if_c::value>::type* = 0) - : Error(0, 0) { - ErrorHolderBase *E = new ErrorHolder(llvm_move(UD)); - E->Error = ErrorOrUserDataTraits::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 - ET getError() const { - assert(ErrorOrUserDataTraits::error() == *this && - "Incorrect user error data type for error!"); - if (!Error.getPointer()->HasUserData) - return ET(); - return reinterpret_cast *>( - 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 Error; -}; - template typename enable_if_c::value || is_error_condition_enum::value, bool>::type diff --git a/unittests/Support/ErrorOrTest.cpp b/unittests/Support/ErrorOrTest.cpp index 4853426c947..feb6a086e19 100644 --- a/unittests/Support/ErrorOrTest.cpp +++ b/unittests/Support/ErrorOrTest.cpp @@ -45,9 +45,6 @@ TEST(ErrorOr, Types) { *a = 42; EXPECT_EQ(42, x); - EXPECT_FALSE(ErrorOr(errc::broken_pipe)); - EXPECT_TRUE(ErrorOr(errc::success)); - #if LLVM_HAS_CXX11_STDLIB // Move only types. EXPECT_EQ(3, **t3()); @@ -67,38 +64,3 @@ TEST(ErrorOr, Covariant) { #endif } } // end anon namespace - -struct InvalidArgError { - InvalidArgError() {} - InvalidArgError(std::string S) : ArgName(S) {} - std::string ArgName; -}; - -namespace llvm { -template<> -struct ErrorOrUserDataTraits : true_type { - static error_code error() { - return make_error_code(errc::invalid_argument); - } -}; -} // end namespace llvm - -ErrorOr t4() { - return InvalidArgError("adena"); -} - -ErrorOr t5() { - return InvalidArgError("pie"); -} - -namespace { -TEST(ErrorOr, UserErrorData) { - ErrorOr a = t4(); - EXPECT_EQ(errc::invalid_argument, a); - EXPECT_EQ("adena", t4().getError().ArgName); - - ErrorOr b = t5(); - EXPECT_EQ(errc::invalid_argument, b); - EXPECT_EQ("pie", b.getError().ArgName); -} -} // end anon namespace