diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv index 179958854e8cb22..6fc40270af15809 100644 --- a/libcxx/docs/Status/Cxx20Issues.csv +++ b/libcxx/docs/Status/Cxx20Issues.csv @@ -200,7 +200,7 @@ "`3200 `__","``midpoint``\ should not constrain ``T``\ is complete","Prague","|Nothing To Do|","" "`3201 `__","``lerp``\ should be marked as ``noexcept``\ ","Prague","|Complete|","" "`3226 `__","``zoned_time``\ constructor from ``string_view``\ should accept ``zoned_time``\ ","Prague","","","|chrono|" -"`3233 `__","Broken requirements for ``shared_ptr``\ converting constructors","Prague","","" +"`3233 `__","Broken requirements for ``shared_ptr``\ converting constructors","Prague","|Complete|","19.0" "`3237 `__","LWG 3038 and 3190 have inconsistent PRs","Prague","|Complete|","16.0" "`3238 `__","Insufficiently-defined behavior of ``std::function``\ deduction guides","Prague","","" "`3242 `__","``std::format``\ : missing rules for ``arg-id``\ in ``width``\ and ``precision``\ ","Prague","|Complete|","14.0","|format|" diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h index 992b1ba43f100d7..de5707c4a67b0c7 100644 --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -403,6 +403,9 @@ struct __shared_ptr_deleter_ctor_reqs { __well_formed_deleter<_Dp, _Yp*>::value; }; +template +using __shared_ptr_nullptr_deleter_ctor_reqs = _And, __well_formed_deleter<_Dp, nullptr_t> >; + #if defined(_LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI) # define _LIBCPP_SHARED_PTR_TRIVIAL_ABI __attribute__((__trivial_abi__)) #else @@ -498,7 +501,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr { #endif // _LIBCPP_HAS_NO_EXCEPTIONS } - template + template ::value, int> = 0 > _LIBCPP_HIDE_FROM_ABI shared_ptr(nullptr_t __p, _Dp __d) : __ptr_(nullptr) { #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { @@ -518,7 +521,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr { #endif // _LIBCPP_HAS_NO_EXCEPTIONS } - template + template ::value, int> = 0 > _LIBCPP_HIDE_FROM_ABI shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a) : __ptr_(nullptr) { #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter.pass.cpp index 49497b6956b9fbe..13340ed5294c050 100644 --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter.pass.cpp @@ -17,6 +17,7 @@ #include "test_macros.h" #include "deleter_types.h" +#include "types.h" struct A { static int count; @@ -28,6 +29,25 @@ struct A int A::count = 0; +// LWG 3233. Broken requirements for shared_ptr converting constructors +// https://cplusplus.github.io/LWG/issue3233 +static_assert( std::is_constructible, std::nullptr_t, test_deleter >::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, bad_deleter>::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, no_nullptr_deleter>::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, no_move_deleter>::value, ""); + +#if TEST_STD_VER >= 17 +static_assert( std::is_constructible, std::nullptr_t, test_deleter >::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, bad_deleter>::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, no_nullptr_deleter>::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, no_move_deleter>::value, ""); + +static_assert( std::is_constructible, std::nullptr_t, test_deleter >::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, bad_deleter>::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, no_nullptr_deleter>::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, no_move_deleter>::value, ""); +#endif + int main(int, char**) { { diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator.pass.cpp index 4e9fc227b99e813..53ca6fb5b234d40 100644 --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator.pass.cpp @@ -17,6 +17,8 @@ #include "test_allocator.h" #include "min_allocator.h" +#include "types.h" + struct A { static int count; @@ -28,6 +30,25 @@ struct A int A::count = 0; +// LWG 3233. Broken requirements for shared_ptr converting constructors +// https://cplusplus.github.io/LWG/issue3233 +static_assert( std::is_constructible, std::nullptr_t, test_deleter, test_allocator >::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, bad_deleter, test_allocator >::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, no_nullptr_deleter, test_allocator >::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, no_move_deleter, test_allocator >::value, ""); + +#if TEST_STD_VER >= 17 +static_assert( std::is_constructible, std::nullptr_t, test_deleter, test_allocator >::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, bad_deleter, test_allocator >::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, no_nullptr_deleter, test_allocator >::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, no_move_deleter, test_allocator >::value, ""); + +static_assert( std::is_constructible, std::nullptr_t, test_deleter, test_allocator >::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, bad_deleter, test_allocator >::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, no_nullptr_deleter, test_allocator >::value, ""); +static_assert(!std::is_constructible, std::nullptr_t, no_move_deleter, test_allocator >::value, ""); +#endif + int main(int, char**) { test_allocator_statistics alloc_stats; 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 42225a4b0be7ec3..9c1e9b72be573c1 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 @@ -17,6 +17,8 @@ #include "test_macros.h" #include "deleter_types.h" +#include "types.h" + struct A { static int count; @@ -28,38 +30,8 @@ struct A int A::count = 0; -struct bad_ty { }; - -struct bad_deleter -{ - void operator()(bad_ty) { } -}; - -struct no_move_deleter -{ - no_move_deleter(no_move_deleter const&) = delete; - no_move_deleter(no_move_deleter &&) = delete; - void operator()(int*) { } -}; - -static_assert(!std::is_move_constructible::value, ""); - -struct Base { }; -struct Derived : Base { }; - -template -class MoveDeleter -{ - MoveDeleter(); - MoveDeleter(MoveDeleter const&); -public: - MoveDeleter(MoveDeleter&&) {} - - explicit MoveDeleter(int) {} - - void operator()(T* ptr) { delete ptr; } -}; - +// LWG 3233. Broken requirements for shared_ptr converting constructors +// https://cplusplus.github.io/LWG/issue3233 // https://llvm.org/PR60258 // Invalid constructor SFINAE for std::shared_ptr's array ctors static_assert( std::is_constructible, int*, test_deleter >::value, ""); @@ -68,12 +40,12 @@ static_assert( std::is_constructible, Derived*, test_dele 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*, 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(*)[], 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, ""); +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 a110525b9b922da..9dffbcdd59a735d 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 @@ -17,6 +17,7 @@ #include "test_allocator.h" #include "min_allocator.h" +#include "types.h" struct A { static int count; @@ -28,38 +29,8 @@ struct A int A::count = 0; -struct bad_ty { }; - -struct bad_deleter -{ - void operator()(bad_ty) { } -}; - -struct no_move_deleter -{ - no_move_deleter(no_move_deleter const&) = delete; - no_move_deleter(no_move_deleter &&) = delete; - void operator()(int*) { } -}; - -static_assert(!std::is_move_constructible::value, ""); - -struct Base { }; -struct Derived : Base { }; - -template -class MoveDeleter -{ - MoveDeleter(); - MoveDeleter(MoveDeleter const&); -public: - MoveDeleter(MoveDeleter&&) {} - - explicit MoveDeleter(int) {} - - void operator()(T* ptr) { delete ptr; } -}; - +// LWG 3233. Broken requirements for shared_ptr converting constructors +// https://cplusplus.github.io/LWG/issue3233 // 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, ""); @@ -68,12 +39,12 @@ static_assert( std::is_constructible, Derived*, test_dele 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, ""); +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 diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/types.h b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/types.h new file mode 100644 index 000000000000000..5bfb3d70febea04 --- /dev/null +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/types.h @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// 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_UTILITIES_MEMORY_UTIL_SMARTPTR_SHARED_CONST_TYPES_H +#define TEST_STD_UTILITIES_MEMORY_UTIL_SMARTPTR_SHARED_CONST_TYPES_H + +#include + +struct bad_ty {}; + +struct bad_deleter { + void operator()(bad_ty) {} +}; + +struct no_move_deleter { + no_move_deleter(no_move_deleter const&) = delete; + no_move_deleter(no_move_deleter&&) = delete; + void operator()(int*) {} +}; + +static_assert(!std::is_move_constructible::value, ""); + +struct no_nullptr_deleter { + void operator()(int*) const {} + void operator()(std::nullptr_t) const = delete; +}; + +struct Base {}; +struct Derived : Base {}; + +template +class MoveDeleter { + MoveDeleter(); + MoveDeleter(MoveDeleter const&); + +public: + MoveDeleter(MoveDeleter&&) {} + + explicit MoveDeleter(int) {} + + void operator()(T* ptr) { delete ptr; } +}; + +#endif // TEST_STD_UTILITIES_MEMORY_UTIL_SMARTPTR_SHARED_CONST_TYPES_H