[libcxx-commits] [libcxx] e8c13c1 - [libcxx] shared_ptr changes from library fundamentals (P0414R2).

via libcxx-commits libcxx-commits at lists.llvm.org
Mon May 11 18:47:06 PDT 2020


Author: zoecarver
Date: 2020-05-11T18:46:29-07:00
New Revision: e8c13c182a562f45287d6b8da612264d09027087

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

LOG: [libcxx] shared_ptr changes from library fundamentals (P0414R2).

Implements P0414R2:
  * Adds support for array types in std::shared_ptr.
  * Adds reinterpret_pointer_cast for shared_ptr.

Differential Revision: https://reviews.llvm.org/D62259

Added: 
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/reinterpret_pointer_cast.pass.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_copy_move.fail.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_arrow.fail.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bracket.fail.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bracket.pass.cpp

Modified: 
    libcxx/include/memory
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/types.pass.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/const_pointer_cast.pass.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/dynamic_pointer_cast.pass.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/static_pointer_cast.pass.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/default.pass.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer.pass.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_pointer.pass.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.protected.fail.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bool.pass.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.assign/shared_ptr_Y.pass.cpp
    libcxx/www/cxx1z_status.html

Removed: 
    


################################################################################
diff  --git a/libcxx/include/memory b/libcxx/include/memory
index 29c5e98b3b7c..49627147b061 100644
--- a/libcxx/include/memory
+++ b/libcxx/include/memory
@@ -3702,15 +3702,25 @@ public:
 
 template<class _Tp> class _LIBCPP_TEMPLATE_VIS enable_shared_from_this;
 
+template<class _Tp, class _Up>
+struct __compatible_with
+#if _LIBCPP_STD_VER > 14
+    : is_convertible<remove_extent_t<_Tp>*, remove_extent_t<_Up>*> {};
+#else
+    : is_convertible<_Tp*, _Up*> {};
+#endif // _LIBCPP_STD_VER > 14
+
 template<class _Tp>
 class _LIBCPP_TEMPLATE_VIS shared_ptr
 {
 public:
-    typedef _Tp element_type;
-
 #if _LIBCPP_STD_VER > 14
     typedef weak_ptr<_Tp> weak_type;
+    typedef remove_extent_t<_Tp> element_type;
+#else
+    typedef _Tp element_type;
 #endif
+
 private:
     element_type*      __ptr_;
     __shared_weak_count* __cntrl_;
@@ -3723,13 +3733,13 @@ public:
     _LIBCPP_CONSTEXPR shared_ptr(nullptr_t) _NOEXCEPT;
     template<class _Yp>
         explicit shared_ptr(_Yp* __p,
-                            typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type = __nat());
+                            typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat());
     template<class _Yp, class _Dp>
         shared_ptr(_Yp* __p, _Dp __d,
-                   typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type = __nat());
+                   typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat());
     template<class _Yp, class _Dp, class _Alloc>
         shared_ptr(_Yp* __p, _Dp __d, _Alloc __a,
-                   typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type = __nat());
+                   typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat());
     template <class _Dp> shared_ptr(nullptr_t __p, _Dp __d);
     template <class _Dp, class _Alloc> shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a);
     template<class _Yp> _LIBCPP_INLINE_VISIBILITY shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) _NOEXCEPT;
@@ -3738,13 +3748,13 @@ public:
     template<class _Yp>
         _LIBCPP_INLINE_VISIBILITY
         shared_ptr(const shared_ptr<_Yp>& __r,
-                   typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type = __nat())
+                   typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat())
                        _NOEXCEPT;
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     _LIBCPP_INLINE_VISIBILITY
     shared_ptr(shared_ptr&& __r) _NOEXCEPT;
     template<class _Yp> _LIBCPP_INLINE_VISIBILITY  shared_ptr(shared_ptr<_Yp>&& __r,
-                   typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type = __nat())
+                   typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat())
                        _NOEXCEPT;
 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
     template<class _Yp> explicit shared_ptr(const weak_ptr<_Yp>& __r,
@@ -3807,7 +3817,7 @@ public:
     template<class _Yp>
         typename enable_if
         <
-            is_convertible<_Yp*, element_type*>::value,
+            __compatible_with<_Yp, element_type>::value,
             shared_ptr&
         >::type
         _LIBCPP_INLINE_VISIBILITY
@@ -3818,8 +3828,8 @@ public:
     template<class _Yp>
         typename enable_if
         <
-            is_convertible<_Yp*, element_type*>::value,
-            shared_ptr<_Tp>&
+            __compatible_with<_Yp, element_type>::value,
+            shared_ptr&
         >::type
         _LIBCPP_INLINE_VISIBILITY
         operator=(shared_ptr<_Yp>&& __r);
@@ -3869,7 +3879,7 @@ public:
     template<class _Yp>
         typename enable_if
         <
-            is_convertible<_Yp*, element_type*>::value,
+            __compatible_with<_Yp, element_type>::value,
             void
         >::type
         _LIBCPP_INLINE_VISIBILITY
@@ -3877,7 +3887,7 @@ public:
     template<class _Yp, class _Dp>
         typename enable_if
         <
-            is_convertible<_Yp*, element_type*>::value,
+            __compatible_with<_Yp, element_type>::value,
             void
         >::type
         _LIBCPP_INLINE_VISIBILITY
@@ -3885,7 +3895,7 @@ public:
     template<class _Yp, class _Dp, class _Alloc>
         typename enable_if
         <
-            is_convertible<_Yp*, element_type*>::value,
+            __compatible_with<_Yp, element_type>::value,
             void
         >::type
         _LIBCPP_INLINE_VISIBILITY
@@ -3897,7 +3907,12 @@ public:
     typename add_lvalue_reference<element_type>::type operator*() const _NOEXCEPT
         {return *__ptr_;}
     _LIBCPP_INLINE_VISIBILITY
-    element_type* operator->() const _NOEXCEPT {return __ptr_;}
+    element_type* operator->() const _NOEXCEPT
+    {
+        static_assert(!_VSTD::is_array<_Tp>::value,
+                      "std::shared_ptr<T>::operator-> is only valid when T is not an array type.");
+        return __ptr_;
+    }
     _LIBCPP_INLINE_VISIBILITY
     long use_count() const _NOEXCEPT {return __cntrl_ ? __cntrl_->use_count() : 0;}
     _LIBCPP_INLINE_VISIBILITY
@@ -3917,6 +3932,17 @@ public:
     __owner_equivalent(const shared_ptr& __p) const
         {return __cntrl_ == __p.__cntrl_;}
 
+#if _LIBCPP_STD_VER > 14
+    typename add_lvalue_reference<element_type>::type
+    _LIBCPP_INLINE_VISIBILITY
+    operator[](ptr
diff _t __i) const
+    {
+            static_assert(_VSTD::is_array<_Tp>::value,
+                          "std::shared_ptr<T>::operator[] is only valid when T is an array type.");
+            return __ptr_[__i];
+    }
+#endif
+
 #ifndef _LIBCPP_NO_RTTI
     template <class _Dp>
         _LIBCPP_INLINE_VISIBILITY
@@ -3969,6 +3995,18 @@ private:
 
     _LIBCPP_INLINE_VISIBILITY void __enable_weak_this(...) _NOEXCEPT {}
 
+    template <class, class _Yp>
+        struct __shared_ptr_default_delete
+            : default_delete<_Yp> {};
+
+    template <class _Yp, class _Un, size_t _Sz>
+        struct __shared_ptr_default_delete<_Yp[_Sz], _Un>
+            : default_delete<_Yp[]> {};
+
+    template <class _Yp, class _Un>
+        struct __shared_ptr_default_delete<_Yp[], _Un>
+            : default_delete<_Yp[]> {};
+
     template <class _Up> friend class _LIBCPP_TEMPLATE_VIS shared_ptr;
     template <class _Up> friend class _LIBCPP_TEMPLATE_VIS weak_ptr;
 };
@@ -4001,13 +4039,13 @@ shared_ptr<_Tp>::shared_ptr(nullptr_t) _NOEXCEPT
 template<class _Tp>
 template<class _Yp>
 shared_ptr<_Tp>::shared_ptr(_Yp* __p,
-                            typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type)
+                            typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type)
     : __ptr_(__p)
 {
     unique_ptr<_Yp> __hold(__p);
     typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
-    typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, _AllocT > _CntrlBlk;
-    __cntrl_ = new _CntrlBlk(__p, default_delete<_Yp>(), _AllocT());
+    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);
 }
@@ -4015,7 +4053,7 @@ shared_ptr<_Tp>::shared_ptr(_Yp* __p,
 template<class _Tp>
 template<class _Yp, class _Dp>
 shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d,
-                            typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type)
+                            typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type)
     : __ptr_(__p)
 {
 #ifndef _LIBCPP_NO_EXCEPTIONS
@@ -4061,7 +4099,7 @@ shared_ptr<_Tp>::shared_ptr(nullptr_t __p, _Dp __d)
 template<class _Tp>
 template<class _Yp, class _Dp, class _Alloc>
 shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d, _Alloc __a,
-                            typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type)
+                            typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type)
     : __ptr_(__p)
 {
 #ifndef _LIBCPP_NO_EXCEPTIONS
@@ -4139,7 +4177,7 @@ template<class _Tp>
 template<class _Yp>
 inline
 shared_ptr<_Tp>::shared_ptr(const shared_ptr<_Yp>& __r,
-                            typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type)
+                            typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type)
          _NOEXCEPT
     : __ptr_(__r.__ptr_),
       __cntrl_(__r.__cntrl_)
@@ -4164,7 +4202,7 @@ template<class _Tp>
 template<class _Yp>
 inline
 shared_ptr<_Tp>::shared_ptr(shared_ptr<_Yp>&& __r,
-                            typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type)
+                            typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type)
          _NOEXCEPT
     : __ptr_(__r.__ptr_),
       __cntrl_(__r.__cntrl_)
@@ -4276,7 +4314,7 @@ template<class _Yp>
 inline
 typename enable_if
 <
-    is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value,
+    __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value,
     shared_ptr<_Tp>&
 >::type
 shared_ptr<_Tp>::operator=(const shared_ptr<_Yp>& __r) _NOEXCEPT
@@ -4301,7 +4339,7 @@ template<class _Yp>
 inline
 typename enable_if
 <
-    is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value,
+    __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value,
     shared_ptr<_Tp>&
 >::type
 shared_ptr<_Tp>::operator=(shared_ptr<_Yp>&& __r)
@@ -4402,7 +4440,7 @@ template<class _Yp>
 inline
 typename enable_if
 <
-    is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value,
+    __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value,
     void
 >::type
 shared_ptr<_Tp>::reset(_Yp* __p)
@@ -4415,7 +4453,7 @@ template<class _Yp, class _Dp>
 inline
 typename enable_if
 <
-    is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value,
+    __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value,
     void
 >::type
 shared_ptr<_Tp>::reset(_Yp* __p, _Dp __d)
@@ -4428,7 +4466,7 @@ template<class _Yp, class _Dp, class _Alloc>
 inline
 typename enable_if
 <
-    is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value,
+    __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value,
     void
 >::type
 shared_ptr<_Tp>::reset(_Yp* __p, _Dp __d, _Alloc __a)
@@ -4642,41 +4680,41 @@ swap(shared_ptr<_Tp>& __x, shared_ptr<_Tp>& __y) _NOEXCEPT
 
 template<class _Tp, class _Up>
 inline _LIBCPP_INLINE_VISIBILITY
-typename enable_if
-<
-    !is_array<_Tp>::value && !is_array<_Up>::value,
-    shared_ptr<_Tp>
->::type
+shared_ptr<_Tp>
 static_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT
 {
-    return shared_ptr<_Tp>(__r, static_cast<_Tp*>(__r.get()));
+    return shared_ptr<_Tp>(__r,
+                           static_cast<
+                               typename shared_ptr<_Tp>::element_type*>(__r.get()));
 }
 
 template<class _Tp, class _Up>
 inline _LIBCPP_INLINE_VISIBILITY
-typename enable_if
-<
-    !is_array<_Tp>::value && !is_array<_Up>::value,
-    shared_ptr<_Tp>
->::type
+shared_ptr<_Tp>
 dynamic_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT
 {
-    _Tp* __p = dynamic_cast<_Tp*>(__r.get());
+    typedef typename shared_ptr<_Tp>::element_type _ET;
+    _ET* __p = dynamic_cast<_ET*>(__r.get());
     return __p ? shared_ptr<_Tp>(__r, __p) : shared_ptr<_Tp>();
 }
 
 template<class _Tp, class _Up>
-typename enable_if
-<
-    is_array<_Tp>::value == is_array<_Up>::value,
-    shared_ptr<_Tp>
->::type
+shared_ptr<_Tp>
 const_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT
 {
-    typedef typename remove_extent<_Tp>::type _RTp;
+    typedef typename shared_ptr<_Tp>::element_type _RTp;
     return shared_ptr<_Tp>(__r, const_cast<_RTp*>(__r.get()));
 }
 
+template<class _Tp, class _Up>
+shared_ptr<_Tp>
+reinterpret_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT
+{
+    return shared_ptr<_Tp>(__r,
+                           reinterpret_cast<
+                               typename shared_ptr<_Tp>::element_type*>(__r.get()));
+}
+
 #ifndef _LIBCPP_NO_RTTI
 
 template<class _Dp, class _Tp>
@@ -5080,7 +5118,7 @@ struct _LIBCPP_TEMPLATE_VIS hash<shared_ptr<_Tp> >
     _LIBCPP_INLINE_VISIBILITY
     result_type operator()(const argument_type& __ptr) const _NOEXCEPT
     {
-        return hash<_Tp*>()(__ptr.get());
+        return hash<typename shared_ptr<_Tp>::element_type*>()(__ptr.get());
     }
 };
 

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/types.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/types.pass.cpp
index c3aedd5b1ad2..b33f4043e1e0 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/types.pass.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/types.pass.cpp
@@ -20,14 +20,42 @@
 
 #include "test_macros.h"
 
+#if TEST_STD_VER > 14
+template <typename T, typename = std::void_t<> >
+struct has_less : std::false_type {};
+
+template <typename T>
+struct has_less<T,
+                std::void_t<decltype(std::declval<T>() < std::declval<T>())> >
+    : std::true_type {};
+#endif
+
 struct A;  // purposefully incomplete
+struct B {
+  int x;
+  B() = default;
+};
 
-int main(int, char**)
-{
-    static_assert((std::is_same<std::shared_ptr<A>::element_type, A>::value), "");
+template <class T>
+void test() {
+  ASSERT_SAME_TYPE(typename std::shared_ptr<T>::element_type, T);
 #if TEST_STD_VER > 14
-    static_assert((std::is_same<std::shared_ptr<A>::weak_type, std::weak_ptr<A>>::value), "");
+  ASSERT_SAME_TYPE(typename std::shared_ptr<T>::weak_type, std::weak_ptr<T>);
+  static_assert(std::is_copy_constructible<std::shared_ptr<T> >::value, "");
+  static_assert(std::is_copy_assignable<std::shared_ptr<T> >::value, "");
+  static_assert(has_less<std::shared_ptr<T> >::value);
+  static_assert(
+      std::is_same<typename std::shared_ptr<T[]>::element_type, T>::value, "");
+  static_assert(
+      std::is_same<typename std::shared_ptr<T[8]>::element_type, T>::value, "");
 #endif
+}
+
+int main(int, char**) {
+  test<A>();
+  test<B>();
+  test<int>();
+  test<char*>();
 
   return 0;
 }

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/const_pointer_cast.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/const_pointer_cast.pass.cpp
index e2bb126fd470..588a79f9b07f 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/const_pointer_cast.pass.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/const_pointer_cast.pass.cpp
@@ -55,6 +55,14 @@ int main(int, char**)
         assert(pB.get() == pA.get());
         assert(!pB.owner_before(pA) && !pA.owner_before(pB));
     }
+#if TEST_STD_VER > 14
+    {
+      const std::shared_ptr<const A[8]> pA;
+      std::shared_ptr<A[8]> pB = std::const_pointer_cast<A[8]>(pA);
+      assert(pB.get() == pA.get());
+      assert(!pB.owner_before(pA) && !pA.owner_before(pB));
+    }
+#endif // TEST_STD_VER > 14
 
-  return 0;
+    return 0;
 }

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/dynamic_pointer_cast.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/dynamic_pointer_cast.pass.cpp
index d6d5da1197ac..de268eb769b5 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/dynamic_pointer_cast.pass.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/dynamic_pointer_cast.pass.cpp
@@ -55,6 +55,14 @@ int main(int, char**)
         assert(pA.get() == 0);
         assert(pA.use_count() == 0);
     }
+#if TEST_STD_VER > 14
+    {
+      const std::shared_ptr<B[8]> pB(new B[8]);
+      std::shared_ptr<A[8]> pA = std::dynamic_pointer_cast<A[8]>(pB);
+      assert(pA.get() == 0);
+      assert(pA.use_count() == 0);
+    }
+#endif // TEST_STD_VER > 14
 
-  return 0;
+    return 0;
 }

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/reinterpret_pointer_cast.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/reinterpret_pointer_cast.pass.cpp
new file mode 100644
index 000000000000..221001f91c17
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/reinterpret_pointer_cast.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// shared_ptr
+
+// template<class T, class U>
+//     shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept;
+
+#include "test_macros.h"
+
+#include <memory>
+#include <type_traits>
+#include <cassert>
+
+struct A {
+  int x;
+};
+
+int main(int, char**) {
+  {
+    const std::shared_ptr<A> pA(new A);
+    std::shared_ptr<int> pi = std::reinterpret_pointer_cast<int>(pA);
+    std::shared_ptr<A> pA2 = std::reinterpret_pointer_cast<A>(pi);
+    assert(pA2.get() == pA.get());
+    assert(!pi.owner_before(pA) && !pA.owner_before(pi));
+  }
+  {
+    const std::shared_ptr<A> pA;
+    std::shared_ptr<int> pi = std::reinterpret_pointer_cast<int>(pA);
+    std::shared_ptr<A> pA2 = std::reinterpret_pointer_cast<A>(pi);
+    assert(pA2.get() == pA.get());
+    assert(!pi.owner_before(pA) && !pA.owner_before(pi));
+  }
+#if TEST_STD_VER > 14
+  {
+    const std::shared_ptr<A[8]> pA;
+    std::shared_ptr<int[8]> pi = std::reinterpret_pointer_cast<int[8]>(pA);
+    std::shared_ptr<A[8]> pA2 = std::reinterpret_pointer_cast<A[8]>(pi);
+    assert(pA2.get() == pA.get());
+    assert(!pi.owner_before(pA) && !pA.owner_before(pi));
+  }
+#endif // TEST_STD_VER > 14
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/static_pointer_cast.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/static_pointer_cast.pass.cpp
index 1fe674fa530e..8f8dadea0d48 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/static_pointer_cast.pass.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/static_pointer_cast.pass.cpp
@@ -67,6 +67,20 @@ int main(int, char**)
         assert(pB.get() == pA.get());
         assert(!pB.owner_before(pA) && !pA.owner_before(pB));
     }
+#if TEST_STD_VER > 14
+    {
+      const std::shared_ptr<A[8]> pA;
+      std::shared_ptr<B[8]> pB = std::static_pointer_cast<B[8]>(pA);
+      assert(pB.get() == pA.get());
+      assert(!pB.owner_before(pA) && !pA.owner_before(pB));
+    }
+    {
+      const std::shared_ptr<B[8]> pA;
+      std::shared_ptr<A[8]> pB = std::static_pointer_cast<A[8]>(pA);
+      assert(pB.get() == pA.get());
+      assert(!pB.owner_before(pA) && !pA.owner_before(pB));
+    }
+#endif // TEST_STD_VER > 14
 
-  return 0;
+    return 0;
 }

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/default.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/default.pass.cpp
index 17b346d3a13f..4efa18f63f52 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/default.pass.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/default.pass.cpp
@@ -15,11 +15,21 @@
 
 #include "test_macros.h"
 
-int main(int, char**)
-{
-    std::shared_ptr<int> p;
-    assert(p.use_count() == 0);
-    assert(p.get() == 0);
+struct A {};
+
+template <class T>
+void test() {
+  std::shared_ptr<T> p;
+  assert(p.use_count() == 0);
+  assert(p.get() == 0);
+}
+
+int main(int, char**) {
+  test<int>();
+  test<A>();
+  test<int*>();
+  test<int[]>();
+  test<int[8]>();
 
   return 0;
 }

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer.pass.cpp
index 6eceb552ec14..b055543336d5 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer.pass.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer.pass.cpp
@@ -45,5 +45,21 @@ int main(int, char**)
     }
     assert(A::count == 0);
 
-  return 0;
+#if TEST_STD_VER > 14
+    {
+      std::shared_ptr<A[8]> pA(new A[8]);
+      assert(pA.use_count() == 1);
+      assert(A::count == 8);
+    }
+    assert(A::count == 0);
+
+    {
+      std::shared_ptr<A[]> pA(new A[8]);
+      assert(pA.use_count() == 1);
+      assert(A::count == 8);
+    }
+    assert(A::count == 0);
+#endif
+
+    return 0;
 }

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_copy_move.fail.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_copy_move.fail.cpp
new file mode 100644
index 000000000000..41452fd1af12
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_copy_move.fail.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// shared_ptr
+
+// template<class Y> shared_ptr(const shared_ptr<Y>& r);
+
+#include <memory>
+#include <type_traits>
+
+struct A {
+  int x = 42;
+};
+
+struct ADel : std::default_delete<A> {
+  typedef A* pointer;
+};
+
+int main(int, char**) {
+  static_assert(!(std::is_convertible<A, int>::value), "");
+
+  {
+    std::shared_ptr<A> pA;
+    std::shared_ptr<int> pi(pA); // expected-error {{no matching constructor for initialization of 'std::shared_ptr<int>'}}
+  }
+  {
+    std::shared_ptr<A> pA;
+    std::shared_ptr<int> pi(std::move(pA)); // expected-error {{no matching constructor for initialization of 'std::shared_ptr<int>'}}
+  }
+  {
+    std::weak_ptr<A> pA;
+    std::shared_ptr<int> pi(std::move(pA)); // expected-error {{no matching constructor for initialization of 'std::shared_ptr<int>'}}
+  }
+
+#if TEST_STD_VER > 14
+  {
+    std::unique_ptr<int, ADel> ui;
+    std::shared_ptr<int> pi(std::move(ui)); // expected-error {{no matching constructor for initialization of 'std::shared_ptr<int>'}}
+  }
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_pointer.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_pointer.pass.cpp
index 3a600f8e30bb..d4a783a5bb48 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_pointer.pass.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_pointer.pass.cpp
@@ -44,6 +44,7 @@ int main(int, char**)
     {
         std::shared_ptr<A> pA(new A);
         assert(pA.use_count() == 1);
+
         {
             B b;
             std::shared_ptr<B> pB(pA, &b);
@@ -60,5 +61,38 @@ int main(int, char**)
     assert(A::count == 0);
     assert(B::count == 0);
 
-  return 0;
+    {
+      std::shared_ptr<int> p1(nullptr);
+      std::shared_ptr<int> p2(p1, new int);
+      assert(p2.get() != nullptr);
+    }
+    {
+      std::shared_ptr<int> p1(new int);
+      std::shared_ptr<int> p2(p1, nullptr);
+      assert(p2.get() == nullptr);
+    }
+
+#if TEST_STD_VER > 17
+    {
+      std::shared_ptr<A> pA(new A);
+      assert(pA.use_count() == 1);
+
+      {
+        B b;
+        std::shared_ptr<B> pB(std::move(pA), &b);
+        assert(A::count == 1);
+        assert(B::count == 1);
+        assert(pA.use_count() == 2);
+        assert(pB.use_count() == 2);
+        assert(pB.get() == &b);
+      }
+      assert(pA.use_count() == 1);
+      assert(A::count == 1);
+      assert(B::count == 0);
+    }
+    assert(A::count == 0);
+    assert(B::count == 0);
+#endif
+
+    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 91716fca0574..40b68f6a896b 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
@@ -56,6 +56,19 @@ struct D {
 void ref(D);
 }
 
+template <class T>
+struct StatefulDeleter {
+  int state = 0;
+
+  StatefulDeleter(int val = 0) : state(val) {}
+  StatefulDeleter(StatefulDeleter const&) { assert(false); }
+
+  void operator()(T* ptr) {
+    assert(state == 42);
+    delete ptr;
+  }
+};
+
 int main(int, char**)
 {
     {
@@ -90,11 +103,29 @@ int main(int, char**)
             assert(A::count == 0);
             assert(B::count == 0);
             assert(ptr.get() == 0);
-#endif
+#endif // TEST_STD_VER >= 11
         }
     }
 #endif
+
+#if TEST_STD_VER > 14
+    {
+      std::unique_ptr<int> ptr;
+      std::shared_ptr<int> p(std::move(ptr));
+      assert(p.get() == 0);
+      assert(p.use_count() == 0);
+    }
+#endif
+
+    {
+      StatefulDeleter<A> d;
+      std::unique_ptr<A, StatefulDeleter<A>&> u(new A, d);
+      std::shared_ptr<A> p(std::move(u));
+      d.state = 42;
+      assert(A::count == 1);
+    }
     assert(A::count == 0);
+
     { // LWG 2399
         fn(std::unique_ptr<int>(new int));
     }

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.protected.fail.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.protected.fail.cpp
index d708743814ea..75bb497fdab8 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.protected.fail.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.protected.fail.cpp
@@ -27,7 +27,8 @@ struct S {
 
 int main(int, char**)
 {
-    std::shared_ptr<S> p = std::make_shared<S>();  // expected-error-re at memory:* {{static_assert failed{{.*}} "Can't construct object in make_shared"}}
+  std::shared_ptr<S> p = std::make_shared<
+      S>(); // expected-error at memory:* {{static_assert failed due to requirement 'is_constructible<S>::value' "Can't construct object in make_shared"}}
 
   return 0;
 }

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_arrow.fail.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_arrow.fail.cpp
new file mode 100644
index 000000000000..c4ed32c293c3
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_arrow.fail.cpp
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// shared_ptr
+
+// element_type& operator[](ptr
diff _t i) const;
+
+#include "test_macros.h"
+
+#include <memory>
+#include <cassert>
+
+struct Foo {
+  void call() {}
+};
+
+int main(int, char**) {
+  // Check that we get a static assertion when we try to use the bracket
+  // operator on shared_ptr<T> when T is not an array type.
+  const std::shared_ptr<Foo[]> p1;
+  (void)p1
+      ->call(); // expected-error at memory:* {{std::shared_ptr<T>::operator-> is only valid when T is not an array type.}}
+  const std::shared_ptr<Foo[4]> p2;
+  (void)p2
+      ->call(); // expected-error at memory:* {{std::shared_ptr<T>::operator-> is only valid when T is not an array type.}}
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bool.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bool.pass.cpp
index 69b0ff3ed5c9..80162246d244 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bool.pass.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bool.pass.cpp
@@ -17,16 +17,27 @@
 
 #include "test_macros.h"
 
+struct A {
+  int a;
+  virtual ~A(){};
+};
+struct B : A {};
+
 int main(int, char**)
 {
     {
-    const std::shared_ptr<int> p(new int(32));
-    assert(p);
+      const std::shared_ptr<int> p(new int(32));
+      assert(p);
+    }
+    {
+      const std::shared_ptr<int> p;
+      assert(!p);
     }
     {
-    const std::shared_ptr<int> p;
-    assert(!p);
+      std::shared_ptr<A> basePtr = std::make_shared<B>();
+      std::shared_ptr<B> sp = std::dynamic_pointer_cast<B>(basePtr);
+      assert(sp);
     }
 
-  return 0;
+    return 0;
 }

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bracket.fail.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bracket.fail.cpp
new file mode 100644
index 000000000000..aef8ef75fcd2
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bracket.fail.cpp
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// shared_ptr
+
+// element_type& operator[](ptr
diff _t i) const;
+
+#include "test_macros.h"
+
+#include <memory>
+#include <cassert>
+
+int main(int, char**) {
+  // Check that we get a static assertion when we try to use the bracket
+  // operator on shared_ptr<T> when T is not an array type.
+  const std::shared_ptr<int> p;
+  (void)p
+      [0]; // expected-error at memory:* {{std::shared_ptr<T>::operator[] is only valid when T is an array type.}}
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bracket.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bracket.pass.cpp
new file mode 100644
index 000000000000..4a976fa296aa
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bracket.pass.cpp
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// shared_ptr
+
+// element_type& operator[](ptr
diff _t i) const;
+
+#include "test_macros.h"
+
+#include <memory>
+#include <cassert>
+
+int main(int, char**) {
+  {
+    const std::shared_ptr<int[8]> p(new int[8]);
+
+    for (int i = 0; i < 8; ++i)
+      p[i] = i;
+    for (int i = 0; i < 8; ++i)
+      assert(p[i] == i);
+  }
+  {
+    int* iptr = new int[8];
+    for (int i = 0; i < 8; ++i)
+      iptr[i] = i;
+
+    const std::shared_ptr<int[8]> p(iptr);
+
+    for (int i = 0; i < 8; ++i)
+      assert(p[i] == i);
+  }
+  {
+    const std::shared_ptr<int[]> p(new int[8]);
+
+    for (int i = 0; i < 8; ++i)
+      p[i] = i;
+    for (int i = 0; i < 8; ++i)
+      assert(p[i] == i);
+  }
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.assign/shared_ptr_Y.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.assign/shared_ptr_Y.pass.cpp
index 6d6f4e13556d..f899dc426251 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.assign/shared_ptr_Y.pass.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.assign/shared_ptr_Y.pass.cpp
@@ -45,6 +45,7 @@ int main(int, char**)
 {
     {
         const std::shared_ptr<A> pA(new A);
+        assert(pA.use_count() == 1);
         {
             std::weak_ptr<B> pB;
             pB = pA;

diff  --git a/libcxx/www/cxx1z_status.html b/libcxx/www/cxx1z_status.html
index 8f3f88310a74..83aedb96bdb7 100644
--- a/libcxx/www/cxx1z_status.html
+++ b/libcxx/www/cxx1z_status.html
@@ -128,7 +128,7 @@ <h3>Paper Status</h3>
 	<tr><td><a href="https://wg21.link/P0003R5">P0003R5</a></td><td>LWG</td><td>Removing Deprecated Exception Specifications from C++17</td><td>Issaquah</td><td>Complete</td><td>5.0</td></tr>
 	<tr><td><a href="https://wg21.link/P0067R5">P0067R5</a></td><td>LWG</td><td>Elementary string conversions, revision 5</td><td>Issaquah</td><td><i>Partially done</i></td><td></td></tr>
 	<tr><td><a href="https://wg21.link/P0403R1">P0403R1</a></td><td>LWG</td><td>Literal suffixes for <tt>basic_string_view</tt></td><td>Issaquah</td><td>Complete</td><td>4.0</td></tr>
-	<tr><td><a href="https://wg21.link/P0414R2">P0414R2</a></td><td>LWG</td><td>Merging shared_ptr changes from Library Fundamentals to C++17</td><td>Issaquah</td><td></td><td></td></tr>
+	<tr><td><a href="https://wg21.link/P0414R2">P0414R2</a></td><td>LWG</td><td>Merging shared_ptr changes from Library Fundamentals to C++17</td><td>Issaquah</td><td>Complete</td><td>11.0</td></tr>
 	<tr><td><a href="https://wg21.link/P0418R2">P0418R2</a></td><td>LWG</td><td>Fail or succeed: there is no atomic lattice</td><td>Issaquah</td><td></td><td></td></tr>
 	<tr><td><a href="https://wg21.link/P0426R1">P0426R1</a></td><td>LWG</td><td>Constexpr for <tt>std::char_traits</tt></td><td>Issaquah</td><td>Complete</td><td>4.0</td></tr>
 	<tr><td><a href="https://wg21.link/P0435R1">P0435R1</a></td><td>LWG</td><td>Resolving LWG Issues re <tt>common_type</tt></td><td>Issaquah</td><td>Complete</td><td>4.0</td></tr>


        


More information about the libcxx-commits mailing list