mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-26 23:32:58 +00:00
[Support][ErrorOr] Add support for convertable types.
Thanks to Andrew, David, and Aaron for helping fix this. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174552 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f91b23c8cd
commit
780e9004c8
@ -162,6 +162,7 @@ public:
|
|||||||
/// T cannot be a rvalue reference.
|
/// T cannot be a rvalue reference.
|
||||||
template<class T>
|
template<class T>
|
||||||
class ErrorOr {
|
class ErrorOr {
|
||||||
|
template <class OtherT> friend class ErrorOr;
|
||||||
static const bool isRef = is_reference<T>::value;
|
static const bool isRef = is_reference<T>::value;
|
||||||
typedef ReferenceStorage<typename remove_reference<T>::type> wrap;
|
typedef ReferenceStorage<typename remove_reference<T>::type> wrap;
|
||||||
|
|
||||||
@ -199,60 +200,43 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr(const ErrorOr &Other) : IsValid(false) {
|
ErrorOr(const ErrorOr &Other) : IsValid(false) {
|
||||||
// Construct an invalid ErrorOr if other is invalid.
|
copyConstruct(Other);
|
||||||
if (!Other.IsValid)
|
}
|
||||||
return;
|
|
||||||
IsValid = true;
|
template <class OtherT>
|
||||||
if (!Other.HasError) {
|
ErrorOr(const ErrorOr<OtherT> &Other) : IsValid(false) {
|
||||||
// Get the other value.
|
copyConstruct(Other);
|
||||||
HasError = false;
|
|
||||||
new (get()) storage_type(*Other.get());
|
|
||||||
} else {
|
|
||||||
// Get other's error.
|
|
||||||
Error = Other.Error;
|
|
||||||
HasError = true;
|
|
||||||
Error->aquire();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr &operator =(const ErrorOr &Other) {
|
ErrorOr &operator =(const ErrorOr &Other) {
|
||||||
if (this == &Other)
|
copyAssign(Other);
|
||||||
return *this;
|
return *this;
|
||||||
|
}
|
||||||
this->~ErrorOr();
|
|
||||||
new (this) ErrorOr(Other);
|
|
||||||
|
|
||||||
|
template <class OtherT>
|
||||||
|
ErrorOr &operator =(const ErrorOr<OtherT> &Other) {
|
||||||
|
copyAssign(Other);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LLVM_HAS_RVALUE_REFERENCES
|
#if LLVM_HAS_RVALUE_REFERENCES
|
||||||
ErrorOr(ErrorOr &&Other) : IsValid(false) {
|
ErrorOr(ErrorOr &&Other) : IsValid(false) {
|
||||||
// Construct an invalid ErrorOr if other is invalid.
|
moveConstruct(std::move(Other));
|
||||||
if (!Other.IsValid)
|
}
|
||||||
return;
|
|
||||||
IsValid = true;
|
template <class OtherT>
|
||||||
if (!Other.HasError) {
|
ErrorOr(ErrorOr<OtherT> &&Other) : IsValid(false) {
|
||||||
// Get the other value.
|
moveConstruct(std::move(Other));
|
||||||
HasError = false;
|
|
||||||
new (get()) storage_type(std::move(*Other.get()));
|
|
||||||
// Tell other not to do any destruction.
|
|
||||||
Other.IsValid = false;
|
|
||||||
} else {
|
|
||||||
// Get other's error.
|
|
||||||
Error = Other.Error;
|
|
||||||
HasError = true;
|
|
||||||
// Tell other not to do any destruction.
|
|
||||||
Other.IsValid = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr &operator =(ErrorOr &&Other) {
|
ErrorOr &operator =(ErrorOr &&Other) {
|
||||||
if (this == &Other)
|
moveAssign(std::move(Other));
|
||||||
return *this;
|
return *this;
|
||||||
|
}
|
||||||
this->~ErrorOr();
|
|
||||||
new (this) ErrorOr(std::move(Other));
|
|
||||||
|
|
||||||
|
template <class OtherT>
|
||||||
|
ErrorOr &operator =(ErrorOr<OtherT> &&Other) {
|
||||||
|
moveAssign(std::move(Other));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -300,6 +284,75 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
template <class OtherT>
|
||||||
|
void copyConstruct(const ErrorOr<OtherT> &Other) {
|
||||||
|
// Construct an invalid ErrorOr if other is invalid.
|
||||||
|
if (!Other.IsValid)
|
||||||
|
return;
|
||||||
|
IsValid = true;
|
||||||
|
if (!Other.HasError) {
|
||||||
|
// Get the other value.
|
||||||
|
HasError = false;
|
||||||
|
new (get()) storage_type(*Other.get());
|
||||||
|
} else {
|
||||||
|
// Get other's error.
|
||||||
|
Error = Other.Error;
|
||||||
|
HasError = true;
|
||||||
|
Error->aquire();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T1>
|
||||||
|
static bool compareThisIfSameType(const T1 &a, const T1 &b) {
|
||||||
|
return &a == &b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T1, class T2>
|
||||||
|
static bool compareThisIfSameType(const T1 &a, const T2 &b) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class OtherT>
|
||||||
|
void copyAssign(const ErrorOr<OtherT> &Other) {
|
||||||
|
if (compareThisIfSameType(*this, Other))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this->~ErrorOr();
|
||||||
|
new (this) ErrorOr(Other);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LLVM_HAS_RVALUE_REFERENCES
|
||||||
|
template <class OtherT>
|
||||||
|
void moveConstruct(ErrorOr<OtherT> &&Other) {
|
||||||
|
// Construct an invalid ErrorOr if other is invalid.
|
||||||
|
if (!Other.IsValid)
|
||||||
|
return;
|
||||||
|
IsValid = true;
|
||||||
|
if (!Other.HasError) {
|
||||||
|
// Get the other value.
|
||||||
|
HasError = false;
|
||||||
|
new (get()) storage_type(std::move(*Other.get()));
|
||||||
|
// Tell other not to do any destruction.
|
||||||
|
Other.IsValid = false;
|
||||||
|
} else {
|
||||||
|
// Get other's error.
|
||||||
|
Error = Other.Error;
|
||||||
|
HasError = true;
|
||||||
|
// Tell other not to do any destruction.
|
||||||
|
Other.IsValid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class OtherT>
|
||||||
|
void moveAssign(ErrorOr<OtherT> &&Other) {
|
||||||
|
if (compareThisIfSameType(*this, Other))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this->~ErrorOr();
|
||||||
|
new (this) ErrorOr(std::move(Other));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
pointer toPointer(pointer Val) {
|
pointer toPointer(pointer Val) {
|
||||||
return Val;
|
return Val;
|
||||||
}
|
}
|
||||||
@ -308,7 +361,6 @@ private:
|
|||||||
return &Val->get();
|
return &Val->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
storage_type *get() {
|
storage_type *get() {
|
||||||
assert(IsValid && "Can't do anything on a default constructed ErrorOr!");
|
assert(IsValid && "Can't do anything on a default constructed ErrorOr!");
|
||||||
assert(!HasError && "Cannot get value when an error exists!");
|
assert(!HasError && "Cannot get value when an error exists!");
|
||||||
|
@ -53,6 +53,19 @@ TEST(ErrorOr, Types) {
|
|||||||
EXPECT_EQ(3, **t3());
|
EXPECT_EQ(3, **t3());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct B {};
|
||||||
|
struct D : B {};
|
||||||
|
|
||||||
|
TEST(ErrorOr, Covariant) {
|
||||||
|
ErrorOr<B*> b(ErrorOr<D*>(0));
|
||||||
|
b = ErrorOr<D*>(0);
|
||||||
|
|
||||||
|
#if LLVM_HAS_CXX11_STDLIB
|
||||||
|
ErrorOr<std::unique_ptr<B> > b1(ErrorOr<std::unique_ptr<D> >(0));
|
||||||
|
b1 = ErrorOr<std::unique_ptr<D> >(0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
} // end anon namespace
|
} // end anon namespace
|
||||||
|
|
||||||
struct InvalidArgError {
|
struct InvalidArgError {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user