From 0ad232a8826f08d3a1e6a217ecf58a300960439a Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Sun, 10 May 2015 13:59:45 +0000 Subject: [PATCH] Fix for LWG Issue 2415: Inconsistency between unique_ptr and shared_ptr git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@236953 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/memory | 32 +++++++++++++------ .../unique_ptr_Y.pass.cpp | 4 +-- .../unique_ptr.pass.cpp | 12 +++++++ 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/include/memory b/include/memory index 3f7ea1a2..eb4a30f1 100644 --- a/include/memory +++ b/include/memory @@ -1639,7 +1639,7 @@ template struct __rebind_alloc_helper { #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - typedef typename _Traits::template rebind_alloc<_Tp> type; + typedef typename _Traits::template rebind_alloc<_Tp> type; #else typedef typename _Traits::template rebind_alloc<_Tp>::other type; #endif @@ -4277,9 +4277,16 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp> __r, >::type) : __ptr_(__r.get()) { - typedef __shared_ptr_pointer<_Yp*, _Dp, allocator<_Yp> > _CntrlBlk; - __cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), allocator<_Yp>()); - __enable_weak_this(__r.get()); +#if _LIBCPP_STD_VER > 11 + if (__ptr_ == nullptr) + __cntrl_ = nullptr; + else +#endif + { + typedef __shared_ptr_pointer<_Yp*, _Dp, allocator<_Yp> > _CntrlBlk; + __cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), allocator<_Yp>()); + __enable_weak_this(__r.get()); + } __r.release(); } @@ -4299,11 +4306,18 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp> __r, >::type) : __ptr_(__r.get()) { - typedef __shared_ptr_pointer<_Yp*, - reference_wrapper::type>, - allocator<_Yp> > _CntrlBlk; - __cntrl_ = new _CntrlBlk(__r.get(), ref(__r.get_deleter()), allocator<_Yp>()); - __enable_weak_this(__r.get()); +#if _LIBCPP_STD_VER > 11 + if (__ptr_ == nullptr) + __cntrl_ = nullptr; + else +#endif + { + typedef __shared_ptr_pointer<_Yp*, + reference_wrapper::type>, + allocator<_Yp> > _CntrlBlk; + __cntrl_ = new _CntrlBlk(__r.get(), ref(__r.get_deleter()), allocator<_Yp>()); + __enable_weak_this(__r.get()); + } __r.release(); } diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/unique_ptr_Y.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/unique_ptr_Y.pass.cpp index 742d8c1b..30e0fce2 100644 --- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/unique_ptr_Y.pass.cpp +++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/unique_ptr_Y.pass.cpp @@ -67,7 +67,7 @@ int main() pB = std::move(pA); assert(B::count == 0); assert(A::count == 0); - assert(pB.use_count() == 1); +// assert(pB.use_count() == 1); // no longer true due to LWG 2415 assert(pA.get() == 0); assert(pB.get() == ptrA); } @@ -101,7 +101,7 @@ int main() pB = std::move(pA); assert(B::count == 0); assert(A::count == 0); - assert(pB.use_count() == 1); +// assert(pB.use_count() == 1); // no longer true due to LWG 2415 assert(pA.get() == 0); assert(pB.get() == ptrA); } diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp index 68b9b288..5e09d9a7 100644 --- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp +++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp @@ -58,6 +58,9 @@ int A::count = 0; void fn ( const std::shared_ptr &) {} void fn ( const std::shared_ptr &) { assert (false); } +template +void assert_deleter ( T * ) { assert(false); } + int main() { { @@ -100,4 +103,13 @@ int main() throw_next = false; fn(std::unique_ptr(new int)); } + +#if __cplusplus >= 201402L + // LWG 2415 + { + std::unique_ptr p(nullptr, assert_deleter); + std::shared_ptr p2(std::move(p)); // should not call deleter when going out of scope + } +#endif + }