diff options
author | zoecarver <z.zoelec2@gmail.com> | 2021-04-08 22:01:35 -0700 |
---|---|---|
committer | Tom Stellard <tstellar@redhat.com> | 2021-06-22 20:27:57 -0400 |
commit | 5cb4200739750a7866817c22de32b50819cd76b5 (patch) | |
tree | d96c53058df2226823bb7446103fae17a92e4fe2 | |
parent | 0680e2b5a1182abc1d2fdb6730ef7d742a4d6345 (diff) |
[libcxx] Allow shared_ptr's unique_ptr converting constructor to support array types.
Refs: https://bugs.llvm.org/show_bug.cgi?id=32147
Differential Revision: https://reviews.llvm.org/D80882
(cherry picked from commit 097d77d611d1e1b3972be661fdc3caaa4d1824b4)
3 files changed, 178 insertions, 10 deletions
diff --git a/libcxx/include/memory b/libcxx/include/memory index e02846b4035c..62235cf72b35 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -2771,7 +2771,6 @@ public: typename enable_if < !is_lvalue_reference<_Dp>::value && - !is_array<_Yp>::value && is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, __nat >::type = __nat()); @@ -2780,7 +2779,6 @@ public: typename enable_if < is_lvalue_reference<_Dp>::value && - !is_array<_Yp>::value && is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, __nat >::type = __nat()); @@ -2821,7 +2819,6 @@ public: template <class _Yp, class _Dp> typename enable_if < - !is_array<_Yp>::value && is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, shared_ptr& >::type @@ -3183,7 +3180,6 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r, typename enable_if < !is_lvalue_reference<_Dp>::value && - !is_array<_Yp>::value && is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, __nat >::type) @@ -3196,7 +3192,7 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r, #endif { typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; - typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT > _CntrlBlk; + typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer, _Dp, _AllocT > _CntrlBlk; __cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), _AllocT()); __enable_weak_this(__r.get(), __r.get()); } @@ -3209,7 +3205,6 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r, typename enable_if < is_lvalue_reference<_Dp>::value && - !is_array<_Yp>::value && is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, __nat >::type) @@ -3222,7 +3217,7 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r, #endif { typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; - typedef __shared_ptr_pointer<_Yp*, + typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer, reference_wrapper<typename remove_reference<_Dp>::type>, _AllocT > _CntrlBlk; __cntrl_ = new _CntrlBlk(__r.get(), _VSTD::ref(__r.get_deleter()), _AllocT()); @@ -3306,7 +3301,6 @@ template <class _Yp, class _Dp> inline typename enable_if < - !is_array<_Yp>::value && is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, typename shared_ptr<_Tp>::element_type*>::value, shared_ptr<_Tp>& diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/unique_ptr_Y.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/unique_ptr_Y.pass.cpp index 0096897ee07e..f9e1798d8a7a 100644 --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/unique_ptr_Y.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/unique_ptr_Y.pass.cpp @@ -41,6 +41,19 @@ struct A int A::count = 0; +template <class T> +struct StatefulArrayDeleter { + int state = 0; + + StatefulArrayDeleter(int val = 0) : state(val) {} + StatefulArrayDeleter(StatefulArrayDeleter const&) { assert(false); } + + void operator()(T* ptr) { + assert(state == 42); + delete []ptr; + } +}; + int main(int, char**) { { @@ -112,5 +125,82 @@ int main(int, char**) assert(B::count == 0); assert(A::count == 0); + { + std::unique_ptr<A[]> ptr(new A[8]); + A* raw_ptr = ptr.get(); + std::shared_ptr<B> p; + p = std::move(ptr); + assert(A::count == 8); + assert(B::count == 8); + assert(p.use_count() == 1); + assert(p.get() == raw_ptr); + assert(ptr.get() == 0); + } + assert(A::count == 0); + assert(B::count == 0); + + { + std::unique_ptr<A[]> ptr(new A[8]); + A* raw_ptr = ptr.get(); + std::shared_ptr<A> p; + p = std::move(ptr); + assert(A::count == 8); + assert(p.use_count() == 1); + assert(p.get() == raw_ptr); + assert(ptr.get() == 0); + } + assert(A::count == 0); + + { + std::unique_ptr<int[]> ptr(new int[8]); + std::shared_ptr<int> p; + p = std::move(ptr); + } + +#if TEST_STD_VER > 14 + { + StatefulArrayDeleter<A> d; + std::unique_ptr<A[], StatefulArrayDeleter<A>&> u(new A[4], d); + std::shared_ptr<A[]> p; + p = std::move(u); + d.state = 42; + assert(A::count == 4); + } + assert(A::count == 0); + assert(B::count == 0); + + { + std::unique_ptr<A[]> ptr(new A[8]); + A* raw_ptr = ptr.get(); + std::shared_ptr<B[]> p; + p = std::move(ptr); + assert(A::count == 8); + assert(B::count == 8); + assert(p.use_count() == 1); + assert(p.get() == raw_ptr); + assert(ptr.get() == 0); + } + assert(A::count == 0); + assert(B::count == 0); + + { + std::unique_ptr<A[]> ptr(new A[8]); + A* raw_ptr = ptr.get(); + std::shared_ptr<A[]> p; + p = std::move(ptr); + assert(A::count == 8); + assert(p.use_count() == 1); + assert(p.get() == raw_ptr); + assert(ptr.get() == 0); + } + assert(A::count == 0); + + { + std::unique_ptr<int[]> ptr(new int[8]); + std::shared_ptr<int[]> p; + p = std::move(ptr); + } +#endif // TEST_STD_VER >= 14 + return 0; } 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 index 398c64ee6d74..ad88a3e8a7df 100644 --- 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 @@ -10,7 +10,7 @@ // <memory> -// template <class Y, class D> explicit shared_ptr(unique_ptr<Y, D>&&r); +// template <class Y, class D> shared_ptr(unique_ptr<Y, D>&&r); #include <memory> #include <new> @@ -69,6 +69,19 @@ struct StatefulDeleter { } }; +template <class T> +struct StatefulArrayDeleter { + int state = 0; + + StatefulArrayDeleter(int val = 0) : state(val) {} + StatefulArrayDeleter(StatefulArrayDeleter const&) { assert(false); } + + void operator()(T* ptr) { + assert(state == 42); + delete []ptr; + } +}; + int main(int, char**) { { @@ -135,5 +148,76 @@ int main(int, char**) std::shared_ptr<int> s = std::move(u); } - return 0; + assert(A::count == 0); + { + std::unique_ptr<A[]> ptr(new A[8]); + A* raw_ptr = ptr.get(); + std::shared_ptr<B> p(std::move(ptr)); + assert(A::count == 8); + assert(B::count == 8); + assert(p.use_count() == 1); + assert(p.get() == raw_ptr); + assert(ptr.get() == 0); + } + assert(A::count == 0); + assert(B::count == 0); + + { + std::unique_ptr<A[]> ptr(new A[8]); + A* raw_ptr = ptr.get(); + std::shared_ptr<A> p(std::move(ptr)); + assert(A::count == 8); + assert(p.use_count() == 1); + assert(p.get() == raw_ptr); + assert(ptr.get() == 0); + } + assert(A::count == 0); + + { + std::unique_ptr<int[]> ptr(new int[8]); + std::shared_ptr<int> p(std::move(ptr)); + } + +#if TEST_STD_VER > 14 + { + StatefulArrayDeleter<A> d; + std::unique_ptr<A[], StatefulArrayDeleter<A>&> u(new A[4], d); + std::shared_ptr<A[]> p(std::move(u)); + d.state = 42; + assert(A::count == 4); + } + assert(A::count == 0); + assert(B::count == 0); + + { + std::unique_ptr<A[]> ptr(new A[8]); + A* raw_ptr = ptr.get(); + std::shared_ptr<B[]> p(std::move(ptr)); + assert(A::count == 8); + assert(B::count == 8); + assert(p.use_count() == 1); + assert(p.get() == raw_ptr); + assert(ptr.get() == 0); + } + assert(A::count == 0); + assert(B::count == 0); + + { + std::unique_ptr<A[]> ptr(new A[8]); + A* raw_ptr = ptr.get(); + std::shared_ptr<A[]> p(std::move(ptr)); + assert(A::count == 8); + assert(p.use_count() == 1); + assert(p.get() == raw_ptr); + assert(ptr.get() == 0); + } + assert(A::count == 0); + + { + std::unique_ptr<int[]> ptr(new int[8]); + std::shared_ptr<int[]> p(std::move(ptr)); + } +#endif // TEST_STD_VER >= 14 + + return 0; } |