[llvm-branch-commits] [libcxx] 5cb4200 - [libcxx] Allow shared_ptr's unique_ptr converting constructor to support array types.

Tom Stellard via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Jun 22 17:28:25 PDT 2021


Author: zoecarver
Date: 2021-06-22T20:27:57-04:00
New Revision: 5cb4200739750a7866817c22de32b50819cd76b5

URL: https://github.com/llvm/llvm-project/commit/5cb4200739750a7866817c22de32b50819cd76b5
DIFF: https://github.com/llvm/llvm-project/commit/5cb4200739750a7866817c22de32b50819cd76b5.diff

LOG: [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)

Added: 
    

Modified: 
    libcxx/include/memory
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/unique_ptr_Y.pass.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/memory b/libcxx/include/memory
index e02846b4035cf..62235cf72b353 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 0096897ee07e6..f9e1798d8a7a6 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 398c64ee6d74a..ad88a3e8a7dfc 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;
 }


        


More information about the llvm-branch-commits mailing list