diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h index 1c99686c4e5f3..b4798c6b31cff 100644 --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -367,13 +367,57 @@ class _LIBCPP_TEMPLATE_VIS allocator<__shared_ptr_dummy_rebind_allocator_type> template class _LIBCPP_TEMPLATE_VIS enable_shared_from_this; -template +// http://eel.is/c++draft/util.sharedptr#util.smartptr.shared.general-6 +// A pointer type Y* is said to be compatible with a pointer type T* +// when either Y* is convertible to T* or Y is U[N] and T is cv U[]. +#if _LIBCPP_STD_VER >= 17 +template +struct __bounded_convertible_to_unbounded : false_type {}; + +template +struct __bounded_convertible_to_unbounded<_Up[_Np], _Tp> + : is_same<__remove_cv_t<_Tp>, _Up[]> {}; + +template struct __compatible_with -#if _LIBCPP_STD_VER > 14 - : is_convertible*, remove_extent_t<_Up>*> {}; + : _Or< + is_convertible<_Yp*, _Tp*>, + __bounded_convertible_to_unbounded<_Yp, _Tp> + > {}; #else - : is_convertible<_Tp*, _Up*> {}; -#endif // _LIBCPP_STD_VER > 14 +template +struct __compatible_with + : is_convertible<_Yp*, _Tp*> {}; +#endif // _LIBCPP_STD_VER >= 17 + +// Constructors that take raw pointers have a different set of "compatible" constraints +// http://eel.is/c++draft/util.sharedptr#util.smartptr.shared.const-9.1 +// - If T is an array type, then either T is U[N] and Y(*)[N] is convertible to T*, +// or T is U[] and Y(*)[] is convertible to T*. +// - If T is not an array type, then Y* is convertible to T*. +#if _LIBCPP_STD_VER >= 17 +template +struct __raw_pointer_compatible_with : _And< + _Not>, + is_convertible<_Yp*, _Tp*> + > {}; + +template +struct __raw_pointer_compatible_with<_Yp, _Up[_Np], __enable_if_t< + is_convertible<_Yp(*)[_Np], _Up(*)[_Np]>::value> > + : true_type {}; + +template +struct __raw_pointer_compatible_with<_Yp, _Up[], __enable_if_t< + is_convertible<_Yp(*)[], _Up(*)[]>::value> > + : true_type {}; + +#else +template +struct __raw_pointer_compatible_with + : is_convertible<_Yp*, _Tp*> {}; +#endif // _LIBCPP_STD_VER >= 17 + template struct __is_deletable : false_type { }; @@ -395,12 +439,12 @@ static false_type __well_formed_deleter_test(...); template struct __well_formed_deleter : decltype(std::__well_formed_deleter_test<_Dp, _Pt>(0)) {}; -template +template struct __shared_ptr_deleter_ctor_reqs { - static const bool value = __compatible_with<_Tp, _Yp>::value && + static const bool value = __raw_pointer_compatible_with<_Yp, _Tp>::value && is_move_constructible<_Dp>::value && - __well_formed_deleter<_Dp, _Tp*>::value; + __well_formed_deleter<_Dp, _Yp*>::value; }; #if defined(_LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI) @@ -439,7 +483,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr template + __raw_pointer_compatible_with<_Yp, _Tp> // In C++03 we get errors when trying to do SFINAE with the // delete operator, so we always pretend that it's deletable. // The same happens on GCC. @@ -457,7 +501,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr __enable_weak_this(__p, __p); } - template::value> > + template::value> > _LIBCPP_HIDE_FROM_ABI shared_ptr(_Yp* __p, _Dp __d) : __ptr_(__p) @@ -484,7 +528,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr #endif // _LIBCPP_NO_EXCEPTIONS } - template::value> > + template::value> > _LIBCPP_HIDE_FROM_ABI shared_ptr(_Yp* __p, _Dp __d, _Alloc __a) : __ptr_(__p) @@ -646,6 +690,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr template ::value && + __compatible_with<_Yp, _Tp>::value && is_convertible::pointer, element_type*>::value > > _LIBCPP_HIDE_FROM_ABI @@ -668,6 +713,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr template ::value && + __compatible_with<_Yp, _Tp>::value && is_convertible::pointer, element_type*>::value > > _LIBCPP_HIDE_FROM_ABI @@ -740,9 +786,10 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr } #endif - template ::pointer, element_type*>::value - > > + template , + is_convertible::pointer, element_type*> + >::value> > _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp>& operator=(unique_ptr<_Yp, _Dp>&& __r) { @@ -764,7 +811,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr } template::value + __raw_pointer_compatible_with<_Yp, _Tp>::value > > _LIBCPP_HIDE_FROM_ABI void reset(_Yp* __p) @@ -773,8 +820,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr } template::value - > > + __shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> > _LIBCPP_HIDE_FROM_ABI void reset(_Yp* __p, _Dp __d) { @@ -782,8 +828,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr } template::value - > > + __shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> > _LIBCPP_HIDE_FROM_ABI void reset(_Yp* __p, _Dp __d, _Alloc __a) { 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 35671c41842f2..b5abcb6f04ceb 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 @@ -55,6 +55,16 @@ struct StatefulArrayDeleter { } }; +// https://llvm.org/PR53368 +// Bogus unique_ptr-to-shared_ptr conversions should be forbidden +#if TEST_STD_VER >= 17 +static_assert( std::is_assignable&, std::unique_ptr&&>::value, ""); +static_assert( std::is_assignable&, std::unique_ptr&&>::value, ""); +static_assert(!std::is_assignable&, std::unique_ptr&&>::value, ""); +static_assert(!std::is_assignable&, std::unique_ptr&&>::value, ""); +static_assert(!std::is_assignable&, std::unique_ptr&&>::value, ""); +#endif + int main(int, char**) { { @@ -126,40 +136,6 @@ int main(int, char**) assert(B::count == 0); assert(A::count == 0); -#ifdef _LIBCPP_VERSION // https://llvm.org/PR53368 - { - std::unique_ptr ptr(new A[8]); - A* raw_ptr = ptr.get(); - std::shared_ptr 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 ptr(new A[8]); - A* raw_ptr = ptr.get(); - std::shared_ptr 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 ptr(new int[8]); - std::shared_ptr p; - p = std::move(ptr); - } -#endif // _LIBCPP_VERSION - #if TEST_STD_VER > 14 { StatefulArrayDeleter d; @@ -172,22 +148,6 @@ int main(int, char**) assert(A::count == 0); assert(B::count == 0); -#ifdef _LIBCPP_VERSION // https://llvm.org/PR53368 - { - std::unique_ptr ptr(new A[8]); - A* raw_ptr = ptr.get(); - std::shared_ptr 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); -#endif // _LIBCPP_VERSION - { std::unique_ptr ptr(new A[8]); A* raw_ptr = ptr.get(); 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 ef3270efc8253..87b0cbde14a35 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 @@ -10,8 +10,9 @@ // template explicit shared_ptr(Y* p); -#include #include +#include +#include #include "test_macros.h" @@ -26,6 +27,25 @@ struct A int A::count = 0; +struct Derived : A {}; + +// https://llvm.org/PR60258 +// Invalid constructor SFINAE for std::shared_ptr's array ctors +static_assert( std::is_constructible, int*>::value, ""); +static_assert( std::is_constructible, Derived*>::value, ""); +static_assert(!std::is_constructible, int*>::value, ""); + +#if TEST_STD_VER >= 17 +static_assert( std::is_constructible, int*>::value, ""); +static_assert(!std::is_constructible, int(*)[]>::value, ""); +static_assert( std::is_constructible, int*>::value, ""); +static_assert(!std::is_constructible, int(*)[5]>::value, ""); +#endif + +// Test explicit +static_assert(std::is_constructible, int*>::value, ""); +static_assert(!std::is_convertible >::value, ""); + int main(int, char**) { { @@ -71,11 +91,18 @@ int main(int, char**) } { - assert(A::count == 0); + assert(A::count == 0); 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 Derived); + assert(pA.use_count() == 1); + assert(A::count == 1); + } #endif return 0; diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter.pass.cpp index b3580e25fe52c..463130789416e 100644 --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter.pass.cpp @@ -60,6 +60,22 @@ class MoveDeleter void operator()(T *ptr) { delete ptr; } }; +// https://llvm.org/PR60258 +// Invalid constructor SFINAE for std::shared_ptr's array ctors +static_assert( std::is_constructible, int*, test_deleter >::value, ""); +static_assert(!std::is_constructible, int*, bad_deleter>::value, ""); +static_assert( std::is_constructible, Derived*, test_deleter >::value, ""); +static_assert(!std::is_constructible, int*, test_deleter >::value, ""); + +#if TEST_STD_VER >= 17 +static_assert( std::is_constructible, int*, test_deleter>::value, ""); +static_assert(!std::is_constructible, int*, bad_deleter>::value, ""); +static_assert(!std::is_constructible, int(*)[], test_deleter>::value, ""); +static_assert( std::is_constructible, int*, test_deleter>::value, ""); +static_assert(!std::is_constructible, int*, bad_deleter>::value, ""); +static_assert(!std::is_constructible, int(*)[5], test_deleter>::value, ""); +#endif + int main(int, char**) { { diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator.pass.cpp index 2fc25282230c8..6d66e05e426b4 100644 --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator.pass.cpp @@ -60,6 +60,23 @@ class MoveDeleter void operator()(T *ptr) { delete ptr; } }; +// https://llvm.org/PR60258 +// Invalid constructor SFINAE for std::shared_ptr's array ctors +static_assert( std::is_constructible, int*, test_deleter, test_allocator >::value, ""); +static_assert(!std::is_constructible, int*, bad_deleter, test_allocator >::value, ""); +static_assert( std::is_constructible, Derived*, test_deleter, test_allocator >::value, ""); +static_assert(!std::is_constructible, int*, test_deleter, test_allocator >::value, ""); + +#if TEST_STD_VER >= 17 +static_assert( std::is_constructible, int*, test_deleter, test_allocator>::value, ""); +static_assert(!std::is_constructible, int*, bad_deleter, test_allocator>::value, ""); +static_assert(!std::is_constructible, int(*)[], test_deleter, test_allocator>::value, ""); +static_assert( std::is_constructible, int*, test_deleter, test_allocator>::value, ""); +static_assert(!std::is_constructible, int*, bad_deleter, test_allocator>::value, ""); +static_assert(!std::is_constructible, int(*)[5], test_deleter, test_allocator>::value, ""); +#endif + + int main(int, char**) { { diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_Y.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_Y.pass.cpp index 26f381c9a2892..06817302446e8 100644 --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_Y.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_Y.pass.cpp @@ -74,6 +74,23 @@ class private_delete_arr_op } }; +// https://llvm.org/PR60258 +// Invalid constructor SFINAE for std::shared_ptr's array ctors +static_assert(!std::is_constructible, const std::shared_ptr&>::value, ""); +static_assert( std::is_constructible, const std::shared_ptr&>::value, ""); +static_assert( std::is_constructible, const std::shared_ptr&>::value, ""); +static_assert(!std::is_constructible, const std::shared_ptr&>::value, ""); + +#if TEST_STD_VER >= 17 +static_assert(!std::is_constructible, const std::shared_ptr&>::value, ""); +static_assert(!std::is_constructible, const std::shared_ptr&>::value, ""); +static_assert(!std::is_constructible, const std::shared_ptr&>::value, ""); +static_assert( std::is_constructible, const std::shared_ptr&>::value, ""); +static_assert(!std::is_constructible, const std::shared_ptr&>::value, ""); +static_assert(!std::is_constructible, const std::shared_ptr&>::value, ""); +static_assert(!std::is_constructible, const std::shared_ptr&>::value, ""); +#endif + int main(int, char**) { static_assert(( std::is_convertible, std::shared_ptr >::value), ""); diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_Y_rv.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_Y_rv.pass.cpp index 84ec26eb140ee..10ccbc4e7adea 100644 --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_Y_rv.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/shared_ptr_Y_rv.pass.cpp @@ -55,6 +55,23 @@ struct C int C::count = 0; +// https://llvm.org/PR60258 +// Invalid constructor SFINAE for std::shared_ptr's array ctors +static_assert(!std::is_constructible, std::shared_ptr&&>::value, ""); +static_assert( std::is_constructible, std::shared_ptr&&>::value, ""); +static_assert( std::is_constructible, std::shared_ptr&&>::value, ""); +static_assert(!std::is_constructible, std::shared_ptr&&>::value, ""); + +#if TEST_STD_VER >= 17 +static_assert(!std::is_constructible, std::shared_ptr&&>::value, ""); +static_assert(!std::is_constructible, std::shared_ptr&&>::value, ""); +static_assert(!std::is_constructible, std::shared_ptr&&>::value, ""); +static_assert( std::is_constructible, std::shared_ptr&&>::value, ""); +static_assert(!std::is_constructible, std::shared_ptr&&>::value, ""); +static_assert(!std::is_constructible, std::shared_ptr&&>::value, ""); +static_assert(!std::is_constructible, std::shared_ptr&&>::value, ""); +#endif + int main(int, char**) { static_assert(( std::is_convertible, std::shared_ptr >::value), ""); 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 871aac6eae0f6..9308bb3858c65 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 @@ -90,6 +90,16 @@ struct MovingDeleter { int *moves_; }; +// https://llvm.org/PR53368 +// Bogus unique_ptr-to-shared_ptr conversions should be forbidden +#if TEST_STD_VER >= 17 +static_assert( std::is_constructible, std::unique_ptr&&>::value, ""); +static_assert( std::is_constructible, std::unique_ptr&&>::value, ""); +static_assert(!std::is_constructible, std::unique_ptr&&>::value, ""); +static_assert(!std::is_constructible, std::unique_ptr&&>::value, ""); +static_assert(!std::is_constructible, std::unique_ptr&&>::value, ""); +#endif + int main(int, char**) { { @@ -169,36 +179,6 @@ int main(int, char**) } assert(A::count == 0); -#ifdef _LIBCPP_VERSION // https://llvm.org/PR53368 - { - std::unique_ptr ptr(new A[8]); - A* raw_ptr = ptr.get(); - std::shared_ptr 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 ptr(new A[8]); - A* raw_ptr = ptr.get(); - std::shared_ptr 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 ptr(new int[8]); - std::shared_ptr p(std::move(ptr)); - } -#endif // _LIBCPP_VERSION #if TEST_STD_VER > 14 { @@ -211,21 +191,6 @@ int main(int, char**) assert(A::count == 0); assert(B::count == 0); -#ifdef _LIBCPP_VERSION // https://llvm.org/PR53368 - { - std::unique_ptr ptr(new A[8]); - A* raw_ptr = ptr.get(); - std::shared_ptr 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); -#endif // _LIBCPP_VERSION - { std::unique_ptr ptr(new A[8]); A* raw_ptr = ptr.get(); diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/weak_ptr.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/weak_ptr.pass.cpp index 57d7cc58ef68c..f59181343b910 100644 --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/weak_ptr.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/weak_ptr.pass.cpp @@ -12,8 +12,9 @@ // template explicit shared_ptr(const weak_ptr& r); -#include #include +#include +#include #include "test_macros.h" @@ -40,6 +41,23 @@ struct A int A::count = 0; +// https://llvm.org/PR60258 +// Invalid constructor SFINAE for std::shared_ptr's array ctors +static_assert(!std::is_constructible, const std::weak_ptr&>::value, ""); +static_assert( std::is_constructible, const std::weak_ptr&>::value, ""); +static_assert( std::is_constructible, const std::weak_ptr&>::value, ""); +static_assert(!std::is_constructible, const std::weak_ptr&>::value, ""); + +#if TEST_STD_VER >= 17 +static_assert(!std::is_constructible, const std::weak_ptr&>::value, ""); +static_assert(!std::is_constructible, const std::weak_ptr&>::value, ""); +static_assert(!std::is_constructible, const std::weak_ptr&>::value, ""); +static_assert( std::is_constructible, const std::weak_ptr&>::value, ""); +static_assert(!std::is_constructible, const std::weak_ptr&>::value, ""); +static_assert(!std::is_constructible, const std::weak_ptr&>::value, ""); +static_assert(!std::is_constructible, const std::weak_ptr&>::value, ""); +#endif + int main(int, char**) { #ifndef TEST_HAS_NO_EXCEPTIONS diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_helper.h b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_helper.h new file mode 100644 index 0000000000000..27d7264be172e --- /dev/null +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_helper.h @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +#ifndef TEST_STD_SHARED_PTR_RESET_H +#define TEST_STD_SHARED_PTR_RESET_H + +#include +#include + +template +std::false_type test_has_reset(...); + +template +typename std::enable_if().reset(std::declval()...)), void>::value, + std::true_type>::type +test_has_reset(int); + +template +using HasReset = decltype(test_has_reset(0)); + +#endif // TEST_STD_SHARED_PTR_RESET_H diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_pointer.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_pointer.pass.cpp index d764e8a312d7a..d1d19e4562355 100644 --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_pointer.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_pointer.pass.cpp @@ -15,6 +15,7 @@ #include #include +#include "reset_helper.h" #include "test_macros.h" struct B @@ -40,6 +41,19 @@ struct A int A::count = 0; +struct Derived : A {}; + +static_assert( HasReset, int*>::value, ""); +static_assert( HasReset, Derived*>::value, ""); +static_assert(!HasReset, int*>::value, ""); + +#if TEST_STD_VER >= 17 +static_assert( HasReset, int*>::value, ""); +static_assert(!HasReset, int(*)[]>::value, ""); +static_assert( HasReset, int*>::value, ""); +static_assert(!HasReset, int(*)[5]>::value, ""); +#endif + int main(int, char**) { { diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_pointer_deleter.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_pointer_deleter.pass.cpp index 14c336b4f59ca..d0375d3aa2001 100644 --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_pointer_deleter.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_pointer_deleter.pass.cpp @@ -12,10 +12,11 @@ // template void reset(Y* p, D d); -#include #include -#include "test_macros.h" +#include #include "deleter_types.h" +#include "reset_helper.h" +#include "test_macros.h" struct B { @@ -40,6 +41,29 @@ struct A int A::count = 0; +struct bad_ty { }; +struct bad_deleter +{ + void operator()(bad_ty) { } +}; + +struct Base { }; +struct Derived : Base { }; + +static_assert( HasReset, int*, test_deleter >::value, ""); +static_assert(!HasReset, int*, bad_deleter>::value, ""); +static_assert( HasReset, Derived*, test_deleter >::value, ""); +static_assert(!HasReset, int*, test_deleter >::value, ""); + +#if TEST_STD_VER >= 17 +static_assert( HasReset, int*, test_deleter>::value, ""); +static_assert(!HasReset, int*, bad_deleter>::value, ""); +static_assert(!HasReset, int(*)[], test_deleter>::value, ""); +static_assert( HasReset, int*, test_deleter>::value, ""); +static_assert(!HasReset, int*, bad_deleter>::value, ""); +static_assert(!HasReset, int(*)[5], test_deleter>::value, ""); +#endif + int main(int, char**) { { diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_pointer_deleter_allocator.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_pointer_deleter_allocator.pass.cpp index a6ea07ea37cee..1cd42c08a23ff 100644 --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_pointer_deleter_allocator.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_pointer_deleter_allocator.pass.cpp @@ -12,10 +12,11 @@ // template void reset(Y* p, D d, A a); -#include #include +#include #include "test_macros.h" #include "deleter_types.h" +#include "reset_helper.h" #include "test_allocator.h" struct B @@ -41,6 +42,30 @@ struct A int A::count = 0; +struct bad_ty { }; + +struct bad_deleter +{ + void operator()(bad_ty) { } +}; + +struct Base { }; +struct Derived : Base { }; + +static_assert( HasReset, int*, test_deleter, test_allocator >::value, ""); +static_assert(!HasReset, int*, bad_deleter, test_allocator >::value, ""); +static_assert( HasReset, Derived*, test_deleter, test_allocator >::value, ""); +static_assert(!HasReset, int*, test_deleter, test_allocator >::value, ""); + +#if TEST_STD_VER >= 17 +static_assert( HasReset, int*, test_deleter, test_allocator>::value, ""); +static_assert(!HasReset, int*, bad_deleter, test_allocator>::value, ""); +static_assert(!HasReset, int(*)[], test_deleter, test_allocator>::value, ""); +static_assert( HasReset, int*, test_deleter, test_allocator>::value, ""); +static_assert(!HasReset, int*, bad_deleter, test_allocator>::value, ""); +static_assert(!HasReset, int(*)[5], test_deleter, test_allocator>::value, ""); +#endif + int main(int, char**) { test_allocator_statistics alloc_stats;