Author: ericwf Date: Tue Sep 6 20:56:07 2016 New Revision: 280775 URL: http://llvm.org/viewvc/llvm-project?rev=280775&view=rev Log: Fix PR30260 - optional<const T> 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 <experimental/optional> to _LIBCPP_EXPERIMENTAL_OPTIONAL from _LIBCPP_OPTIONAL. Modified: libcxx/trunk/include/experimental/optional libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp Modified: libcxx/trunk/include/experimental/optional URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/experimental/optional?rev=280775&r1=280774&r2=280775&view=diff ============================================================================== --- libcxx/trunk/include/experimental/optional (original) +++ libcxx/trunk/include/experimental/optional Tue Sep 6 20:56:07 2016 @@ -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 Modified: libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp?rev=280775&r1=280774&r2=280775&view=diff ============================================================================== --- libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp (original) +++ libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp Tue Sep 6 20:56:07 2016 @@ -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<const AllowConstAssign> opt; + const AllowConstAssign other; + opt = other; + } + { optional<std::unique_ptr<int>> opt; opt = std::unique_ptr<int>(new int(3)); assert(static_cast<bool>(opt) == true); Modified: libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp?rev=280775&r1=280774&r2=280775&view=diff ============================================================================== --- libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp (original) +++ libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp Tue Sep 6 20:56:07 2016 @@ -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<bool>(opt) == static_cast<bool>(opt2)); } { + optional<const AllowConstAssign> opt; + optional<const AllowConstAssign> opt2; + opt = opt2; + } + { optional<int> opt; constexpr optional<int> opt2(2); opt = opt2; Modified: libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp?rev=280775&r1=280774&r2=280775&view=diff ============================================================================== --- libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp (original) +++ libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp Tue Sep 6 20:56:07 2016 @@ -81,6 +81,12 @@ int main() assert(*opt == 1); } { + optional<const int> opt(2); + opt.emplace(1); + assert(static_cast<bool>(opt) == true); + assert(*opt == 1); + } + { optional<X> opt; opt.emplace(); assert(static_cast<bool>(opt) == true); Modified: libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp?rev=280775&r1=280774&r2=280775&view=diff ============================================================================== --- libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp (original) +++ libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp Tue Sep 6 20:56:07 2016 @@ -81,6 +81,17 @@ int main() assert(*opt == X({1, 2})); } } + X::dtor_called = false; + { + X x; + { + optional<const X> opt(x); + assert(X::dtor_called == false); + opt.emplace({1, 2}); + assert(X::dtor_called == true); + assert(*opt == X({1, 2})); + } + } { optional<std::vector<int>> opt; opt.emplace({1, 2, 3}, std::allocator<int>()); Modified: libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp?rev=280775&r1=280774&r2=280775&view=diff ============================================================================== --- libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp (original) +++ libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp Tue Sep 6 20:56:07 2016 @@ -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<const AllowConstAssign> opt; + optional<const AllowConstAssign> opt2; + opt = std::move(opt2); + } + { static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, ""); optional<X> opt; optional<X> opt2(X{}); Modified: libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp?rev=280775&r1=280774&r2=280775&view=diff ============================================================================== --- libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp (original) +++ libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp Tue Sep 6 20:56:07 2016 @@ -88,6 +88,11 @@ int main() test(rhs); } { + typedef const int T; + optional<T> rhs(3); + test(rhs); + } + { typedef X T; optional<T> rhs; test(rhs); @@ -97,6 +102,11 @@ int main() optional<T> rhs(X(3)); test(rhs); } + { + typedef const X T; + optional<T> rhs(X(3)); + test(rhs); + } { typedef Y T; optional<T> rhs; Modified: libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp?rev=280775&r1=280774&r2=280775&view=diff ============================================================================== --- libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp (original) +++ libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp Tue Sep 6 20:56:07 2016 @@ -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<T> rhs(3); + test(rhs); + } + { typedef X T; optional<T> rhs; test(rhs); @@ -97,6 +113,11 @@ int main() test(rhs); } { + typedef const ConstMovable T; + optional<T> rhs(ConstMovable(3)); + test(rhs); + } + { typedef Y T; optional<T> rhs; test(rhs); Modified: libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp?rev=280775&r1=280774&r2=280775&view=diff ============================================================================== --- libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp (original) +++ libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp Tue Sep 6 20:56:07 2016 @@ -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<const ConstSwappable> opt; + optional<const ConstSwappable> opt2; + opt.swap(opt2); + } + { optional<X> opt1; optional<X> opt2; static_assert(noexcept(opt1.swap(opt2)) == true, ""); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits