summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzoecarver <z.zoelec2@gmail.com>2021-04-08 22:01:35 -0700
committerTom Stellard <tstellar@redhat.com>2021-06-22 20:27:57 -0400
commit5cb4200739750a7866817c22de32b50819cd76b5 (patch)
treed96c53058df2226823bb7446103fae17a92e4fe2
parent0680e2b5a1182abc1d2fdb6730ef7d742a4d6345 (diff)
downloadllvm-5cb4200739750a7866817c22de32b50819cd76b5.tar.gz
[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)
-rw-r--r--libcxx/include/memory10
-rw-r--r--libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/unique_ptr_Y.pass.cpp90
-rw-r--r--libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp88
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;
}