diff --git a/libcxx/include/memory b/libcxx/include/memory --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -3702,15 +3702,25 @@ template class _LIBCPP_TEMPLATE_VIS enable_shared_from_this; +template +struct __compatible_with +#if _LIBCPP_STD_VER > 14 + : is_convertible*, remove_extent_t<_Up>*> {}; +#else + : is_convertible<_Tp*, _Up*> {}; +#endif // _LIBCPP_STD_VER > 14 + template 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 @@ _LIBCPP_CONSTEXPR shared_ptr(nullptr_t) _NOEXCEPT; template explicit shared_ptr(_Yp* __p, - typename enable_if::value, __nat>::type = __nat()); + typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()); template shared_ptr(_Yp* __p, _Dp __d, - typename enable_if::value, __nat>::type = __nat()); + typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()); template shared_ptr(_Yp* __p, _Dp __d, _Alloc __a, - typename enable_if::value, __nat>::type = __nat()); + typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()); template shared_ptr(nullptr_t __p, _Dp __d); template shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a); template _LIBCPP_INLINE_VISIBILITY shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) _NOEXCEPT; @@ -3738,13 +3748,13 @@ template _LIBCPP_INLINE_VISIBILITY shared_ptr(const shared_ptr<_Yp>& __r, - typename enable_if::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 _LIBCPP_INLINE_VISIBILITY shared_ptr(shared_ptr<_Yp>&& __r, - typename enable_if::value, __nat>::type = __nat()) + typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()) _NOEXCEPT; #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template explicit shared_ptr(const weak_ptr<_Yp>& __r, @@ -3807,7 +3817,7 @@ template 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 @@ template 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 @@ template typename enable_if < - is_convertible<_Yp*, element_type*>::value, + __compatible_with<_Yp, element_type>::value, void >::type _LIBCPP_INLINE_VISIBILITY @@ -3877,7 +3887,7 @@ template typename enable_if < - is_convertible<_Yp*, element_type*>::value, + __compatible_with<_Yp, element_type>::value, void >::type _LIBCPP_INLINE_VISIBILITY @@ -3885,7 +3895,7 @@ template typename enable_if < - is_convertible<_Yp*, element_type*>::value, + __compatible_with<_Yp, element_type>::value, void >::type _LIBCPP_INLINE_VISIBILITY @@ -3897,7 +3907,12 @@ typename add_lvalue_reference::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::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 @@ __owner_equivalent(const shared_ptr& __p) const {return __cntrl_ == __p.__cntrl_;} +#if _LIBCPP_STD_VER > 14 + typename add_lvalue_reference::type + _LIBCPP_INLINE_VISIBILITY + operator[](ptrdiff_t __i) const + { + static_assert(_VSTD::is_array<_Tp>::value, + "std::shared_ptr::operator[] is only valid when T is an array type."); + return __ptr_[__i]; + } +#endif + #ifndef _LIBCPP_NO_RTTI template _LIBCPP_INLINE_VISIBILITY @@ -3969,6 +3995,18 @@ _LIBCPP_INLINE_VISIBILITY void __enable_weak_this(...) _NOEXCEPT {} + template + struct __shared_ptr_default_delete + : default_delete<_Yp> {}; + + template + struct __shared_ptr_default_delete<_Yp[_Sz], _Un> + : default_delete<_Yp[]> {}; + + template + struct __shared_ptr_default_delete<_Yp[], _Un> + : default_delete<_Yp[]> {}; + template friend class _LIBCPP_TEMPLATE_VIS shared_ptr; template friend class _LIBCPP_TEMPLATE_VIS weak_ptr; }; @@ -4001,13 +4039,13 @@ template template shared_ptr<_Tp>::shared_ptr(_Yp* __p, - typename enable_if::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 @@ template template shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d, - typename enable_if::value, __nat>::type) + typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type) : __ptr_(__p) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -4061,7 +4099,7 @@ template template shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d, _Alloc __a, - typename enable_if::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 inline shared_ptr<_Tp>::shared_ptr(const shared_ptr<_Yp>& __r, - typename enable_if::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 inline shared_ptr<_Tp>::shared_ptr(shared_ptr<_Yp>&& __r, - typename enable_if::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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ template 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 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 -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 +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 @@ -5080,7 +5118,7 @@ _LIBCPP_INLINE_VISIBILITY result_type operator()(const argument_type& __ptr) const _NOEXCEPT { - return hash<_Tp*>()(__ptr.get()); + return hash::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 --- 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 > +struct has_less : std::false_type {}; + +template +struct has_less() < std::declval())> > + : std::true_type {}; +#endif + struct A; // purposefully incomplete +struct B { + int x; + B() = default; +}; -int main(int, char**) -{ - static_assert((std::is_same::element_type, A>::value), ""); +template +void test() { + ASSERT_SAME_TYPE(typename std::shared_ptr::element_type, T); #if TEST_STD_VER > 14 - static_assert((std::is_same::weak_type, std::weak_ptr>::value), ""); + ASSERT_SAME_TYPE(typename std::shared_ptr::weak_type, std::weak_ptr); + static_assert(std::is_copy_constructible >::value, ""); + static_assert(std::is_copy_assignable >::value, ""); + static_assert(has_less >::value); + static_assert( + std::is_same::element_type, T>::value, ""); + static_assert( + std::is_same::element_type, T>::value, ""); #endif +} + +int main(int, char**) { + test(); + test(); + test(); + test(); 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 --- 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 @@ assert(pB.get() == pA.get()); assert(!pB.owner_before(pA) && !pA.owner_before(pB)); } +#if TEST_STD_VER > 14 + { + const std::shared_ptr pA; + std::shared_ptr pB = std::const_pointer_cast(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 --- 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 @@ assert(pA.get() == 0); assert(pA.use_count() == 0); } +#if TEST_STD_VER > 14 + { + const std::shared_ptr pB(new B[8]); + std::shared_ptr pA = std::dynamic_pointer_cast(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 --- /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 +// +//===----------------------------------------------------------------------===// + +// + +// shared_ptr + +// template +// shared_ptr reinterpret_pointer_cast(const shared_ptr& r) noexcept; + +#include "test_macros.h" + +#include +#include +#include + +struct A { + int x; +}; + +int main(int, char**) { + { + const std::shared_ptr pA(new A); + std::shared_ptr pi = std::reinterpret_pointer_cast(pA); + std::shared_ptr pA2 = std::reinterpret_pointer_cast(pi); + assert(pA2.get() == pA.get()); + assert(!pi.owner_before(pA) && !pA.owner_before(pi)); + } + { + const std::shared_ptr pA; + std::shared_ptr pi = std::reinterpret_pointer_cast(pA); + std::shared_ptr pA2 = std::reinterpret_pointer_cast(pi); + assert(pA2.get() == pA.get()); + assert(!pi.owner_before(pA) && !pA.owner_before(pi)); + } +#if TEST_STD_VER > 14 + { + const std::shared_ptr pA; + std::shared_ptr pi = std::reinterpret_pointer_cast(pA); + std::shared_ptr pA2 = std::reinterpret_pointer_cast(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 --- 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 @@ assert(pB.get() == pA.get()); assert(!pB.owner_before(pA) && !pA.owner_before(pB)); } +#if TEST_STD_VER > 14 + { + const std::shared_ptr pA; + std::shared_ptr pB = std::static_pointer_cast(pA); + assert(pB.get() == pA.get()); + assert(!pB.owner_before(pA) && !pA.owner_before(pB)); + } + { + const std::shared_ptr pA; + std::shared_ptr pB = std::static_pointer_cast(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 --- 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 p; - assert(p.use_count() == 0); - assert(p.get() == 0); +struct A {}; + +template +void test() { + std::shared_ptr p; + assert(p.use_count() == 0); + assert(p.get() == 0); +} + +int main(int, char**) { + test(); + test(); + test(); + test(); + test(); 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 --- 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 @@ } assert(A::count == 0); - return 0; +#if TEST_STD_VER > 14 + { + std::shared_ptr pA(new A[8]); + assert(pA.use_count() == 1); + assert(A::count == 8); + } + assert(A::count == 0); + + { + std::shared_ptr 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 --- /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 +// +//===----------------------------------------------------------------------===// + +// + +// shared_ptr + +// template shared_ptr(const shared_ptr& r); + +#include +#include + +struct A { + int x = 42; +}; + +struct ADel : std::default_delete { + typedef A* pointer; +}; + +int main(int, char**) { + static_assert(!(std::is_convertible::value), ""); + + { + std::shared_ptr pA; + std::shared_ptr pi(pA); // expected-error {{no matching constructor for initialization of 'std::shared_ptr'}} + } + { + std::shared_ptr pA; + std::shared_ptr pi(std::move(pA)); // expected-error {{no matching constructor for initialization of 'std::shared_ptr'}} + } + { + std::weak_ptr pA; + std::shared_ptr pi(std::move(pA)); // expected-error {{no matching constructor for initialization of 'std::shared_ptr'}} + } + +#if TEST_STD_VER > 14 + { + std::unique_ptr ui; + std::shared_ptr pi(std::move(ui)); // expected-error {{no matching constructor for initialization of 'std::shared_ptr'}} + } +#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 --- 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 @@ { std::shared_ptr pA(new A); assert(pA.use_count() == 1); + { B b; std::shared_ptr pB(pA, &b); @@ -60,5 +61,38 @@ assert(A::count == 0); assert(B::count == 0); - return 0; + { + std::shared_ptr p1(nullptr); + std::shared_ptr p2(p1, new int); + assert(p2.get() != nullptr); + } + { + std::shared_ptr p1(new int); + std::shared_ptr p2(p1, nullptr); + assert(p2.get() == nullptr); + } + +#if TEST_STD_VER > 17 + { + std::shared_ptr pA(new A); + assert(pA.use_count() == 1); + + { + B b; + std::shared_ptr 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 --- 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 @@ void ref(D); } +template +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 @@ 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 ptr; + std::shared_ptr p(std::move(ptr)); + assert(p.get() == 0); + assert(p.use_count() == 0); + } +#endif + + { + StatefulDeleter d; + std::unique_ptr&> u(new A, d); + std::shared_ptr p(std::move(u)); + d.state = 42; + assert(A::count == 1); + } assert(A::count == 0); + { // LWG 2399 fn(std::unique_ptr(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 --- 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 @@ int main(int, char**) { - std::shared_ptr p = std::make_shared(); // expected-error-re@memory:* {{static_assert failed{{.*}} "Can't construct object in make_shared"}} + std::shared_ptr p = std::make_shared< + S>(); // expected-error@memory:* {{static_assert failed due to requirement 'is_constructible::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 --- /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 +// +//===----------------------------------------------------------------------===// + +// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// shared_ptr + +// element_type& operator[](ptrdiff_t i) const; + +#include "test_macros.h" + +#include +#include + +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 when T is not an array type. + const std::shared_ptr p1; + (void)p1 + ->call(); // expected-error@memory:* {{std::shared_ptr::operator-> is only valid when T is not an array type.}} + const std::shared_ptr p2; + (void)p2 + ->call(); // expected-error@memory:* {{std::shared_ptr::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 --- 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 p(new int(32)); - assert(p); + const std::shared_ptr p(new int(32)); + assert(p); + } + { + const std::shared_ptr p; + assert(!p); } { - const std::shared_ptr p; - assert(!p); + std::shared_ptr basePtr = std::make_shared(); + std::shared_ptr sp = std::dynamic_pointer_cast(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_bool.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bracket.fail.cpp copy from libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bool.pass.cpp copy to libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bracket.fail.cpp --- 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_bracket.fail.cpp @@ -8,25 +8,22 @@ // -// shared_ptr +// UNSUPPORTED: c++98, c++03, c++11, c++14 -// explicit operator bool() const; +// shared_ptr -#include -#include +// element_type& operator[](ptrdiff_t i) const; #include "test_macros.h" -int main(int, char**) -{ - { - const std::shared_ptr p(new int(32)); - assert(p); - } - { - const std::shared_ptr p; - assert(!p); - } +#include +#include +int main(int, char**) { + // Check that we get a static assertion when we try to use the bracket + // operator on shared_ptr when T is not an array type. + const std::shared_ptr p; + (void)p + [0]; // expected-error@memory:* {{std::shared_ptr::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 --- /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 +// +//===----------------------------------------------------------------------===// + +// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// shared_ptr + +// element_type& operator[](ptrdiff_t i) const; + +#include "test_macros.h" + +#include +#include + +int main(int, char**) { + { + const std::shared_ptr 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 p(iptr); + + for (int i = 0; i < 8; ++i) + assert(p[i] == i); + } + { + const std::shared_ptr 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 --- 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 @@ { { const std::shared_ptr pA(new A); + assert(pA.use_count() == 1); { std::weak_ptr pB; pB = pA; diff --git a/libcxx/www/cxx1z_status.html b/libcxx/www/cxx1z_status.html --- a/libcxx/www/cxx1z_status.html +++ b/libcxx/www/cxx1z_status.html @@ -128,7 +128,7 @@ P0003R5LWGRemoving Deprecated Exception Specifications from C++17IssaquahComplete5.0 P0067R5LWGElementary string conversions, revision 5IssaquahPartially done P0403R1LWGLiteral suffixes for basic_string_viewIssaquahComplete4.0 - P0414R2LWGMerging shared_ptr changes from Library Fundamentals to C++17Issaquah + P0414R2LWGMerging shared_ptr changes from Library Fundamentals to C++17IssaquahComplete11.0 P0418R2LWGFail or succeed: there is no atomic latticeIssaquah P0426R1LWGConstexpr for std::char_traitsIssaquahComplete4.0 P0435R1LWGResolving LWG Issues re common_typeIssaquahComplete4.0