Skip to content

Commit 221c391

Browse files
author
Serge Guelton
committed
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
1 parent 8331f61 commit 221c391

File tree

2 files changed

+28
-85
lines changed

2 files changed

+28
-85
lines changed

llvm/include/llvm/ADT/Optional.h

Lines changed: 28 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -29,61 +29,33 @@ namespace llvm {
2929
class raw_ostream;
3030

3131
namespace optional_detail {
32-
template <typename T> struct OptionalStorageBase {
32+
/// Storage for any type.
33+
template <typename T, bool = is_trivially_copyable<T>::value> struct OptionalStorage {
3334
AlignedCharArrayUnion<T> storage;
3435
bool hasVal = false;
3536

36-
OptionalStorageBase() = default;
37-
OptionalStorageBase(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
38-
OptionalStorageBase(T &&y) : hasVal(true) {
39-
new (storage.buffer) T(std::move(y));
40-
}
41-
42-
T *getPointer() {
43-
assert(hasVal);
44-
return reinterpret_cast<T *>(storage.buffer);
45-
}
46-
const T *getPointer() const {
47-
assert(hasVal);
48-
return reinterpret_cast<const T *>(storage.buffer);
49-
}
50-
OptionalStorageBase &operator=(T &&y) {
51-
hasVal = true;
52-
new (this->storage.buffer) T(std::move(y));
53-
return *this;
54-
}
55-
OptionalStorageBase &operator=(const T &y) {
56-
hasVal = true;
57-
new (this->storage.buffer) T(y);
58-
return *this;
59-
}
60-
void reset() { this->hasVal = false; }
61-
};
62-
63-
/// Storage for any type.
64-
template <typename T, bool = is_trivially_copyable<T>::value>
65-
struct OptionalStorage : OptionalStorageBase<T> {
6637
OptionalStorage() = default;
6738

68-
OptionalStorage(const T &y) : OptionalStorageBase<T>(y) {}
69-
OptionalStorage(const OptionalStorage &O) : OptionalStorageBase<T>() {
70-
this->hasVal = O.hasVal;
71-
if (this->hasVal)
72-
new (this->storage.buffer) T(*O.getPointer());
39+
OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
40+
OptionalStorage(const OptionalStorage &O) : hasVal(O.hasVal) {
41+
if (hasVal)
42+
new (storage.buffer) T(*O.getPointer());
7343
}
74-
OptionalStorage(T &&y) : OptionalStorageBase<T>(std::move(y)) {}
75-
OptionalStorage(OptionalStorage &&O) : OptionalStorageBase<T>() {
76-
this->hasVal = O.hasVal;
44+
OptionalStorage(T &&y) : hasVal(true) {
45+
new (storage.buffer) T(std::forward<T>(y));
46+
}
47+
OptionalStorage(OptionalStorage &&O) : hasVal(O.hasVal) {
7748
if (O.hasVal) {
78-
new (this->storage.buffer) T(std::move(*O.getPointer()));
49+
new (storage.buffer) T(std::move(*O.getPointer()));
7950
}
8051
}
8152

8253
OptionalStorage &operator=(T &&y) {
83-
if (this->hasVal)
84-
*this->getPointer() = std::move(y);
54+
if (hasVal)
55+
*getPointer() = std::move(y);
8556
else {
86-
OptionalStorageBase<T>::operator=(std::move(y));
57+
new (storage.buffer) T(std::move(y));
58+
hasVal = true;
8759
}
8860
return *this;
8961
}
@@ -102,10 +74,11 @@ struct OptionalStorage : OptionalStorageBase<T> {
10274
// requirements (notably: the existence of a default ctor) when implemented
10375
// in that way. Careful SFINAE to avoid such pitfalls would be required.
10476
OptionalStorage &operator=(const T &y) {
105-
if (this->hasVal)
106-
*this->getPointer() = y;
77+
if (hasVal)
78+
*getPointer() = y;
10779
else {
108-
OptionalStorageBase<T>::operator=(y);
80+
new (storage.buffer) T(y);
81+
hasVal = true;
10982
}
11083
return *this;
11184
}
@@ -120,30 +93,20 @@ struct OptionalStorage : OptionalStorageBase<T> {
12093
~OptionalStorage() { reset(); }
12194

12295
void reset() {
123-
if (this->hasVal) {
124-
(*this->getPointer()).~T();
96+
if (hasVal) {
97+
(*getPointer()).~T();
98+
hasVal = false;
12599
}
126-
OptionalStorageBase<T>::reset();
127100
}
128-
};
129101

130-
template <typename T> struct OptionalStorage<T, true> : OptionalStorageBase<T> {
131-
OptionalStorage() = default;
132-
OptionalStorage(const T &y) : OptionalStorageBase<T>(y) {}
133-
OptionalStorage(const OptionalStorage &O) = default;
134-
OptionalStorage(T &&y) : OptionalStorageBase<T>(std::move(y)) {}
135-
OptionalStorage(OptionalStorage &&O) = default;
136-
OptionalStorage &operator=(T &&y) {
137-
OptionalStorageBase<T>::operator=(std::move(y));
138-
return *this;
102+
T *getPointer() {
103+
assert(hasVal);
104+
return reinterpret_cast<T *>(storage.buffer);
139105
}
140-
OptionalStorage &operator=(OptionalStorage &&O) = default;
141-
OptionalStorage &operator=(const T &y) {
142-
OptionalStorageBase<T>::operator=(y);
143-
return *this;
106+
const T *getPointer() const {
107+
assert(hasVal);
108+
return reinterpret_cast<const T *>(storage.buffer);
144109
}
145-
OptionalStorage &operator=(const OptionalStorage &O) = default;
146-
~OptionalStorage() = default;
147110
};
148111

149112
} // namespace optional_detail

llvm/unittests/ADT/OptionalTest.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,6 @@ using namespace llvm;
1818

1919
namespace {
2020

21-
static_assert(llvm::is_trivially_copyable<Optional<int>>::value,
22-
"trivially copyable");
23-
24-
static_assert(llvm::is_trivially_copyable<Optional<std::array<int, 3>>>::value,
25-
"trivially copyable");
26-
2721
struct NonDefaultConstructible {
2822
static unsigned CopyConstructions;
2923
static unsigned Destructions;
@@ -51,10 +45,6 @@ unsigned NonDefaultConstructible::CopyConstructions = 0;
5145
unsigned NonDefaultConstructible::Destructions = 0;
5246
unsigned NonDefaultConstructible::CopyAssignments = 0;
5347

54-
static_assert(
55-
!llvm::is_trivially_copyable<Optional<NonDefaultConstructible>>::value,
56-
"not trivially copyable");
57-
5848
// Test fixture
5949
class OptionalTest : public testing::Test {
6050
};
@@ -213,10 +203,6 @@ struct MultiArgConstructor {
213203
};
214204
unsigned MultiArgConstructor::Destructions = 0;
215205

216-
static_assert(
217-
!llvm::is_trivially_copyable<Optional<MultiArgConstructor>>::value,
218-
"not trivially copyable");
219-
220206
TEST_F(OptionalTest, Emplace) {
221207
MultiArgConstructor::ResetCounts();
222208
Optional<MultiArgConstructor> A;
@@ -264,9 +250,6 @@ unsigned MoveOnly::MoveConstructions = 0;
264250
unsigned MoveOnly::Destructions = 0;
265251
unsigned MoveOnly::MoveAssignments = 0;
266252

267-
static_assert(!llvm::is_trivially_copyable<Optional<MoveOnly>>::value,
268-
"not trivially copyable");
269-
270253
TEST_F(OptionalTest, MoveOnlyNull) {
271254
MoveOnly::ResetCounts();
272255
Optional<MoveOnly> O;
@@ -368,9 +351,6 @@ struct Immovable {
368351
unsigned Immovable::Constructions = 0;
369352
unsigned Immovable::Destructions = 0;
370353

371-
static_assert(!llvm::is_trivially_copyable<Optional<Immovable>>::value,
372-
"not trivially copyable");
373-
374354
TEST_F(OptionalTest, ImmovableEmplace) {
375355
Optional<Immovable> A;
376356
Immovable::ResetCounts();

0 commit comments

Comments
 (0)