Index: include/memory =================================================================== --- include/memory +++ include/memory @@ -3711,6 +3711,15 @@ template class _LIBCPP_TEMPLATE_VIS enable_shared_from_this; +template> +struct __libcpp_has_call_op + : std::false_type {}; + +template +struct __libcpp_has_call_op<_Tp, _Up, + std::void_t()(std::declval<_Up>()))>> + : std::true_type {}; + template class _LIBCPP_TEMPLATE_VIS shared_ptr { @@ -3964,6 +3973,11 @@ static __shared_weak_count* __allocate_shared(_Yp* __p, _Deleter __d = _Deleter {}, _Alloc __a = _Alloc {}) { + static_assert(__libcpp_has_call_op<_Deleter, nullptr_t>::value, + "__d must contain call operator that accepts __p"); + static_assert(_VSTD::is_move_constructible<_Deleter>::value, + "_Deleter must be move constructible."); + try { typedef __shared_ptr_pointer<_Yp*, _Deleter, _Alloc> _CT; typedef typename __allocator_traits_rebind<_Alloc, _CT>::type _A2; @@ -3987,6 +4001,11 @@ static __shared_weak_count* __allocate_shared(nullptr_t __p, _Deleter __d = _Deleter {}, _Alloc __a = _Alloc {}) { + static_assert(__libcpp_has_call_op<_Deleter, nullptr_t>::value, + "__d must contain call operator that accepts __p"); + static_assert(_VSTD::is_move_constructible<_Deleter>::value, + "_Deleter must be move constructible."); + try { typedef __shared_ptr_pointer<_Tp*, _Deleter, _Alloc> _CT; typedef typename __allocator_traits_rebind<_Alloc, _CT>::type _A2; Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter.fail.cpp =================================================================== --- /dev/null +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter.fail.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// 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(Y* p, D d); + +#include + +struct NotDeleter +{ + NotDeleter() = default; + NotDeleter(NotDeleter const&) = default; + NotDeleter(NotDeleter&&) = default; +}; + +template +struct NoMoveDeleter +{ + NoMoveDeleter() = default; + NoMoveDeleter(NoMoveDeleter const&) = default; + NoMoveDeleter(NoMoveDeleter&&) = delete; + + void operator()(T*) { } +}; + +int main(int, char**) +{ + { + int* ptr = new int; + // expected-error@memory:* {{static_assert failed due to requirement '__libcpp_has_call_op::value' "__d must contain call operator that accepts __p"}} + // expected-error@memory:* {{type 'NotDeleter' does not provide a call operator}} + std::shared_ptr bp0(ptr, NotDeleter()); // expected-error@memory:* {{type 'NotDeleter' does not provide a call operator}} + + // expected-error@memory:* {{static_assert failed due to requirement 'std::__1::is_move_constructible >::value' "_Deleter must be move constructible."}} + std::shared_ptr bp1(ptr, NoMoveDeleter()); // expected-error@memory:* {{call to deleted constructor of 'NoMoveDeleter'}} + } + + return 0; +} Index: www/cxx1z_status.html =================================================================== --- www/cxx1z_status.html +++ www/cxx1z_status.html @@ -458,7 +458,7 @@ 2795§[global.functions] provides incorrect example of ADL useKonaComplete 2796tuple should be a literal typeKonaComplete 2801Default-constructibility of unique_ptrKonaComplete - 2802shared_ptr constructor requirements for a deleterKona + 2802shared_ptr constructor requirements for a deleterKonaComplete 2804Unconditional constexpr default constructor for istream_iteratorKonaComplete 2806Base class of bad_optional_accessKonaComplete 2807std::invoke should use std::is_nothrow_callableKonaComplete