1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

Revert r353962

Specialization of Optional for trivially copyable types yields failure on the buildbots I fail to reproduce locally.
Better safe than sorry, reverting.

llvm-svn: 353982
This commit is contained in:
Serge Guelton 2019-02-13 22:11:09 +00:00
parent 91b33a7106
commit a27afd3444
2 changed files with 28 additions and 85 deletions

View File

@ -29,61 +29,33 @@ namespace llvm {
class raw_ostream;
namespace optional_detail {
template <typename T> struct OptionalStorageBase {
/// Storage for any type.
template <typename T, bool = is_trivially_copyable<T>::value> struct OptionalStorage {
AlignedCharArrayUnion<T> storage;
bool hasVal = false;
OptionalStorageBase() = default;
OptionalStorageBase(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
OptionalStorageBase(T &&y) : hasVal(true) {
new (storage.buffer) T(std::move(y));
}
T *getPointer() {
assert(hasVal);
return reinterpret_cast<T *>(storage.buffer);
}
const T *getPointer() const {
assert(hasVal);
return reinterpret_cast<const T *>(storage.buffer);
}
OptionalStorageBase &operator=(T &&y) {
hasVal = true;
new (this->storage.buffer) T(std::move(y));
return *this;
}
OptionalStorageBase &operator=(const T &y) {
hasVal = true;
new (this->storage.buffer) T(y);
return *this;
}
void reset() { this->hasVal = false; }
};
/// Storage for any type.
template <typename T, bool = is_trivially_copyable<T>::value>
struct OptionalStorage : OptionalStorageBase<T> {
OptionalStorage() = default;
OptionalStorage(const T &y) : OptionalStorageBase<T>(y) {}
OptionalStorage(const OptionalStorage &O) : OptionalStorageBase<T>() {
this->hasVal = O.hasVal;
if (this->hasVal)
new (this->storage.buffer) T(*O.getPointer());
OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
OptionalStorage(const OptionalStorage &O) : hasVal(O.hasVal) {
if (hasVal)
new (storage.buffer) T(*O.getPointer());
}
OptionalStorage(T &&y) : OptionalStorageBase<T>(std::move(y)) {}
OptionalStorage(OptionalStorage &&O) : OptionalStorageBase<T>() {
this->hasVal = O.hasVal;
OptionalStorage(T &&y) : hasVal(true) {
new (storage.buffer) T(std::forward<T>(y));
}
OptionalStorage(OptionalStorage &&O) : hasVal(O.hasVal) {
if (O.hasVal) {
new (this->storage.buffer) T(std::move(*O.getPointer()));
new (storage.buffer) T(std::move(*O.getPointer()));
}
}
OptionalStorage &operator=(T &&y) {
if (this->hasVal)
*this->getPointer() = std::move(y);
if (hasVal)
*getPointer() = std::move(y);
else {
OptionalStorageBase<T>::operator=(std::move(y));
new (storage.buffer) T(std::move(y));
hasVal = true;
}
return *this;
}
@ -102,10 +74,11 @@ struct OptionalStorage : OptionalStorageBase<T> {
// requirements (notably: the existence of a default ctor) when implemented
// in that way. Careful SFINAE to avoid such pitfalls would be required.
OptionalStorage &operator=(const T &y) {
if (this->hasVal)
*this->getPointer() = y;
if (hasVal)
*getPointer() = y;
else {
OptionalStorageBase<T>::operator=(y);
new (storage.buffer) T(y);
hasVal = true;
}
return *this;
}
@ -120,30 +93,20 @@ struct OptionalStorage : OptionalStorageBase<T> {
~OptionalStorage() { reset(); }
void reset() {
if (this->hasVal) {
(*this->getPointer()).~T();
if (hasVal) {
(*getPointer()).~T();
hasVal = false;
}
OptionalStorageBase<T>::reset();
}
};
template <typename T> struct OptionalStorage<T, true> : OptionalStorageBase<T> {
OptionalStorage() = default;
OptionalStorage(const T &y) : OptionalStorageBase<T>(y) {}
OptionalStorage(const OptionalStorage &O) = default;
OptionalStorage(T &&y) : OptionalStorageBase<T>(std::move(y)) {}
OptionalStorage(OptionalStorage &&O) = default;
OptionalStorage &operator=(T &&y) {
OptionalStorageBase<T>::operator=(std::move(y));
return *this;
T *getPointer() {
assert(hasVal);
return reinterpret_cast<T *>(storage.buffer);
}
OptionalStorage &operator=(OptionalStorage &&O) = default;
OptionalStorage &operator=(const T &y) {
OptionalStorageBase<T>::operator=(y);
return *this;
const T *getPointer() const {
assert(hasVal);
return reinterpret_cast<const T *>(storage.buffer);
}
OptionalStorage &operator=(const OptionalStorage &O) = default;
~OptionalStorage() = default;
};
} // namespace optional_detail

View File

@ -18,12 +18,6 @@ using namespace llvm;
namespace {
static_assert(llvm::is_trivially_copyable<Optional<int>>::value,
"trivially copyable");
static_assert(llvm::is_trivially_copyable<Optional<std::array<int, 3>>>::value,
"trivially copyable");
struct NonDefaultConstructible {
static unsigned CopyConstructions;
static unsigned Destructions;
@ -51,10 +45,6 @@ unsigned NonDefaultConstructible::CopyConstructions = 0;
unsigned NonDefaultConstructible::Destructions = 0;
unsigned NonDefaultConstructible::CopyAssignments = 0;
static_assert(
!llvm::is_trivially_copyable<Optional<NonDefaultConstructible>>::value,
"not trivially copyable");
// Test fixture
class OptionalTest : public testing::Test {
};
@ -213,10 +203,6 @@ struct MultiArgConstructor {
};
unsigned MultiArgConstructor::Destructions = 0;
static_assert(
!llvm::is_trivially_copyable<Optional<MultiArgConstructor>>::value,
"not trivially copyable");
TEST_F(OptionalTest, Emplace) {
MultiArgConstructor::ResetCounts();
Optional<MultiArgConstructor> A;
@ -264,9 +250,6 @@ unsigned MoveOnly::MoveConstructions = 0;
unsigned MoveOnly::Destructions = 0;
unsigned MoveOnly::MoveAssignments = 0;
static_assert(!llvm::is_trivially_copyable<Optional<MoveOnly>>::value,
"not trivially copyable");
TEST_F(OptionalTest, MoveOnlyNull) {
MoveOnly::ResetCounts();
Optional<MoveOnly> O;
@ -368,9 +351,6 @@ private:
unsigned Immovable::Constructions = 0;
unsigned Immovable::Destructions = 0;
static_assert(!llvm::is_trivially_copyable<Optional<Immovable>>::value,
"not trivially copyable");
TEST_F(OptionalTest, ImmovableEmplace) {
Optional<Immovable> A;
Immovable::ResetCounts();