X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FSupport%2FErrorOr.h;h=ca6ede73e8df1315d6eb7da25569123127e208ff;hb=b9f514b1bf24a7b370f03868189ed6946ead2ed7;hp=39fec3b5ae3db6cd7f2cdbcdf90757a9214d8d77;hpb=e82dec5c0f6708164242192cb3c9f43e2fc6ec36;p=oota-llvm.git diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h index 39fec3b5ae3..ca6ede73e8d 100644 --- a/include/llvm/Support/ErrorOr.h +++ b/include/llvm/Support/ErrorOr.h @@ -1,4 +1,4 @@ -//===- llvm/Support/ErrorOr.h - Error Smart Pointer -----------------------===// +//===- llvm/Support/ErrorOr.h - Error Smart Pointer -------------*- C++ -*-===// // // The LLVM Linker // @@ -13,20 +13,16 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_ERROR_OR_H -#define LLVM_SUPPORT_ERROR_OR_H +#ifndef LLVM_SUPPORT_ERROROR_H +#define LLVM_SUPPORT_ERROROR_H #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/AlignOf.h" -#include "llvm/Support/system_error.h" -#include "llvm/Support/type_traits.h" #include -#if LLVM_HAS_CXX11_TYPETRAITS +#include #include -#endif namespace llvm { -#if LLVM_HAS_CXX11_TYPETRAITS && LLVM_HAS_RVALUE_REFERENCES template typename std::enable_if< std::is_constructible::value , typename std::remove_reference::type>::type && @@ -40,12 +36,6 @@ typename std::enable_if< !std::is_constructible::value moveIfMoveConstructible(V &Val) { return Val; } -#else -template -V &moveIfMoveConstructible(V &Val) { - return Val; -} -#endif /// \brief Stores a reference that can be changed. template @@ -78,9 +68,9 @@ public: /// \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 -/// value. Accessing the value when there is an error has undefined behavior. +/// Implicit conversion to bool returns true if there is a usable value. The +/// unary * and -> operators provide pointer like access to the value. Accessing +/// the value when there is an error has undefined behavior. /// /// When T is a reference type the behaivor is slightly different. The reference /// is held in a std::reference_wrapper::type>, and @@ -91,31 +81,30 @@ public: template class ErrorOr { template friend class ErrorOr; - static const bool isRef = is_reference::value; - typedef ReferenceStorage::type> wrap; + static const bool isRef = std::is_reference::value; + typedef ReferenceStorage::type> wrap; public: - typedef typename - conditional< isRef - , wrap - , T - >::type storage_type; + typedef typename std::conditional::type storage_type; private: - typedef typename remove_reference::type &reference; - typedef typename remove_reference::type *pointer; + typedef typename std::remove_reference::type &reference; + typedef const typename std::remove_reference::type &const_reference; + typedef typename std::remove_reference::type *pointer; + typedef const typename std::remove_reference::type *const_pointer; public: template - ErrorOr(E ErrorCode, typename enable_if_c::value || - is_error_condition_enum::value, - void *>::type = 0) + ErrorOr(E ErrorCode, + typename std::enable_if::value || + std::is_error_condition_enum::value, + void *>::type = 0) : HasError(true) { - new (getErrorStorage()) error_code(make_error_code(ErrorCode)); + new (getErrorStorage()) std::error_code(make_error_code(ErrorCode)); } - ErrorOr(llvm::error_code EC) : HasError(true) { - new (getErrorStorage()) error_code(EC); + ErrorOr(std::error_code EC) : HasError(true) { + new (getErrorStorage()) std::error_code(EC); } ErrorOr(T Val) : HasError(false) { @@ -127,42 +116,52 @@ public: } template - ErrorOr(const ErrorOr &Other) { + ErrorOr( + const ErrorOr &Other, + typename std::enable_if::value>::type * = + nullptr) { copyConstruct(Other); } - ErrorOr &operator =(const ErrorOr &Other) { - copyAssign(Other); - return *this; - } - template - ErrorOr &operator =(const ErrorOr &Other) { - copyAssign(Other); - return *this; + explicit ErrorOr( + const ErrorOr &Other, + typename std::enable_if< + !std::is_convertible::value>::type * = nullptr) { + copyConstruct(Other); } -#if LLVM_HAS_RVALUE_REFERENCES ErrorOr(ErrorOr &&Other) { moveConstruct(std::move(Other)); } template - ErrorOr(ErrorOr &&Other) { + ErrorOr( + ErrorOr &&Other, + typename std::enable_if::value>::type * = + nullptr) { moveConstruct(std::move(Other)); } - ErrorOr &operator =(ErrorOr &&Other) { - moveAssign(std::move(Other)); + // This might eventually need SFINAE but it's more complex than is_convertible + // & I'm too lazy to write it right now. + template + explicit ErrorOr( + ErrorOr &&Other, + typename std::enable_if::value>::type * = + nullptr) { + moveConstruct(std::move(Other)); + } + + ErrorOr &operator=(const ErrorOr &Other) { + copyAssign(Other); return *this; } - template - ErrorOr &operator =(ErrorOr &&Other) { + ErrorOr &operator=(ErrorOr &&Other) { moveAssign(std::move(Other)); return *this; } -#endif ~ErrorOr() { if (!HasError) @@ -170,25 +169,29 @@ public: } /// \brief Return false if there is an error. - LLVM_EXPLICIT operator bool() const { + explicit operator bool() const { return !HasError; } reference get() { return *getStorage(); } - const reference get() const { return const_cast >(this)->get(); } + const_reference get() const { return const_cast *>(this)->get(); } - error_code getError() const { - return HasError ? *getErrorStorage() : error_code::success(); + std::error_code getError() const { + return HasError ? *getErrorStorage() : std::error_code(); } pointer operator ->() { return toPointer(getStorage()); } + const_pointer operator->() const { return toPointer(getStorage()); } + reference operator *() { return *getStorage(); } + const_reference operator*() const { return *getStorage(); } + private: template void copyConstruct(const ErrorOr &Other) { @@ -199,7 +202,7 @@ private: } else { // Get other's error. HasError = true; - new (getErrorStorage()) error_code(Other.getError()); + new (getErrorStorage()) std::error_code(Other.getError()); } } @@ -222,7 +225,6 @@ private: new (this) ErrorOr(Other); } -#if LLVM_HAS_RVALUE_REFERENCES template void moveConstruct(ErrorOr &&Other) { if (!Other.HasError) { @@ -232,7 +234,7 @@ private: } else { // Get other's error. HasError = true; - new (getErrorStorage()) error_code(Other.getError()); + new (getErrorStorage()) std::error_code(Other.getError()); } } @@ -244,16 +246,19 @@ private: this->~ErrorOr(); new (this) ErrorOr(std::move(Other)); } -#endif pointer toPointer(pointer Val) { return Val; } + const_pointer toPointer(const_pointer Val) const { return Val; } + pointer toPointer(wrap *Val) { return &Val->get(); } + const_pointer toPointer(const wrap *Val) const { return &Val->get(); } + storage_type *getStorage() { assert(!HasError && "Cannot get value when an error exists!"); return reinterpret_cast(TStorage.buffer); @@ -264,28 +269,29 @@ private: return reinterpret_cast(TStorage.buffer); } - error_code *getErrorStorage() { + std::error_code *getErrorStorage() { assert(HasError && "Cannot get error when a value exists!"); - return reinterpret_cast(ErrorStorage.buffer); + return reinterpret_cast(ErrorStorage.buffer); } - const error_code *getErrorStorage() const { + const std::error_code *getErrorStorage() const { return const_cast *>(this)->getErrorStorage(); } union { AlignedCharArrayUnion TStorage; - AlignedCharArrayUnion ErrorStorage; + AlignedCharArrayUnion ErrorStorage; }; bool HasError : 1; }; -template -typename enable_if_c::value || - is_error_condition_enum::value, bool>::type -operator ==(ErrorOr &Err, E Code) { - return error_code(Err) == Code; +template +typename std::enable_if::value || + std::is_error_condition_enum::value, + bool>::type +operator==(const ErrorOr &Err, E Code) { + return Err.getError() == Code; } } // end namespace llvm