aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerge Guelton <sguelton@redhat.com>2019-02-13 11:35:45 +0000
committerSerge Guelton <sguelton@redhat.com>2019-02-13 11:35:45 +0000
commite194414673592749c06af78585d27aafc27b3a87 (patch)
treea54768a6bdf0439f91f4e631276e5080b3b786ae
parent8810171ee8995b00d4fbb8a8cd754fbc76d1f528 (diff)
downloadllvm-e194414673592749c06af78585d27aafc27b3a87.tar.gz
Revert r353927
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@353940 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/ADT/Optional.h95
-rw-r--r--unittests/ADT/OptionalTest.cpp20
2 files changed, 31 insertions, 84 deletions
diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h
index 35ce0ce7010..25a3185064f 100644
--- a/include/llvm/ADT/Optional.h
+++ b/include/llvm/ADT/Optional.h
@@ -29,77 +29,36 @@ namespace llvm {
class raw_ostream;
namespace optional_detail {
-
/// Storage for any type.
-//
-template <class T> struct OptionalTrivialStorage {
+template <typename T, bool = is_trivially_copyable<T>::value> struct OptionalStorage {
AlignedCharArrayUnion<T> storage;
bool hasVal = false;
- OptionalTrivialStorage() = default;
- OptionalTrivialStorage(OptionalTrivialStorage const &) = default;
- OptionalTrivialStorage(OptionalTrivialStorage &&) = default;
- OptionalTrivialStorage &operator=(OptionalTrivialStorage const &) = default;
- OptionalTrivialStorage &operator=(OptionalTrivialStorage &&) = default;
- ~OptionalTrivialStorage() = default;
-
- OptionalTrivialStorage(const T &y) : hasVal(true) {
- new (storage.buffer) T(y);
- }
- OptionalTrivialStorage(T &&y) : hasVal(true) {
- new (storage.buffer) T(std::move(y));
- }
-
- OptionalTrivialStorage &operator=(const T &y) {
- new (storage.buffer) T(y);
- hasVal = true;
- return *this;
- }
- OptionalTrivialStorage &operator=(T &&y) {
- new (storage.buffer) T(std::move(y));
- hasVal = true;
- return *this;
- }
-
- T *getPointer() {
- assert(hasVal);
- return reinterpret_cast<T *>(storage.buffer);
- }
- const T *getPointer() const {
- assert(hasVal);
- return reinterpret_cast<const T *>(storage.buffer);
- }
- void reset() { hasVal = false; }
-};
-
-template <typename T> struct OptionalStorage : OptionalTrivialStorage<T> {
OptionalStorage() = default;
- OptionalStorage(const T &y) : OptionalTrivialStorage<T>(y) {}
- OptionalStorage(T &&y) : OptionalTrivialStorage<T>(std::move(y)) {}
-
- OptionalStorage(const OptionalStorage &O) : OptionalTrivialStorage<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(OptionalStorage &&O) : OptionalTrivialStorage<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 {
- OptionalTrivialStorage<T>::operator=(std::move(y));
+ new (storage.buffer) T(std::move(y));
+ hasVal = true;
}
return *this;
}
-
OptionalStorage &operator=(OptionalStorage &&O) {
if (!O.hasVal)
reset();
@@ -115,10 +74,11 @@ template <typename T> struct OptionalStorage : OptionalTrivialStorage<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 {
- OptionalTrivialStorage<T>::operator=(y);
+ new (storage.buffer) T(y);
+ hasVal = true;
}
return *this;
}
@@ -133,19 +93,26 @@ template <typename T> struct OptionalStorage : OptionalTrivialStorage<T> {
~OptionalStorage() { reset(); }
void reset() {
- if (this->hasVal) {
- (*this->getPointer()).~T();
- OptionalTrivialStorage<T>::reset();
+ if (hasVal) {
+ (*getPointer()).~T();
+ hasVal = false;
}
}
+
+ T *getPointer() {
+ assert(hasVal);
+ return reinterpret_cast<T *>(storage.buffer);
+ }
+ const T *getPointer() const {
+ assert(hasVal);
+ return reinterpret_cast<const T *>(storage.buffer);
+ }
};
} // namespace optional_detail
template <typename T> class Optional {
- typename std::conditional<is_trivially_copyable<T>::value,
- optional_detail::OptionalTrivialStorage<T>,
- optional_detail::OptionalStorage<T>>::type Storage;
+ optional_detail::OptionalStorage<T> Storage;
public:
using value_type = T;
diff --git a/unittests/ADT/OptionalTest.cpp b/unittests/ADT/OptionalTest.cpp
index c39b6727cd5..98adaccca96 100644
--- a/unittests/ADT/OptionalTest.cpp
+++ b/unittests/ADT/OptionalTest.cpp
@@ -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();