Author: ericwf Date: Mon Apr 17 15:20:27 2017 New Revision: 300489 URL: http://llvm.org/viewvc/llvm-project?rev=300489&view=rev Log: Fix passing incorrectly value-category when constructing unique_ptr's deleter
Modified: libcxx/trunk/include/memory libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.pass.cpp Modified: libcxx/trunk/include/memory URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=300489&r1=300488&r2=300489&view=diff ============================================================================== --- libcxx/trunk/include/memory (original) +++ libcxx/trunk/include/memory Mon Apr 17 15:20:27 2017 @@ -2734,7 +2734,7 @@ public: > _LIBCPP_INLINE_VISIBILITY unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept - : __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) { + : __ptr_(__u.release(), _VSTD::forward<_Ep>(__u.get_deleter())) { } template <class _Up, class _Ep, Modified: libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.pass.cpp?rev=300489&r1=300488&r2=300489&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.pass.cpp Mon Apr 17 15:20:27 2017 @@ -19,6 +19,7 @@ #include <cassert> #include "test_macros.h" +#include "type_id.h" #include "unique_ptr_test_helper.h" template <int ID = 0> @@ -33,9 +34,71 @@ struct GenericConvertingDeleter { void operator()(void*) const {} }; +template <class Templ, class Other> +struct is_specialization; + +template <template <int> class Templ, int ID1, class Other> +struct is_specialization<Templ<ID1>, Other> : std::false_type {}; + +template <template <int> class Templ, int ID1, int ID2> +struct is_specialization<Templ<ID1>, Templ<ID2> > : std::true_type {}; + +template <class Templ, class Other> +using EnableIfSpecialization = typename std::enable_if< + is_specialization<Templ, typename std::decay<Other>::type >::value + >::type; + + +template <int ID> +struct TrackingDeleter { + TrackingDeleter() : arg_type(&makeArgumentID<>()) {} + + TrackingDeleter(TrackingDeleter const&) + : arg_type(&makeArgumentID<TrackingDeleter const&>()) {} + + TrackingDeleter(TrackingDeleter&&) + : arg_type(&makeArgumentID<TrackingDeleter &&>()) {} + + template <class T, class = EnableIfSpecialization<TrackingDeleter, T> > + TrackingDeleter(T&&) : arg_type(&makeArgumentID<T&&>()) {} + + TrackingDeleter& operator=(TrackingDeleter const&) { + arg_type = &makeArgumentID<TrackingDeleter const&>(); + return *this; + } + + TrackingDeleter& operator=(TrackingDeleter &&) { + arg_type = &makeArgumentID<TrackingDeleter &&>(); + return *this; + } + + template <class T, class = EnableIfSpecialization<TrackingDeleter, T> > + TrackingDeleter& operator=(T&&) { + arg_type = &makeArgumentID<T&&>(); + return *this; + } + + void operator()(void*) const {} + +public: + TypeID const* reset() const { + TypeID const* tmp = arg_type; + arg_type = nullptr; + return tmp; + } + + mutable TypeID const* arg_type; +}; + + +template <class ExpectT, int ID> +bool checkArg(TrackingDeleter<ID> const& d) { + return d.arg_type && *d.arg_type == makeArgumentID<ExpectT>(); +} + + template <bool IsArray> void test_sfinae() { -#if TEST_STD_VER >= 11 typedef typename std::conditional<IsArray, A[], A>::type VT; { // Test that different non-reference deleter types are allowed so long @@ -80,13 +143,11 @@ void test_sfinae() { static_assert(std::is_constructible<U1, U5&&>::value, ""); static_assert(std::is_constructible<U1, U6&&>::value, ""); } -#endif } template <bool IsArray> void test_noexcept() { -#if TEST_STD_VER >= 11 typedef typename std::conditional<IsArray, A[], A>::type VT; { typedef std::unique_ptr<const VT> APtr; @@ -108,7 +169,39 @@ void test_noexcept() { typedef std::unique_ptr<VT, const NCConstDeleter<const VT>&> BPtr; static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, ""); } -#endif +} + + +template <bool IsArray> +void test_deleter_value_category() { + typedef typename std::conditional<IsArray, A[], A>::type VT; + using TD1 = TrackingDeleter<1>; + using TD2 = TrackingDeleter<2>; + TD1 d1; + TD2 d2; + + { // Test non-reference deleter conversions + using U1 = std::unique_ptr<VT, TD1 >; + using U2 = std::unique_ptr<VT, TD2 >; + U2 u2; + u2.get_deleter().reset(); + U1 u1(std::move(u2)); + assert(checkArg<TD2&&>(u1.get_deleter())); + } + { // Test assignment from non-const ref + using U1 = std::unique_ptr<VT, TD1 >; + using U2 = std::unique_ptr<VT, TD2& >; + U2 u2(nullptr, d2); + U1 u1(std::move(u2)); + assert(checkArg<TD2&>(u1.get_deleter())); + } + { // Test assignment from const ref + using U1 = std::unique_ptr<VT, TD1 >; + using U2 = std::unique_ptr<VT, TD2 const& >; + U2 u2(nullptr, d2); + U1 u1(std::move(u2)); + assert(checkArg<TD2 const&>(u1.get_deleter())); + } } @@ -116,9 +209,11 @@ int main() { { test_sfinae</*IsArray*/false>(); test_noexcept<false>(); + test_deleter_value_category<false>(); } { test_sfinae</*IsArray*/true>(); test_noexcept<true>(); + test_deleter_value_category<true>(); } } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits