From: Eric Fiselier Date: Wed, 7 Sep 2016 01:56:07 +0000 (+0000) Subject: Fix PR30260 - optional not working. X-Git-Tag: llvmorg-4.0.0-rc1~10496 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c1d527d3d832cac86eb9461dcef978011ef8caeb;p=platform%2Fupstream%2Fllvm.git Fix PR30260 - optional not working. This patch fixes PR30260 by using a (void*) cast on the placement argument to placement new to casts away the const. See also http://llvm.org/PR30260. As a drive by change this patch also changes the header guard for to _LIBCPP_EXPERIMENTAL_OPTIONAL from _LIBCPP_OPTIONAL. llvm-svn: 280775 --- diff --git a/libcxx/include/experimental/optional b/libcxx/include/experimental/optional index 11bf867..966c889 100644 --- a/libcxx/include/experimental/optional +++ b/libcxx/include/experimental/optional @@ -8,8 +8,8 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP_OPTIONAL -#define _LIBCPP_OPTIONAL +#ifndef _LIBCPP_EXPERIMENTAL_OPTIONAL +#define _LIBCPP_EXPERIMENTAL_OPTIONAL /* optional synopsis @@ -211,7 +211,7 @@ protected: : __engaged_(__x.__engaged_) { if (__engaged_) - ::new(_VSTD::addressof(__val_)) value_type(__x.__val_); + ::new((void*)_VSTD::addressof(__val_)) value_type(__x.__val_); } _LIBCPP_INLINE_VISIBILITY @@ -220,7 +220,7 @@ protected: : __engaged_(__x.__engaged_) { if (__engaged_) - ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_)); + ::new((void*)_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_)); } _LIBCPP_INLINE_VISIBILITY @@ -262,7 +262,7 @@ protected: : __engaged_(__x.__engaged_) { if (__engaged_) - ::new(_VSTD::addressof(__val_)) value_type(__x.__val_); + ::new((void*)_VSTD::addressof(__val_)) value_type(__x.__val_); } _LIBCPP_INLINE_VISIBILITY @@ -271,7 +271,7 @@ protected: : __engaged_(__x.__engaged_) { if (__engaged_) - ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_)); + ::new((void*)_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_)); } _LIBCPP_INLINE_VISIBILITY @@ -368,7 +368,7 @@ public: if (this->__engaged_) this->__val_.~value_type(); else - ::new(_VSTD::addressof(this->__val_)) value_type(__opt.__val_); + ::new((void*)_VSTD::addressof(this->__val_)) value_type(__opt.__val_); this->__engaged_ = __opt.__engaged_; } return *this; @@ -390,7 +390,8 @@ public: if (this->__engaged_) this->__val_.~value_type(); else - ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_)); + ::new((void*)_VSTD::addressof(this->__val_)) + value_type(_VSTD::move(__opt.__val_)); this->__engaged_ = __opt.__engaged_; } return *this; @@ -412,7 +413,7 @@ public: this->__val_ = _VSTD::forward<_Up>(__v); else { - ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v)); + ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v)); this->__engaged_ = true; } return *this; @@ -429,7 +430,8 @@ public: emplace(_Args&&... __args) { *this = nullopt; - ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); + ::new((void*)_VSTD::addressof(this->__val_)) + value_type(_VSTD::forward<_Args>(__args)...); this->__engaged_ = true; } @@ -444,7 +446,8 @@ public: emplace(initializer_list<_Up> __il, _Args&&... __args) { *this = nullopt; - ::new(_VSTD::addressof(this->__val_)) value_type(__il, _VSTD::forward<_Args>(__args)...); + ::new((void*)_VSTD::addressof(this->__val_)) + value_type(__il, _VSTD::forward<_Args>(__args)...); this->__engaged_ = true; } @@ -464,12 +467,14 @@ public: { if (this->__engaged_) { - ::new(_VSTD::addressof(__opt.__val_)) value_type(_VSTD::move(this->__val_)); + ::new((void*)_VSTD::addressof(__opt.__val_)) + value_type(_VSTD::move(this->__val_)); this->__val_.~value_type(); } else { - ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_)); + ::new((void*)_VSTD::addressof(this->__val_)) + value_type(_VSTD::move(__opt.__val_)); __opt.__val_.~value_type(); } swap(this->__engaged_, __opt.__engaged_); @@ -901,4 +906,4 @@ _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_STD_VER > 11 -#endif // _LIBCPP_OPTIONAL +#endif // _LIBCPP_EXPERIMENTAL_OPTIONAL diff --git a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp index 3d0d2e0..27aafe0 100644 --- a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp +++ b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp @@ -19,6 +19,14 @@ using std::experimental::optional; +struct AllowConstAssign { + AllowConstAssign() = default; + AllowConstAssign(AllowConstAssign const&) {} + AllowConstAssign const& operator=(AllowConstAssign const&) const { + return *this; + } +}; + struct X { }; @@ -53,6 +61,11 @@ int main() assert(*opt == i); } { + optional opt; + const AllowConstAssign other; + opt = other; + } + { optional> opt; opt = std::unique_ptr(new int(3)); assert(static_cast(opt) == true); diff --git a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp index 89ea345..ff37b22c 100644 --- a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp +++ b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp @@ -19,6 +19,13 @@ using std::experimental::optional; +struct AllowConstAssign { + AllowConstAssign(AllowConstAssign const&) {} + AllowConstAssign const& operator=(AllowConstAssign const&) const { + return *this; + } +}; + struct X { static bool throw_now; @@ -43,6 +50,11 @@ int main() assert(static_cast(opt) == static_cast(opt2)); } { + optional opt; + optional opt2; + opt = opt2; + } + { optional opt; constexpr optional opt2(2); opt = opt2; diff --git a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp index 94f2bb2..6a7b56e 100644 --- a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp +++ b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp @@ -81,6 +81,12 @@ int main() assert(*opt == 1); } { + optional opt(2); + opt.emplace(1); + assert(static_cast(opt) == true); + assert(*opt == 1); + } + { optional opt; opt.emplace(); assert(static_cast(opt) == true); diff --git a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp index fec3740..b02616e 100644 --- a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp +++ b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp @@ -81,6 +81,17 @@ int main() assert(*opt == X({1, 2})); } } + X::dtor_called = false; + { + X x; + { + optional opt(x); + assert(X::dtor_called == false); + opt.emplace({1, 2}); + assert(X::dtor_called == true); + assert(*opt == X({1, 2})); + } + } { optional> opt; opt.emplace({1, 2, 3}, std::allocator()); diff --git a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp index fa00f56..1c3b780 100644 --- a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp +++ b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp @@ -21,6 +21,13 @@ using std::experimental::optional; +struct AllowConstAssign { + AllowConstAssign(AllowConstAssign const&) {} + AllowConstAssign const& operator=(AllowConstAssign const&) const { + return *this; + } +}; + struct X { static bool throw_now; @@ -77,6 +84,11 @@ int main() assert(*opt == *opt2); } { + optional opt; + optional opt2; + opt = std::move(opt2); + } + { static_assert(!std::is_nothrow_move_assignable>::value, ""); optional opt; optional opt2(X{}); diff --git a/libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp b/libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp index 144af2e..c7c687c 100644 --- a/libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp +++ b/libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp @@ -88,6 +88,11 @@ int main() test(rhs); } { + typedef const int T; + optional rhs(3); + test(rhs); + } + { typedef X T; optional rhs; test(rhs); @@ -98,6 +103,11 @@ int main() test(rhs); } { + typedef const X T; + optional rhs(X(3)); + test(rhs); + } + { typedef Y T; optional rhs; test(rhs); diff --git a/libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp b/libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp index 851157f..4ed0c92 100644 --- a/libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp +++ b/libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp @@ -74,6 +74,17 @@ public: friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;} }; + +class ConstMovable +{ + int i_; +public: + ConstMovable(int i) : i_(i) {} + ConstMovable(const ConstMovable&& x) : i_(x.i_) {} + ~ConstMovable() {i_ = 0;} + friend bool operator==(const ConstMovable& x, const ConstMovable& y) {return x.i_ == y.i_;} +}; + int main() { { @@ -87,6 +98,11 @@ int main() test(rhs); } { + typedef const int T; + optional rhs(3); + test(rhs); + } + { typedef X T; optional rhs; test(rhs); @@ -97,6 +113,11 @@ int main() test(rhs); } { + typedef const ConstMovable T; + optional rhs(ConstMovable(3)); + test(rhs); + } + { typedef Y T; optional rhs; test(rhs); diff --git a/libcxx/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp b/libcxx/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp index 620dda1..be0d1ef 100644 --- a/libcxx/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp +++ b/libcxx/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp @@ -62,6 +62,10 @@ public: friend void swap(Z& x, Z& y) {throw 6;} }; +struct ConstSwappable { +}; +void swap(ConstSwappable const&, ConstSwappable const&) {} + int main() { { @@ -113,6 +117,11 @@ int main() assert(*opt2 == 1); } { + optional opt; + optional opt2; + opt.swap(opt2); + } + { optional opt1; optional opt2; static_assert(noexcept(opt1.swap(opt2)) == true, "");