Skip to content

Commit 7c1ef4a

Browse files
committed
Revert rL317019, "[ADT] Split optional to only include copy mechanics and dtor for non-trivial types."
Seems g++-4.8 (eg. Ubuntu 14.04) doesn't like this. llvm-svn: 317077
1 parent a31174e commit 7c1ef4a

File tree

2 files changed

+58
-117
lines changed

2 files changed

+58
-117
lines changed

llvm/include/llvm/ADT/Optional.h

Lines changed: 58 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -27,173 +27,123 @@
2727

2828
namespace llvm {
2929

30-
namespace optional_detail {
31-
/// Storage for any type.
32-
template <typename T, bool IsPodLike> struct OptionalStorage {
30+
template<typename T>
31+
class Optional {
3332
AlignedCharArrayUnion<T> storage;
3433
bool hasVal = false;
3534

36-
OptionalStorage() = default;
35+
public:
36+
using value_type = T;
3737

38-
OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
39-
OptionalStorage(const OptionalStorage &O) : hasVal(O.hasVal) {
38+
Optional(NoneType) {}
39+
explicit Optional() {}
40+
41+
Optional(const T &y) : hasVal(true) {
42+
new (storage.buffer) T(y);
43+
}
44+
45+
Optional(const Optional &O) : hasVal(O.hasVal) {
4046
if (hasVal)
41-
new (storage.buffer) T(*O.getPointer());
47+
new (storage.buffer) T(*O);
4248
}
43-
OptionalStorage(T &&y) : hasVal(true) {
49+
50+
Optional(T &&y) : hasVal(true) {
4451
new (storage.buffer) T(std::forward<T>(y));
4552
}
46-
OptionalStorage(OptionalStorage &&O) : hasVal(O.hasVal) {
47-
if (O.hasVal) {
48-
new (storage.buffer) T(std::move(*O.getPointer()));
53+
54+
Optional(Optional<T> &&O) : hasVal(O) {
55+
if (O) {
56+
new (storage.buffer) T(std::move(*O));
4957
O.reset();
5058
}
5159
}
5260

53-
OptionalStorage &operator=(T &&y) {
61+
~Optional() {
62+
reset();
63+
}
64+
65+
Optional &operator=(T &&y) {
5466
if (hasVal)
55-
*getPointer() = std::move(y);
67+
**this = std::move(y);
5668
else {
5769
new (storage.buffer) T(std::move(y));
5870
hasVal = true;
5971
}
6072
return *this;
6173
}
62-
OptionalStorage &operator=(OptionalStorage &&O) {
63-
if (!O.hasVal)
74+
75+
Optional &operator=(Optional &&O) {
76+
if (!O)
6477
reset();
6578
else {
66-
*this = std::move(*O.getPointer());
79+
*this = std::move(*O);
6780
O.reset();
6881
}
6982
return *this;
7083
}
7184

85+
/// Create a new object by constructing it in place with the given arguments.
86+
template<typename ...ArgTypes>
87+
void emplace(ArgTypes &&...Args) {
88+
reset();
89+
hasVal = true;
90+
new (storage.buffer) T(std::forward<ArgTypes>(Args)...);
91+
}
92+
93+
static inline Optional create(const T* y) {
94+
return y ? Optional(*y) : Optional();
95+
}
96+
7297
// FIXME: these assignments (& the equivalent const T&/const Optional& ctors)
7398
// could be made more efficient by passing by value, possibly unifying them
7499
// with the rvalue versions above - but this could place a different set of
75100
// requirements (notably: the existence of a default ctor) when implemented
76101
// in that way. Careful SFINAE to avoid such pitfalls would be required.
77-
OptionalStorage &operator=(const T &y) {
102+
Optional &operator=(const T &y) {
78103
if (hasVal)
79-
*getPointer() = y;
104+
**this = y;
80105
else {
81106
new (storage.buffer) T(y);
82107
hasVal = true;
83108
}
84109
return *this;
85110
}
86-
OptionalStorage &operator=(const OptionalStorage &O) {
87-
if (!O.hasVal)
111+
112+
Optional &operator=(const Optional &O) {
113+
if (!O)
88114
reset();
89115
else
90-
*this = *O.getPointer();
116+
*this = *O;
91117
return *this;
92118
}
93119

94-
~OptionalStorage() { reset(); }
95-
96120
void reset() {
97121
if (hasVal) {
98-
(*getPointer()).~T();
122+
(**this).~T();
99123
hasVal = false;
100124
}
101125
}
102126

103-
T *getPointer() {
104-
assert(hasVal);
105-
return reinterpret_cast<T *>(storage.buffer);
106-
}
107-
const T *getPointer() const {
108-
assert(hasVal);
109-
return reinterpret_cast<const T *>(storage.buffer);
110-
}
111-
};
112-
113-
/// Storage for trivially copyable types only.
114-
template <typename T> struct OptionalStorage<T, true> {
115-
AlignedCharArrayUnion<T> storage;
116-
bool hasVal = false;
117-
118-
OptionalStorage() = default;
119-
120-
OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
121-
OptionalStorage &operator=(const T &y) {
122-
new (storage.buffer) T(y);
123-
hasVal = true;
124-
return *this;
125-
}
126-
127-
void reset() { hasVal = false; }
128-
};
129-
} // namespace optional_detail
130-
131-
template <typename T> class Optional {
132-
optional_detail::OptionalStorage<T, isPodLike<T>::value> Storage;
133-
134-
public:
135-
using value_type = T;
136-
137-
constexpr Optional() {}
138-
constexpr Optional(NoneType) {}
139-
140-
Optional(const T &y) : Storage(y) {}
141-
Optional(const Optional &O) = default;
142-
143-
Optional(T &&y) : Storage(std::forward<T>(y)) {}
144-
Optional(Optional &&O) = default;
145-
146-
Optional &operator=(T &&y) {
147-
Storage = std::move(y);
148-
return *this;
149-
}
150-
Optional &operator=(Optional &&O) = default;
151-
152-
/// Create a new object by constructing it in place with the given arguments.
153-
template <typename... ArgTypes> void emplace(ArgTypes &&... Args) {
154-
reset();
155-
Storage.hasVal = true;
156-
new (getPointer()) T(std::forward<ArgTypes>(Args)...);
157-
}
158-
159-
static inline Optional create(const T *y) {
160-
return y ? Optional(*y) : Optional();
161-
}
162-
163-
Optional &operator=(const T &y) {
164-
Storage = y;
165-
return *this;
166-
}
167-
Optional &operator=(const Optional &O) = default;
168-
169-
void reset() { Storage.reset(); }
170-
171-
const T *getPointer() const {
172-
assert(Storage.hasVal);
173-
return reinterpret_cast<const T *>(Storage.storage.buffer);
174-
}
175-
T *getPointer() {
176-
assert(Storage.hasVal);
177-
return reinterpret_cast<T *>(Storage.storage.buffer);
178-
}
179-
const T &getValue() const LLVM_LVALUE_FUNCTION { return *getPointer(); }
180-
T &getValue() LLVM_LVALUE_FUNCTION { return *getPointer(); }
127+
const T* getPointer() const { assert(hasVal); return reinterpret_cast<const T*>(storage.buffer); }
128+
T* getPointer() { assert(hasVal); return reinterpret_cast<T*>(storage.buffer); }
129+
const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
130+
T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
181131

182-
explicit operator bool() const { return Storage.hasVal; }
183-
bool hasValue() const { return Storage.hasVal; }
132+
explicit operator bool() const { return hasVal; }
133+
bool hasValue() const { return hasVal; }
184134
const T* operator->() const { return getPointer(); }
185135
T* operator->() { return getPointer(); }
186-
const T &operator*() const LLVM_LVALUE_FUNCTION { return *getPointer(); }
187-
T &operator*() LLVM_LVALUE_FUNCTION { return *getPointer(); }
136+
const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
137+
T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
188138

189139
template <typename U>
190140
constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION {
191141
return hasValue() ? getValue() : std::forward<U>(value);
192142
}
193143

194144
#if LLVM_HAS_RVALUE_REFERENCE_THIS
195-
T &&getValue() && { return std::move(*getPointer()); }
196-
T &&operator*() && { return std::move(*getPointer()); }
145+
T&& getValue() && { assert(hasVal); return std::move(*getPointer()); }
146+
T&& operator*() && { assert(hasVal); return std::move(*getPointer()); }
197147

198148
template <typename U>
199149
T getValueOr(U &&value) && {

llvm/unittests/ADT/OptionalTest.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -518,14 +518,5 @@ TEST_F(OptionalTest, OperatorGreaterEqual) {
518518
CheckRelation<GreaterEqual>(InequalityLhs, InequalityRhs, !IsLess);
519519
}
520520

521-
#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \
522-
(defined(__GNUC__) && __GNUC__ >= 5)
523-
static_assert(std::is_trivially_copyable<Optional<int>>::value,
524-
"Should be trivially copyable");
525-
static_assert(
526-
!std::is_trivially_copyable<Optional<NonDefaultConstructible>>::value,
527-
"Shouldn't be trivially copyable");
528-
#endif
529-
530521
} // end anonymous namespace
531522

0 commit comments

Comments
 (0)