mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-25 16:31:33 +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.
|
||||
template<class T>
|
||||
class ErrorOr {
|
||||
template <class OtherT> friend class ErrorOr;
|
||||
static const bool isRef = is_reference<T>::value;
|
||||
typedef ReferenceStorage<typename remove_reference<T>::type> wrap;
|
||||
|
||||
@ -199,60 +200,43 @@ public:
|
||||
}
|
||||
|
||||
ErrorOr(const ErrorOr &Other) : IsValid(false) {
|
||||
// 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();
|
||||
}
|
||||
copyConstruct(Other);
|
||||
}
|
||||
|
||||
template <class OtherT>
|
||||
ErrorOr(const ErrorOr<OtherT> &Other) : IsValid(false) {
|
||||
copyConstruct(Other);
|
||||
}
|
||||
|
||||
ErrorOr &operator =(const ErrorOr &Other) {
|
||||
if (this == &Other)
|
||||
return *this;
|
||||
|
||||
this->~ErrorOr();
|
||||
new (this) ErrorOr(Other);
|
||||
copyAssign(Other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class OtherT>
|
||||
ErrorOr &operator =(const ErrorOr<OtherT> &Other) {
|
||||
copyAssign(Other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
ErrorOr(ErrorOr &&Other) : IsValid(false) {
|
||||
// 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;
|
||||
}
|
||||
moveConstruct(std::move(Other));
|
||||
}
|
||||
|
||||
template <class OtherT>
|
||||
ErrorOr(ErrorOr<OtherT> &&Other) : IsValid(false) {
|
||||
moveConstruct(std::move(Other));
|
||||
}
|
||||
|
||||
ErrorOr &operator =(ErrorOr &&Other) {
|
||||
if (this == &Other)
|
||||
return *this;
|
||||
|
||||
this->~ErrorOr();
|
||||
new (this) ErrorOr(std::move(Other));
|
||||
moveAssign(std::move(Other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class OtherT>
|
||||
ErrorOr &operator =(ErrorOr<OtherT> &&Other) {
|
||||
moveAssign(std::move(Other));
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
@ -300,6 +284,75 @@ public:
|
||||
}
|
||||
|
||||
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) {
|
||||
return Val;
|
||||
}
|
||||
@ -308,7 +361,6 @@ private:
|
||||
return &Val->get();
|
||||
}
|
||||
|
||||
protected:
|
||||
storage_type *get() {
|
||||
assert(IsValid && "Can't do anything on a default constructed ErrorOr!");
|
||||
assert(!HasError && "Cannot get value when an error exists!");
|
||||
|
@ -53,6 +53,19 @@ TEST(ErrorOr, Types) {
|
||||
EXPECT_EQ(3, **t3());
|
||||
#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
|
||||
|
||||
struct InvalidArgError {
|
||||
|
Loading…
x
Reference in New Issue
Block a user