diff --git a/libcxx/docs/Status/Cxx2bIssues.csv b/libcxx/docs/Status/Cxx2bIssues.csv --- a/libcxx/docs/Status/Cxx2bIssues.csv +++ b/libcxx/docs/Status/Cxx2bIssues.csv @@ -90,7 +90,7 @@ `3543 `__,"Definition of when ``counted_iterators`` refer to the same sequence isn't quite right","June 2021","|Nothing To Do|","","|ranges|" `3544 `__,"``format-arg-store::args`` is unintentionally not exposition-only","June 2021","|Complete|","14.0","|format|" `3546 `__,"``common_iterator``'s postfix-proxy is not quite right","June 2021","","","|ranges|" -`3548 `__,"``shared_ptr`` construction from ``unique_ptr`` should move (not copy) the deleter","June 2021","","" +`3548 `__,"``shared_ptr`` construction from ``unique_ptr`` should move (not copy) the deleter","June 2021","|Complete|","15.0" `3549 `__,"``view_interface`` is overspecified to derive from ``view_base``","June 2021","|Complete|","14.0","|ranges|" `3551 `__,"``borrowed_{iterator,subrange}_t`` are overspecified","June 2021","|Nothing To Do|","","|ranges|" `3552 `__,"Parallel specialized memory algorithms should require forward iterators","June 2021","","" diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -457,7 +457,7 @@ explicit shared_ptr(_Yp* __p) : __ptr_(__p) { unique_ptr<_Yp> __hold(__p); typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; - typedef __shared_ptr_pointer<_Yp*, __shared_ptr_default_delete<_Tp, _Yp>, _AllocT > _CntrlBlk; + typedef __shared_ptr_pointer<_Yp*, __shared_ptr_default_delete<_Tp, _Yp>, _AllocT> _CntrlBlk; __cntrl_ = new _CntrlBlk(__p, __shared_ptr_default_delete<_Tp, _Yp>(), _AllocT()); __hold.release(); __enable_weak_this(__p, __p); @@ -473,7 +473,7 @@ { #endif // _LIBCPP_NO_EXCEPTIONS typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; - typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT > _CntrlBlk; + typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT> _CntrlBlk; #ifndef _LIBCPP_CXX03_LANG __cntrl_ = new _CntrlBlk(__p, _VSTD::move(__d), _AllocT()); #else @@ -532,7 +532,7 @@ { #endif // _LIBCPP_NO_EXCEPTIONS typedef typename __shared_ptr_default_allocator<_Tp>::type _AllocT; - typedef __shared_ptr_pointer _CntrlBlk; + typedef __shared_ptr_pointer _CntrlBlk; #ifndef _LIBCPP_CXX03_LANG __cntrl_ = new _CntrlBlk(__p, _VSTD::move(__d), _AllocT()); #else @@ -665,8 +665,8 @@ #endif { typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; - typedef __shared_ptr_pointer::pointer, _Dp, _AllocT > _CntrlBlk; - __cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), _AllocT()); + typedef __shared_ptr_pointer::pointer, _Dp, _AllocT> _CntrlBlk; + __cntrl_ = new _CntrlBlk(__r.get(), std::move(__r.get_deleter()), _AllocT()); __enable_weak_this(__r.get(), __r.get()); } __r.release(); @@ -689,7 +689,7 @@ typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; typedef __shared_ptr_pointer::pointer, reference_wrapper::type>, - _AllocT > _CntrlBlk; + _AllocT> _CntrlBlk; __cntrl_ = new _CntrlBlk(__r.get(), _VSTD::ref(__r.get_deleter()), _AllocT()); __enable_weak_this(__r.get(), __r.get()); } diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp @@ -82,6 +82,13 @@ } }; +struct MovingDeleter { + explicit MovingDeleter(int *moves) : moves_(moves) {} + MovingDeleter(MovingDeleter&& rhs) : moves_(rhs.moves_) { *moves_ += 1; } + void operator()(int*) const {} + int *moves_; +}; + int main(int, char**) { { @@ -230,10 +237,39 @@ assert(A::count == 0); { - std::unique_ptr ptr(new int[8]); - std::shared_ptr p(std::move(ptr)); + int *p = new int[8]; + std::unique_ptr u(p); + std::shared_ptr s(std::move(u)); + assert(u == nullptr); + assert(s.get() == p); + } +#endif // TEST_STD_VER > 14 + + { // LWG 3548 + { + int moves = 0; + int i = 42; + std::unique_ptr u(&i, MovingDeleter(&moves)); + assert(moves == 1); + std::shared_ptr s(std::move(u)); + assert(moves >= 2); + assert(u == nullptr); + assert(s.get() == &i); + } + +#if TEST_STD_VER > 14 + { + int moves = 0; + int a[8]; + std::unique_ptr u(a, MovingDeleter(&moves)); + assert(moves == 1); + std::shared_ptr s = std::move(u); + assert(moves >= 2); + assert(u == nullptr); + assert(s.get() == a); + } +#endif // TEST_STD_VER > 14 } -#endif // TEST_STD_VER >= 14 return 0; }