https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/73618
>From 84770c82152f027588dd744bbfb91ed55377e007 Mon Sep 17 00:00:00 2001 From: Hristo Hristov <zin...@outlook.com> Date: Sun, 30 Apr 2023 13:17:20 +0300 Subject: [PATCH 1/4] [libc++][memory] P1132R8: out_ptr - a scalable output pointer abstraction Differential Revision: https://reviews.llvm.org/D150525 --- libcxx/docs/FeatureTestMacroTable.rst | 2 +- libcxx/docs/Status/Cxx23Issues.csv | 4 +- libcxx/docs/Status/Cxx23Papers.csv | 2 +- libcxx/include/CMakeLists.txt | 2 + libcxx/include/__memory/allocator_traits.h | 1 - libcxx/include/__memory/inout_ptr.h | 100 +++++++++ libcxx/include/__memory/out_ptr.h | 97 +++++++++ libcxx/include/__memory/pointer_traits.h | 67 +++++- libcxx/include/memory | 18 ++ libcxx/include/module.modulemap.in | 2 + libcxx/include/version | 2 +- libcxx/modules/std/memory.inc | 10 +- .../memory.version.compile.pass.cpp | 16 +- .../version.version.compile.pass.cpp | 16 +- .../inout.ptr/inout.ptr.compile.pass.cpp | 35 +++ .../adapt/inout.ptr/inout.ptr.pass.cpp | 205 ++++++++++++++++++ .../inout.ptr/inout.ptr.t.compile.pass.cpp | 32 +++ .../adapt/inout.ptr/inout.ptr.t.verify.cpp | 29 +++ .../adapt/inout.ptr/inout.ptr.verify.cpp | 30 +++ .../adapt/out.ptr/out.ptr.compile.pass.cpp | 34 +++ .../smartptr/adapt/out.ptr/out.ptr.pass.cpp | 163 ++++++++++++++ .../adapt/out.ptr/out.ptr.t.compile.pass.cpp | 32 +++ .../adapt/out.ptr/out.ptr.t.verify.cpp | 29 +++ .../smartptr/adapt/out.ptr/out.ptr.verify.cpp | 30 +++ .../test/std/utilities/smartptr/adapt/types.h | 77 +++++++ .../generate_feature_test_macro_components.py | 1 - 26 files changed, 999 insertions(+), 37 deletions(-) create mode 100644 libcxx/include/__memory/inout_ptr.h create mode 100644 libcxx/include/__memory/out_ptr.h create mode 100644 libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.compile.pass.cpp create mode 100644 libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.pass.cpp create mode 100644 libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.compile.pass.cpp create mode 100644 libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.verify.cpp create mode 100644 libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.verify.cpp create mode 100644 libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.compile.pass.cpp create mode 100644 libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.pass.cpp create mode 100644 libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.compile.pass.cpp create mode 100644 libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.verify.cpp create mode 100644 libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.verify.cpp create mode 100644 libcxx/test/std/utilities/smartptr/adapt/types.h diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index d09f65b7cadc0e2..4b2adc70f51740c 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -342,7 +342,7 @@ Status --------------------------------------------------- ----------------- ``__cpp_lib_optional`` ``202110L`` --------------------------------------------------- ----------------- - ``__cpp_lib_out_ptr`` *unimplemented* + ``__cpp_lib_out_ptr`` ``202106L`` --------------------------------------------------- ----------------- ``__cpp_lib_print`` *unimplemented* --------------------------------------------------- ----------------- diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv index b24ecc5525a1497..e5ad365f9ffb877 100644 --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -192,7 +192,7 @@ "`3515 <https://wg21.link/LWG3515>`__","§[stacktrace.basic.nonmem]: ``operator<<`` should be less templatized", "November 2022","","","" "`3545 <https://wg21.link/LWG3545>`__","``std::pointer_traits`` should be SFINAE-friendly", "November 2022","|Complete|","18.0","" "`3569 <https://wg21.link/LWG3569>`__","``join_view`` fails to support ranges of ranges with non-default_initializable iterators", "November 2022","","","|ranges|" -"`3594 <https://wg21.link/LWG3594>`__","``inout_ptr`` — inconsistent ``release()`` in destructor", "November 2022","","","" +"`3594 <https://wg21.link/LWG3594>`__","``inout_ptr`` — inconsistent ``release()`` in destructor", "November 2022","|Complete|","17.0","" "`3597 <https://wg21.link/LWG3597>`__","Unsigned integer types don't model advanceable", "November 2022","","","|ranges|" "`3600 <https://wg21.link/LWG3600>`__","Making ``istream_iterator`` copy constructor trivial is an ABI break", "November 2022","","","" "`3629 <https://wg21.link/LWG3629>`__","``make_error_code`` and ``make_error_condition`` are customization points","November 2022","|Complete|","16.0","" @@ -282,7 +282,7 @@ "`3645 <https://wg21.link/LWG3645>`__","``resize_and_overwrite`` is overspecified to call its callback with lvalues","February 2023","|Complete|","14.0","" "`3655 <https://wg21.link/LWG3655>`__","The ``INVOKE`` operation and union types","February 2023","|Complete|","18.0","" "`3723 <https://wg21.link/LWG3723>`__","``priority_queue::push_range`` needs to ``append_range``","February 2023","","","|ranges|" -"`3734 <https://wg21.link/LWG3734>`__","Inconsistency in ``inout_ptr`` and ``out_ptr`` for empty case","February 2023","","","" +"`3734 <https://wg21.link/LWG3734>`__","Inconsistency in ``inout_ptr`` and ``out_ptr`` for empty case","February 2023","|Complete|","17.0","" "`3772 <https://wg21.link/LWG3772>`__","``repeat_view``'s ``piecewise`` constructor is missing Postconditions","February 2023","","","|ranges|" "`3786 <https://wg21.link/LWG3786>`__","Flat maps' deduction guide needs to default ``Allocator`` to be useful","February 2023","","","" "`3803 <https://wg21.link/LWG3803>`__","``flat_foo`` constructors taking ``KeyContainer`` lack ``KeyCompare`` parameter","February 2023","","","" diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv index 5cc9e488297b9f7..198b0ab9d390e33 100644 --- a/libcxx/docs/Status/Cxx23Papers.csv +++ b/libcxx/docs/Status/Cxx23Papers.csv @@ -13,7 +13,7 @@ "","","","","","","" "`P0401R6 <https://wg21.link/P0401R6>`__","LWG","Providing size feedback in the Allocator interface","June 2021","|Complete|","15.0" "`P0448R4 <https://wg21.link/P0448R4>`__","LWG","A strstream replacement using span<charT> as buffer","June 2021","","" -"`P1132R8 <https://wg21.link/P1132R8>`__","LWG","out_ptr - a scalable output pointer abstraction","June 2021","","" +"`P1132R8 <https://wg21.link/P1132R8>`__","LWG","out_ptr - a scalable output pointer abstraction","June 2021","|Complete|","17.0" "`P1328R1 <https://wg21.link/P1328R1>`__","LWG","Making std::type_info::operator== constexpr","June 2021","|Complete|","17.0" "`P1425R4 <https://wg21.link/P1425R4>`__","LWG","Iterators pair constructors for stack and queue","June 2021","|Complete|","14.0","|ranges|" "`P1518R2 <https://wg21.link/P1518R2>`__","LWG","Stop overconstraining allocators in container deduction guides","June 2021","|Complete|","13.0" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index d8faf6467b79ae2..e5a28734ae34bfb 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -529,6 +529,8 @@ set(files __memory/concepts.h __memory/construct_at.h __memory/destruct_n.h + __memory/inout_ptr.h + __memory/out_ptr.h __memory/pointer_traits.h __memory/ranges_construct_at.h __memory/ranges_uninitialized_algorithms.h diff --git a/libcxx/include/__memory/allocator_traits.h b/libcxx/include/__memory/allocator_traits.h index eea5ee973d37fd7..ed13cf8a3c278c1 100644 --- a/libcxx/include/__memory/allocator_traits.h +++ b/libcxx/include/__memory/allocator_traits.h @@ -38,7 +38,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> struct NAME<_Tp, __void_t<typename _Tp:: PROPERTY > > : true_type { } // __pointer -_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_pointer, pointer); template <class _Tp, class _Alloc, class _RawAlloc = __libcpp_remove_reference_t<_Alloc>, bool = __has_pointer<_RawAlloc>::value> diff --git a/libcxx/include/__memory/inout_ptr.h b/libcxx/include/__memory/inout_ptr.h new file mode 100644 index 000000000000000..c2044a4642cf4ee --- /dev/null +++ b/libcxx/include/__memory/inout_ptr.h @@ -0,0 +1,100 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 _LIBCPP___INOUT_PTR_H +#define _LIBCPP___INOUT_PTR_H + +#include <__config> +#include <__memory/addressof.h> +#include <__memory/pointer_traits.h> +#include <__memory/shared_ptr.h> +#include <__memory/unique_ptr.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_specialization.h> +#include <__type_traits/is_void.h> +#include <tuple> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +template <class _Smart, class _Pointer, class... _Args> +class _LIBCPP_TEMPLATE_VIS inout_ptr_t { + static_assert(!__is_specialization_v<_Smart, shared_ptr>, "std::shared_ptr<> is not supported"); + +public: + _LIBCPP_HIDE_FROM_ABI explicit inout_ptr_t(_Smart& __s, _Args... __args) + : __s_(__s), __a_(std::forward<_Args>(__args)...), __p_([&__s] { + if constexpr (is_pointer_v<_Smart>) { + return __s; + } else { + return __s.get(); + } + }()) { + if constexpr (requires { __s.release(); }) { + __s.release(); + } else { + __s = _Smart(); + } + } + + _LIBCPP_HIDE_FROM_ABI inout_ptr_t(const inout_ptr_t&) = delete; + + _LIBCPP_HIDE_FROM_ABI ~inout_ptr_t() { + if (!__p_) { + return; + } + + using _SP = __pointer_of_or_t<_Smart, _Pointer>; + if constexpr (is_pointer_v<_Smart>) { + std::apply([&](auto&&... __args) { __s_ = _Smart(static_cast<_SP>(__p_), std::forward<_Args>(__args)...); }, + std::move(__a_)); + } else if constexpr (__resettable_smart_pointer_with_args<_Smart, _Pointer, _Args...>) { + std::apply([&](auto&&... __args) { __s_.reset(static_cast<_SP>(__p_), std::forward<_Args>(__args)...); }, + std::move(__a_)); + } else if constexpr (is_constructible_v<_Smart, _SP, _Args...>) { + std::apply([&](auto&&... __args) { __s_ = _Smart(static_cast<_SP>(__p_), std::forward<_Args>(__args)...); }, + std::move(__a_)); + } else { + static_assert(is_pointer_v<_Smart> || __resettable_smart_pointer_with_args<_Smart, _Pointer, _Args...> || + is_constructible_v<_Smart, _SP, _Args...>); + } + } + + _LIBCPP_HIDE_FROM_ABI operator _Pointer*() const noexcept { return std::addressof(const_cast<_Pointer&>(__p_)); } + + _LIBCPP_HIDE_FROM_ABI operator void**() const noexcept + requires(!is_same_v<_Pointer, void*>) + { + static_assert(is_pointer_v<_Pointer>); + + return reinterpret_cast<void**>(static_cast<_Pointer*>(*this)); + } + +private: + _Smart& __s_; + tuple<_Args...> __a_; + _Pointer __p_; +}; + +template <class _Pointer = void, class _Smart, class... _Args> +_LIBCPP_HIDE_FROM_ABI auto inout_ptr(_Smart& __s, _Args&&... __args) { + using _Ptr = conditional_t<is_void_v<_Pointer>, __pointer_of_t<_Smart>, _Pointer>; + return std::inout_ptr_t<_Smart, _Ptr, _Args&&...>{__s, std::forward<_Args>(__args)...}; +} + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___INOUT_PTR_H diff --git a/libcxx/include/__memory/out_ptr.h b/libcxx/include/__memory/out_ptr.h new file mode 100644 index 000000000000000..09c77cbafe69e01 --- /dev/null +++ b/libcxx/include/__memory/out_ptr.h @@ -0,0 +1,97 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 _LIBCPP___OUT_PTR_H +#define _LIBCPP___OUT_PTR_H + +#include <__config> +#include <__memory/addressof.h> +#include <__memory/pointer_traits.h> +#include <__memory/shared_ptr.h> +#include <__memory/unique_ptr.h> +#include <__type_traits/is_specialization.h> +#include <__type_traits/is_void.h> +#include <tuple> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +template <class _Tp> +concept __resettable_adapted_ptr = requires(_Tp __ptr) { __ptr().reset(); }; + +template <class _Smart, class _Pointer, class... _Args> +class _LIBCPP_TEMPLATE_VIS out_ptr_t { + static_assert(!__is_specialization_v<_Smart, shared_ptr> || sizeof...(_Args) > 0, + "Specialization of std::shared_ptr<> requires a deleter."); + +public: + _LIBCPP_HIDE_FROM_ABI explicit out_ptr_t(_Smart& __s, _Args... __args) + : __s_(__s), __a_(std::forward<_Args>(__args)...), __p_() { + using _Ptr = decltype(__s); + if constexpr (__resettable_smart_pointer<_Ptr>) { + __s_.reset(); + } else if constexpr (is_constructible_v<_Smart>) { + __s_ = _Smart(); + } else { + static_assert(__resettable_smart_pointer<_Ptr> || is_constructible_v<_Smart>); + } + } + + _LIBCPP_HIDE_FROM_ABI out_ptr_t(const out_ptr_t&) = delete; + + _LIBCPP_HIDE_FROM_ABI ~out_ptr_t() { + if (!__p_) { + return; + } + + using _SP = __pointer_of_or_t<_Smart, _Pointer>; + if constexpr (__resettable_smart_pointer_with_args<_Smart, _Pointer, _Args...>) { + std::apply([&](auto&&... __args) { __s_.reset(static_cast<_SP>(__p_), std::forward<_Args>(__args)...); }, + std::move(__a_)); + } else if constexpr (is_constructible_v<_Smart, _SP, _Args...>) { + std::apply([&](auto&&... __args) { __s_ = _Smart(static_cast<_SP>(__p_), std::forward<_Args>(__args)...); }, + std::move(__a_)); + } else { + static_assert(__resettable_smart_pointer_with_args<_Smart, _Pointer, _Args...> || + is_constructible_v<_Smart, _SP, _Args...>); + } + } + + _LIBCPP_HIDE_FROM_ABI operator _Pointer*() const noexcept { return std::addressof(const_cast<_Pointer&>(__p_)); } + + _LIBCPP_HIDE_FROM_ABI operator void**() const noexcept + requires(!is_same_v<_Pointer, void*>) + { + static_assert(is_pointer_v<_Pointer>); + + return reinterpret_cast<void**>(static_cast<_Pointer*>(*this)); + } + +private: + _Smart& __s_; + tuple<_Args...> __a_; + _Pointer __p_ = _Pointer(); +}; + +template <class _Pointer = void, class _Smart, class... _Args> +_LIBCPP_HIDE_FROM_ABI auto out_ptr(_Smart& __s, _Args&&... __args) { + using _Ptr = conditional_t<is_void_v<_Pointer>, __pointer_of_t<_Smart>, _Pointer>; + return std::out_ptr_t<_Smart, _Ptr, _Args&&...>{__s, std::forward<_Args>(__args)...}; +} + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___OUT_PTR_H diff --git a/libcxx/include/__memory/pointer_traits.h b/libcxx/include/__memory/pointer_traits.h index 7617948ed76bd66..2be0deb50cb8ed1 100644 --- a/libcxx/include/__memory/pointer_traits.h +++ b/libcxx/include/__memory/pointer_traits.h @@ -15,11 +15,14 @@ #include <__type_traits/conditional.h> #include <__type_traits/conjunction.h> #include <__type_traits/decay.h> +#include <__type_traits/enable_if.h> #include <__type_traits/is_class.h> #include <__type_traits/is_function.h> #include <__type_traits/is_void.h> +#include <__type_traits/negation.h> #include <__type_traits/void_t.h> #include <__utility/declval.h> +#include <__utility/forward.h> #include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -28,11 +31,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp, class = void> -struct __has_element_type : false_type {}; +// clang-format off +#define _LIBCPP_CLASS_TRAITS_HAS_XXX(NAME, PROPERTY) \ + template <class _Tp, class = void> \ + struct NAME : false_type {}; \ + template <class _Tp> \ + struct NAME<_Tp, __void_t<typename _Tp::PROPERTY> > : true_type {} +// clang-format on -template <class _Tp> -struct __has_element_type<_Tp, __void_t<typename _Tp::element_type> > : true_type {}; +_LIBCPP_CLASS_TRAITS_HAS_XXX(__has_pointer, pointer); +_LIBCPP_CLASS_TRAITS_HAS_XXX(__has_element_type, element_type); template <class _Ptr, bool = __has_element_type<_Ptr>::value> struct __pointer_traits_element_type {}; @@ -242,6 +250,57 @@ auto to_address(const _Pointer& __p) noexcept -> decltype(std::__to_address(__p) } #endif +#if _LIBCPP_STD_VER >= 23 + +template <class _Tp> +struct __pointer_of {}; + +template <class _Tp> + requires(__has_pointer<_Tp>::value) +struct __pointer_of<_Tp> { + using type = typename _Tp::pointer; +}; + +template <class _Tp> + requires(!__has_pointer<_Tp>::value && __has_element_type<_Tp>::value) +struct __pointer_of<_Tp> { + using type = typename _Tp::element_type*; +}; + +template <class _Tp> + requires(!__has_pointer<_Tp>::value && !__has_element_type<_Tp>::value && + __has_element_type<pointer_traits<_Tp>>::value) +struct __pointer_of<_Tp> { + using type = typename pointer_traits<_Tp>::element_type*; +}; + +template <typename _Tp> +using __pointer_of_t = typename __pointer_of<_Tp>::type; + +template <class _Tp, class _Up> +struct __pointer_of_or { + using type _LIBCPP_NODEBUG = _Up; +}; + +template <class _Tp, class _Up> + requires requires { typename __pointer_of_t<_Tp>; } +struct __pointer_of_or<_Tp, _Up> { + using type _LIBCPP_NODEBUG = __pointer_of_t<_Tp>; +}; + +template <typename _Tp, typename _Up> +using __pointer_of_or_t = typename __pointer_of_or<_Tp, _Up>::type; + +template <class _Smart> +concept __resettable_smart_pointer = requires(_Smart __s) { __s.reset(); }; + +template <class _Smart, class _Pointer = void, class... _Args> +concept __resettable_smart_pointer_with_args = requires(_Smart __s, _Pointer __p, _Args... __args) { + __s.reset(static_cast<__pointer_of_or_t<_Smart, _Pointer>>(__p), std::forward<_Args>(__args)...); +}; + +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___MEMORY_POINTER_TRAITS_H diff --git a/libcxx/include/memory b/libcxx/include/memory index 24ba82f43ddd309..d3ab5f73bf00aae 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -910,6 +910,22 @@ void* align(size_t alignment, size_t size, void*& ptr, size_t& space); template<size_t N, class T> [[nodiscard]] constexpr T* assume_aligned(T* ptr); // since C++20 +// [out.ptr.t], class template out_ptr_t +template<class Smart, class Pointer, class... Args> + class out_ptr_t; // since c++23 + +// [out.ptr], function template out_ptr +template<class Pointer = void, class Smart, class... Args> + auto out_ptr(Smart& s, Args&&... args); // since c++23 + +// [inout.ptr.t], class template inout_ptr_t +template<class Smart, class Pointer, class... Args> + class inout_ptr_t; // since c++23 + +// [inout.ptr], function template inout_ptr +template<class Pointer = void, class Smart, class... Args> + auto inout_ptr(Smart& s, Args&&... args); // since c++23 + } // std */ @@ -928,6 +944,8 @@ template<size_t N, class T> #include <__memory/compressed_pair.h> #include <__memory/concepts.h> #include <__memory/construct_at.h> +#include <__memory/inout_ptr.h> +#include <__memory/out_ptr.h> #include <__memory/pointer_traits.h> #include <__memory/ranges_construct_at.h> #include <__memory/ranges_uninitialized_algorithms.h> diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index 90ee7fbb2157c2d..f8a154d2541677d 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1519,6 +1519,8 @@ module std_private_memory_concepts [system] { } module std_private_memory_construct_at [system] { header "__memory/construct_at.h" } module std_private_memory_destruct_n [system] { header "__memory/destruct_n.h" } +module std_private_memory_inout_ptr [system] { header "__memory/inout_ptr.h" } +module std_private_memory_out_ptr [system] { header "__memory/out_ptr.h" } module std_private_memory_pointer_traits [system] { header "__memory/pointer_traits.h" } module std_private_memory_ranges_construct_at [system] { header "__memory/ranges_construct_at.h" } module std_private_memory_ranges_uninitialized_algorithms [system] { diff --git a/libcxx/include/version b/libcxx/include/version index e84790b888d3333..2203dfd0e600580 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -455,7 +455,7 @@ __cpp_lib_within_lifetime 202306L <type_traits> // # define __cpp_lib_move_only_function 202110L # undef __cpp_lib_optional # define __cpp_lib_optional 202110L -// # define __cpp_lib_out_ptr 202106L +# define __cpp_lib_out_ptr 202106L // # define __cpp_lib_print 202207L // # define __cpp_lib_ranges_as_const 202207L # define __cpp_lib_ranges_as_rvalue 202207L diff --git a/libcxx/modules/std/memory.inc b/libcxx/modules/std/memory.inc index fba2461732c1b9d..a02fa2b865f57fa 100644 --- a/libcxx/modules/std/memory.inc +++ b/libcxx/modules/std/memory.inc @@ -177,17 +177,19 @@ export namespace std { // [util.smartptr.atomic], atomic smart pointers // using std::atomic; +#if _LIBCPP_STD_VER >= 23 // [out.ptr.t], class template out_ptr_t - // using std::out_ptr_t; + using std::out_ptr_t; // [out.ptr], function template out_ptr - // using std::out_ptr; + using std::out_ptr; // [inout.ptr.t], class template inout_ptr_t - // using std::inout_ptr_t; + using std::inout_ptr_t; // [inout.ptr], function template inout_ptr - // using std::inout_ptr; + using std::inout_ptr; +#endif // _LIBCPP_STD_VER >= 23 #ifndef _LIBCPP_HAS_NO_THREADS // [depr.util.smartptr.shared.atomic] diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp index b1f6c76d847398d..c3b37ed35a3ad0e 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp @@ -485,17 +485,11 @@ # error "__cpp_lib_make_unique should have the value 201304L in c++23" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_out_ptr -# error "__cpp_lib_out_ptr should be defined in c++23" -# endif -# if __cpp_lib_out_ptr != 202106L -# error "__cpp_lib_out_ptr should have the value 202106L in c++23" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_out_ptr -# error "__cpp_lib_out_ptr should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_out_ptr +# error "__cpp_lib_out_ptr should be defined in c++23" +# endif +# if __cpp_lib_out_ptr != 202106L +# error "__cpp_lib_out_ptr should have the value 202106L in c++23" # endif # ifndef __cpp_lib_ranges diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp index a995795e305c49f..413fca0e79fecee 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -5210,17 +5210,11 @@ # error "__cpp_lib_optional should have the value 202110L in c++23" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_out_ptr -# error "__cpp_lib_out_ptr should be defined in c++23" -# endif -# if __cpp_lib_out_ptr != 202106L -# error "__cpp_lib_out_ptr should have the value 202106L in c++23" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_out_ptr -# error "__cpp_lib_out_ptr should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_out_ptr +# error "__cpp_lib_out_ptr should be defined in c++23" +# endif +# if __cpp_lib_out_ptr != 202106L +# error "__cpp_lib_out_ptr should have the value 202106L in c++23" # endif # if !defined(_LIBCPP_VERSION) diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.compile.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.compile.pass.cpp new file mode 100644 index 000000000000000..d2eb8c3a6ac0081 --- /dev/null +++ b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.compile.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// 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++03, c++11, c++14, c++17, c++20 + +// <memory> + +// [inout.ptr], function template inout_ptr +// template<class Pointer = void, class Smart, class... Args> +// auto inout_ptr(Smart& s, Args&&... args); // since c++23 + +#include <memory> + +int main(int, char**) { + { + std::unique_ptr<int> uPtr; + + auto inoutUPtr1 = std::inout_ptr(uPtr); + auto inoutUPtr2 = std::inout_ptr<int*>(uPtr); + } + { + auto deleter = [](auto* p) { delete p; }; + std::unique_ptr<int, decltype(deleter)> uPtr; + + auto inoutUPtr1 = std::inout_ptr(uPtr, deleter); + auto inoutUPtr2 = std::inout_ptr<int*>(uPtr, deleter); + } + + return 0; +} diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.pass.cpp new file mode 100644 index 000000000000000..ece562805342780 --- /dev/null +++ b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.pass.cpp @@ -0,0 +1,205 @@ +//===----------------------------------------------------------------------===// +// +// 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++03, c++11, c++14, c++17, c++20 + +// <memory> + +// [inout.ptr.t], class template inout_ptr_t +// template<class Smart, class Pointer, class... Args> +// class inout_ptr_t; // since c++23 + +// [inout.ptr], function template inout_ptr +// template<class Pointer = void, class Smart, class... Args> +// auto inout_ptr(Smart& s, Args&&... args); // since c++23 + +#include <cassert> +#include <memory> + +#include "../types.h" + +// Test helpers. + +void replace_int_p(int** pp) { + assert(**pp == 90); + delete *pp; + *pp = new int{84}; +} + +void replace_int_p_with_nullptr(int** pp) { + assert(**pp == 90); + delete *pp; + *pp = nullptr; +} + +void replace_nullptr_with_int_p(int** pp) { + assert(*pp == nullptr); + *pp = new int{84}; +} + +void replace_int_void_p(void** pp) { + assert(*(static_cast<int*>(*pp)) == 90); + delete static_cast<int*>(*pp); + *pp = new int{84}; +} + +void replace_int_void_p_with_nullptr(void** pp) { + assert(*(static_cast<int*>(*pp)) == 90); + delete static_cast<int*>(*pp); + *pp = nullptr; +} + +void replace_nullptr_with_int_void_p(void** pp) { + assert(*pp == nullptr); + *pp = new int{84}; +} + +void replace_SomeInt_p(SomeInt** pp) { + auto si = **pp; + assert(si.value == 90); + delete static_cast<SomeInt*>(*pp); + *pp = new SomeInt{9084}; +} + +void replace_SomeInt_void_p(void** pp) { + assert(reinterpret_cast<SomeInt*>(*pp)->value == 90); + delete static_cast<SomeInt*>(*pp); + *pp = reinterpret_cast<void*>(new SomeInt{9084}); +} + +// Test `std::inout_ptr()` function. + +void test_raw_ptr() { + { + auto rPtr = new int{90}; + + replace_int_p(std::inout_ptr<int*>(rPtr)); + assert(*rPtr == 84); + + delete rPtr; + } + { + auto rPtr = new int{90}; + + replace_int_p_with_nullptr(std::inout_ptr<int*>(rPtr)); + assert(rPtr == nullptr); + } + { + int* rPtr = nullptr; + + replace_nullptr_with_int_p(std::inout_ptr<int*>(rPtr)); + assert(*rPtr == 84); + delete rPtr; + } + { + auto rPtr = new int{90}; + + replace_int_void_p(std::inout_ptr<int*>(rPtr)); + assert(*rPtr == 84); + delete rPtr; + } + { + auto rPtr = new int{90}; + + replace_int_void_p_with_nullptr(std::inout_ptr<int*>(rPtr)); + assert(rPtr == nullptr); + } + { + int* rPtr = nullptr; + + replace_nullptr_with_int_void_p(std::inout_ptr<int*>(rPtr)); + assert(*rPtr == 84); + delete rPtr; + } + { + auto* rPtr = new SomeInt{90}; + + replace_SomeInt_p(std::inout_ptr(rPtr)); + assert(rPtr->value == 9084); + delete rPtr; + } + { + auto* rPtr = new SomeInt{90}; + + replace_SomeInt_void_p(std::inout_ptr<SomeInt*>(rPtr)); + assert(rPtr->value == 9084); + delete rPtr; + } +} + +void test_unique_ptr() { + { + auto uPtr = std::make_unique<int>(90); + + replace_int_p(std::inout_ptr(uPtr)); + assert(*uPtr == 84); + } + { + std::unique_ptr<int> uPtr; + + replace_nullptr_with_int_p(std::inout_ptr(uPtr)); + assert(*uPtr == 84); + } + { + auto uPtr = std::make_unique<int>(90); + + replace_int_void_p(std::inout_ptr(uPtr)); + assert(*uPtr == 84); + } + { + std::unique_ptr<int> uPtr; + + replace_nullptr_with_int_void_p(std::inout_ptr(uPtr)); + assert(*uPtr == 84); + } + { + auto uPtr = std::make_unique<SomeInt>(90); + + replace_SomeInt_p(std::inout_ptr(uPtr)); + assert(uPtr->value == 9084); + } + { + auto uPtr = std::make_unique<SomeInt>(90); + + replace_SomeInt_void_p(std::inout_ptr<SomeInt*>(uPtr)); + assert(uPtr->value == 9084); + } +} + +void test_custom_ptr() { + // ConstructiblePtr + { + ConstructiblePtr<int> cPtr(new int{90}); + + replace_int_p(std::inout_ptr(cPtr)); + assert(cPtr == 84); + } + // ResettablePtr + { + ResettablePtr<int> rPtr(new int{90}); + + replace_int_p(std::inout_ptr(rPtr)); + assert(rPtr == 84); + } + // NonConstructiblePtr + { + NonConstructiblePtr<int> nPtr; + nPtr.reset(new int{90}); + + replace_int_p(std::inout_ptr(nPtr)); + assert(nPtr == 84); + } +} + +int main(int, char**) { + test_raw_ptr(); + test_unique_ptr(); + test_custom_ptr(); + + return 0; +} diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.compile.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.compile.pass.cpp new file mode 100644 index 000000000000000..18979d014dc0137 --- /dev/null +++ b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.compile.pass.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// 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++03, c++11, c++14, c++17, c++20 + +// <memory> + +// [inout.ptr.t], class template inout_ptr_t +// template<class Smart, class Pointer, class... Args> +// class inout_ptr_t; // since c++23 + +#include <memory> + +int main(int, char**) { + { + std::unique_ptr<int> uPtr; + + std::inout_ptr_t<std::unique_ptr<int>, int*>{uPtr}; + } + { + std::unique_ptr<int> uPtr; + + std::inout_ptr_t<std::unique_ptr<int>, int*>{uPtr}; + } + + return 0; +} diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.verify.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.verify.cpp new file mode 100644 index 000000000000000..33cc55520bb40f6 --- /dev/null +++ b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.verify.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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// <memory> + +// [inout.ptr.t], class template inout_ptr_t +// template<class Smart, class Pointer, class... Args> +// class inout_ptr_t; // since c++23 + +#include <memory> + +int main(int, char**) { + // `std::inout_ptr<>` does not support `std::shared_ptr<>`. + { + std::shared_ptr<int> sPtr; + + // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed due to requirement '!__is_specialization_v<std::shared_ptr<int>, std::shared_ptr>'{{.*}}std::shared_ptr<> is not supported}} + std::inout_ptr_t<std::shared_ptr<int>, int*>{sPtr}; + } + + return 0; +} diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.verify.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.verify.cpp new file mode 100644 index 000000000000000..3e23e543781206e --- /dev/null +++ b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.verify.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// 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++03, c++11, c++14, c++17, c++20 + +// <memory> + +// [inout.ptr], function template inout_ptr +// template<class Pointer = void, class Smart, class... Args> +// auto inout_ptr(Smart& s, Args&&... args); // since c++23 + +#include <memory> + +int main(int, char**) { + // `std::inout_ptr<>` does not support `std::shared_ptr<>`. + { + std::shared_ptr<int> sPtr; + + // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed due to requirement '!__is_specialization_v<std::shared_ptr<int>, std::shared_ptr>'{{.*}}std::shared_ptr<> is not supported}} + auto inoutUPtr1 = std::inout_ptr(sPtr); + auto inoutUPtr2 = std::inout_ptr<int*>(sPtr); + } + + return 0; +} diff --git a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.compile.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.compile.pass.cpp new file mode 100644 index 000000000000000..71f78a5bf770a00 --- /dev/null +++ b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.compile.pass.cpp @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// 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++03, c++11, c++14, c++17, c++20 + +// <memory> + +// [out.ptr], function template out_ptr +// template<class Pointer = void, class Smart, class... Args> +// auto out_ptr(Smart& s, Args&&... args); // since c++23 + +#include <memory> + +int main(int, char**) { + { + std::unique_ptr<int> uPtr; + + auto outUPtr1 = std::out_ptr(uPtr); + auto outUPtr2 = std::out_ptr<int*>(uPtr); + } + { + std::shared_ptr<int> sPtr; + + auto outSPtr1 = std::out_ptr(sPtr, [](auto* p) { delete p; }); + auto outSPtr2 = std::out_ptr<int*>(sPtr, [](auto* p) { delete p; }); + } + + return 0; +} diff --git a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.pass.cpp new file mode 100644 index 000000000000000..2ccf48643c3323d --- /dev/null +++ b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.pass.cpp @@ -0,0 +1,163 @@ +//===----------------------------------------------------------------------===// +// +// 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++03, c++11, c++14, c++17, c++20 + +// <memory> + +// [out.ptr.t], class template out_ptr_t +// template<class Smart, class Pointer, class... Args> +// class out_ptr_t; // since c++23 + +// [out.ptr], function template out_ptr +// template<class Pointer = void, class Smart, class... Args> +// auto out_ptr(Smart& s, Args&&... args); // since c++23 + +#include <cassert> +#include <memory> + +#include "../types.h" + +// Test helpers. + +void get_int_p(int** pp) { *pp = new int{84}; } + +void get_int_p_nullptr(int** pp) { *pp = nullptr; } + +void get_int_void_p(void** pp) { *(reinterpret_cast<int**>(pp)) = new int{84}; } + +void get_int_void_p_nullptr(void** pp) { *pp = nullptr; } + +void get_SomeInt_p(SomeInt** pp) { *pp = new SomeInt{84}; } + +void get_SomeInt_void_p(void** pp) { *pp = reinterpret_cast<int*>(new int{84}); } + +// Test `std::out_ptr()` function. + +void test_raw_ptr() { + { + auto n{90}; + auto rPtr = &n; + + get_int_p(std::inout_ptr<int*>(rPtr)); + assert(*rPtr == 84); + delete rPtr; + + get_int_p_nullptr(std::out_ptr<int*>(rPtr)); + assert(rPtr == nullptr); + + get_int_void_p(std::inout_ptr<int*>(rPtr)); + assert(*rPtr == 84); + delete rPtr; + + get_int_void_p_nullptr(std::out_ptr<int*>(rPtr)); + assert(rPtr == nullptr); + } + { + SomeInt si{90}; + auto* rPtr = &si; + + get_SomeInt_p(std::out_ptr(rPtr)); + assert(rPtr->value == 84); + delete rPtr; + } + { + SomeInt si{90}; + auto* rPtr = &si; + + get_SomeInt_void_p(std::out_ptr<SomeInt*>(rPtr)); + assert(rPtr->value == 84); + delete rPtr; + } +} + +void test_shared_ptr() { + { + auto sPtr = std::make_shared<int>(90); + + get_int_p(std::out_ptr(sPtr, [](auto* p) { delete p; })); + assert(*sPtr == 84); + + sPtr.reset(new int(90)); + + get_int_void_p(std::out_ptr(sPtr, [](auto* p) { delete p; })); + assert(*sPtr == 84); + } + { + auto sPtr = std::make_shared<SomeInt>(90); + + get_SomeInt_p(std::out_ptr(sPtr, [](auto* p) { delete p; })); + assert(sPtr->value == 84); + } + { + auto sPtr = std::make_shared<SomeInt>(90); + + get_SomeInt_void_p(std::out_ptr<SomeInt*>(sPtr, [](auto* p) { delete p; })); + assert(sPtr->value == 84); + } +} + +void test_unique_ptr() { + { + auto uPtr = std::make_unique<int>(90); + + get_int_p(std::out_ptr(uPtr)); + assert(*uPtr == 84); + + uPtr.reset(new int{90}); + + get_int_void_p(std::out_ptr(uPtr)); + assert(*uPtr == 84); + } + { + auto uPtr = std::make_unique<SomeInt>(90); + + get_SomeInt_p(std::out_ptr(uPtr)); + assert(uPtr->value == 84); + } + { + auto uPtr = std::make_unique<SomeInt>(90); + + get_SomeInt_void_p(std::out_ptr<SomeInt*>(uPtr)); + assert(uPtr->value == 84); + } +} + +void test_custom_ptr() { + // ConstructiblePtr + { + ConstructiblePtr<int> cPtr(new int{90}); + + get_int_p(std::out_ptr(cPtr)); + assert(cPtr == 84); + } + // ResettablePtr + { + ResettablePtr<int> rPtr(new int{90}); + + get_int_p(std::out_ptr(rPtr)); + assert(rPtr == 84); + } + // NonConstructiblePtr + { + NonConstructiblePtr<int> nPtr; + nPtr.reset(new int{90}); + + get_int_p(std::out_ptr(nPtr)); + assert(nPtr == 84); + } +} + +int main(int, char**) { + test_raw_ptr(); + test_shared_ptr(); + test_unique_ptr(); + test_custom_ptr(); + + return 0; +} diff --git a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.compile.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.compile.pass.cpp new file mode 100644 index 000000000000000..12ad53ac3811e82 --- /dev/null +++ b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.compile.pass.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// 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++03, c++11, c++14, c++17, c++20 + +// <memory> + +// [out.ptr.t], class template out_ptr_t +// template<class Smart, class Pointer, class... Args> +// class out_ptr_t; // since c++23 + +#include <memory> + +int main(int, char**) { + { + std::unique_ptr<int> uPtr; + + std::out_ptr_t<std::unique_ptr<int>, int*>{uPtr}; + } + { + std::unique_ptr<int, std::default_delete<int>> uPtr; + + std::out_ptr_t<decltype(uPtr), int*, std::default_delete<int>>{uPtr, std::default_delete<int>{}}; + } + + return 0; +} diff --git a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.verify.cpp b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.verify.cpp new file mode 100644 index 000000000000000..c89007b77ae82f9 --- /dev/null +++ b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.verify.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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// <memory> + +// [out.ptr.t], class template out_ptr_t +// template<class Smart, class Pointer, class... Args> +// class out_ptr_t; // since c++23 + +#include <memory> + +int main(int, char**) { + // `std::out_ptr_t<>` requires `std::shared_ptr<>` with a deleter. + { + std::shared_ptr<int> sPtr; + + // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed due to requirement '!__is_specialization_v<std::shared_ptr<int>, std::shared_ptr> || sizeof...(_Args) > 0'{{.*}}Specialization of std::shared_ptr<> requires a deleter.}} + std::out_ptr_t<std::shared_ptr<int>, int*>{sPtr}; + } + + return 0; +} diff --git a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.verify.cpp b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.verify.cpp new file mode 100644 index 000000000000000..f48592059ea0a08 --- /dev/null +++ b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.verify.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// 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++03, c++11, c++14, c++17, c++20 + +// <memory> + +// [out.ptr], function template out_ptr +// template<class Pointer = void, class Smart, class... Args> +// auto out_ptr(Smart& s, Args&&... args); // since c++23 + +#include <memory> + +int main(int, char**) { + // `std::out_ptr<>` requires `std::shared_ptr<>` with a deleter. + { + std::shared_ptr<int> sPtr; + + // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed due to requirement '!__is_specialization_v<std::shared_ptr<int>, std::shared_ptr> || sizeof...(_Args) > 0'{{.*}}Specialization of std::shared_ptr<> requires a deleter.}} + auto outSPtr1 = std::out_ptr(sPtr); + auto outSPtr2 = std::out_ptr<int*>(sPtr); + } + + return 0; +} diff --git a/libcxx/test/std/utilities/smartptr/adapt/types.h b/libcxx/test/std/utilities/smartptr/adapt/types.h new file mode 100644 index 000000000000000..0e2dad400308dc7 --- /dev/null +++ b/libcxx/test/std/utilities/smartptr/adapt/types.h @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// 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_LIBCXX_UTILITIES_SMARTPTR_ADAPT_TYPES_H +#define TEST_LIBCXX_UTILITIES_SMARTPTR_ADAPT_TYPES_H + +#include <type_traits> +#include <memory> + +struct ResetArg {}; + +// Custom pointer types. + +template <typename _Tp> +struct ConstructiblePtr { + using pointer = _Tp*; + std::unique_ptr<_Tp> ptr; + + ConstructiblePtr() = default; + explicit ConstructiblePtr(_Tp* p) : ptr{p} {} + + auto operator==(_Tp val) { return *ptr == val; } + + auto* get() const { return ptr.get(); } + + void release() { ptr.release(); } +}; + +static_assert(std::is_same_v<std::__pointer_of_t< ConstructiblePtr<int>>, int* >); +static_assert(std::is_constructible_v< ConstructiblePtr<int>, int* >); + +template <typename _Tp> +struct ResettablePtr { + using element_type = _Tp; + std::unique_ptr<_Tp> ptr; + + explicit ResettablePtr(_Tp* p) : ptr{p} {} + + auto operator*() const { return *ptr; } + + auto operator==(_Tp val) { return *ptr == val; } + + void reset() { ptr.reset(); } + void reset(_Tp* p, ResetArg) { ptr.reset(p); } + + auto* get() const { return ptr.get(); } + + void release() { ptr.release(); } +}; + +static_assert(std::is_same_v<std::__pointer_of_t< ResettablePtr<int>>, int* >); +static_assert(std::is_constructible_v< ResettablePtr<int>, int* >); + +template <typename _Tp> +struct NonConstructiblePtr : public ResettablePtr<_Tp> { + NonConstructiblePtr() : NonConstructiblePtr::ResettablePtr(nullptr){}; + + void reset(_Tp* p) { ResettablePtr<_Tp>::ptr.reset(p); } +}; + +static_assert(std::is_same_v<std::__pointer_of_t< NonConstructiblePtr<int>>, int* >); +static_assert(!std::is_constructible_v< NonConstructiblePtr<int>, int* >); + +// Custom types. + +struct SomeInt { + int value; + + constexpr explicit SomeInt(int val = 0) : value{val} {} +}; + +#endif // TEST_LIBCXX_UTILITIES_SMARTPTR_ADAPT_TYPES_H diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index 47ee20de0fdc2b2..9910afa15cff66f 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -854,7 +854,6 @@ def add_version_header(tc): "c++26": 202311, # P2833R2 Freestanding Library: inout expected span }, "headers": ["memory"], - "unimplemented": True, }, { "name": "__cpp_lib_parallel_algorithm", >From 4bc779ef33ed55605e502f597b94fff69b9e95f9 Mon Sep 17 00:00:00 2001 From: Hristo Hristov <zin...@outlook.com> Date: Thu, 30 Nov 2023 09:58:10 +0200 Subject: [PATCH 2/4] [out_ptr] Address review comments + new tests --- libcxx/docs/FeatureTestMacroTable.rst | 2 +- libcxx/docs/Status/Cxx23Issues.csv | 4 +- libcxx/docs/Status/Cxx23Papers.csv | 2 +- libcxx/docs/Status/Cxx2cIssues.csv | 2 +- libcxx/include/__memory/inout_ptr.h | 8 ++-- libcxx/include/__memory/out_ptr.h | 2 +- libcxx/include/__memory/pointer_traits.h | 2 - libcxx/include/version | 2 +- .../memory.version.compile.pass.cpp | 16 +++---- .../version.version.compile.pass.cpp | 16 +++---- ...le.pass.cpp => inout.ptr.general.pass.cpp} | 4 ++ .../adapt/inout.ptr/inout.ptr.pass.cpp | 4 -- .../adapt/inout.ptr/inout.ptr.t.ctor.pass.cpp | 43 +++++++++++++++++++ ...le.pass.cpp => inout.ptr.t.deref.pass.cpp} | 3 ++ .../adapt/inout.ptr/inout.ptr.verify.cpp | 1 + ...pile.pass.cpp => out.ptr.general.pass.cpp} | 4 ++ .../smartptr/adapt/out.ptr/out.ptr.pass.cpp | 4 -- .../adapt/out.ptr/out.ptr.t.ctor.pass.cpp | 41 ++++++++++++++++++ ...pile.pass.cpp => out.ptr.t.deref.pass.cpp} | 3 ++ .../smartptr/adapt/out.ptr/out.ptr.verify.cpp | 1 + 20 files changed, 122 insertions(+), 42 deletions(-) rename libcxx/test/std/utilities/smartptr/adapt/inout.ptr/{inout.ptr.compile.pass.cpp => inout.ptr.general.pass.cpp} (92%) create mode 100644 libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.ctor.pass.cpp rename libcxx/test/std/utilities/smartptr/adapt/inout.ptr/{inout.ptr.t.compile.pass.cpp => inout.ptr.t.deref.pass.cpp} (91%) rename libcxx/test/std/utilities/smartptr/adapt/out.ptr/{out.ptr.compile.pass.cpp => out.ptr.general.pass.cpp} (92%) create mode 100644 libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.ctor.pass.cpp rename libcxx/test/std/utilities/smartptr/adapt/out.ptr/{out.ptr.t.compile.pass.cpp => out.ptr.t.deref.pass.cpp} (92%) diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index 4b2adc70f51740c..eb7957c07e30752 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -426,7 +426,7 @@ Status --------------------------------------------------- ----------------- ``__cpp_lib_linalg`` *unimplemented* --------------------------------------------------- ----------------- - ``__cpp_lib_out_ptr`` *unimplemented* + ``__cpp_lib_out_ptr`` ``202311L`` --------------------------------------------------- ----------------- ``__cpp_lib_ratio`` ``202306L`` --------------------------------------------------- ----------------- diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv index e5ad365f9ffb877..3e0122706930dab 100644 --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -192,7 +192,7 @@ "`3515 <https://wg21.link/LWG3515>`__","§[stacktrace.basic.nonmem]: ``operator<<`` should be less templatized", "November 2022","","","" "`3545 <https://wg21.link/LWG3545>`__","``std::pointer_traits`` should be SFINAE-friendly", "November 2022","|Complete|","18.0","" "`3569 <https://wg21.link/LWG3569>`__","``join_view`` fails to support ranges of ranges with non-default_initializable iterators", "November 2022","","","|ranges|" -"`3594 <https://wg21.link/LWG3594>`__","``inout_ptr`` — inconsistent ``release()`` in destructor", "November 2022","|Complete|","17.0","" +"`3594 <https://wg21.link/LWG3594>`__","``inout_ptr`` — inconsistent ``release()`` in destructor", "November 2022","|Complete|","18.0","" "`3597 <https://wg21.link/LWG3597>`__","Unsigned integer types don't model advanceable", "November 2022","","","|ranges|" "`3600 <https://wg21.link/LWG3600>`__","Making ``istream_iterator`` copy constructor trivial is an ABI break", "November 2022","","","" "`3629 <https://wg21.link/LWG3629>`__","``make_error_code`` and ``make_error_condition`` are customization points","November 2022","|Complete|","16.0","" @@ -282,7 +282,7 @@ "`3645 <https://wg21.link/LWG3645>`__","``resize_and_overwrite`` is overspecified to call its callback with lvalues","February 2023","|Complete|","14.0","" "`3655 <https://wg21.link/LWG3655>`__","The ``INVOKE`` operation and union types","February 2023","|Complete|","18.0","" "`3723 <https://wg21.link/LWG3723>`__","``priority_queue::push_range`` needs to ``append_range``","February 2023","","","|ranges|" -"`3734 <https://wg21.link/LWG3734>`__","Inconsistency in ``inout_ptr`` and ``out_ptr`` for empty case","February 2023","|Complete|","17.0","" +"`3734 <https://wg21.link/LWG3734>`__","Inconsistency in ``inout_ptr`` and ``out_ptr`` for empty case","February 2023","|Complete|","18.0","" "`3772 <https://wg21.link/LWG3772>`__","``repeat_view``'s ``piecewise`` constructor is missing Postconditions","February 2023","","","|ranges|" "`3786 <https://wg21.link/LWG3786>`__","Flat maps' deduction guide needs to default ``Allocator`` to be useful","February 2023","","","" "`3803 <https://wg21.link/LWG3803>`__","``flat_foo`` constructors taking ``KeyContainer`` lack ``KeyCompare`` parameter","February 2023","","","" diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv index 198b0ab9d390e33..02352837fa4da8e 100644 --- a/libcxx/docs/Status/Cxx23Papers.csv +++ b/libcxx/docs/Status/Cxx23Papers.csv @@ -13,7 +13,7 @@ "","","","","","","" "`P0401R6 <https://wg21.link/P0401R6>`__","LWG","Providing size feedback in the Allocator interface","June 2021","|Complete|","15.0" "`P0448R4 <https://wg21.link/P0448R4>`__","LWG","A strstream replacement using span<charT> as buffer","June 2021","","" -"`P1132R8 <https://wg21.link/P1132R8>`__","LWG","out_ptr - a scalable output pointer abstraction","June 2021","|Complete|","17.0" +"`P1132R8 <https://wg21.link/P1132R8>`__","LWG","out_ptr - a scalable output pointer abstraction","June 2021","|Complete|","18.0" "`P1328R1 <https://wg21.link/P1328R1>`__","LWG","Making std::type_info::operator== constexpr","June 2021","|Complete|","17.0" "`P1425R4 <https://wg21.link/P1425R4>`__","LWG","Iterators pair constructors for stack and queue","June 2021","|Complete|","14.0","|ranges|" "`P1518R2 <https://wg21.link/P1518R2>`__","LWG","Stop overconstraining allocators in container deduction guides","June 2021","|Complete|","13.0" diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv index fe0f13f6e8cb2c2..1f407e322f89134 100644 --- a/libcxx/docs/Status/Cxx2cIssues.csv +++ b/libcxx/docs/Status/Cxx2cIssues.csv @@ -24,7 +24,7 @@ "`3749 <https://wg21.link/LWG3749>`__","``common_iterator`` should handle integer-class difference types","Kona November 2023","","","" "`3809 <https://wg21.link/LWG3809>`__","Is ``std::subtract_with_carry_engine<uint16_t>`` supposed to work","Kona November 2023","","","" "`3892 <https://wg21.link/LWG3892>`__","Incorrect formatting of nested ranges and tuples","Kona November 2023","|Complete|","17.0","|format|" -"`3897 <https://wg21.link/LWG3897>`__","``inout_ptr`` will not update raw pointer to 0","Kona November 2023","","","" +"`3897 <https://wg21.link/LWG3897>`__","``inout_ptr`` will not update raw pointer to 0","Kona November 2023","|Complete|","18.0","" "`3946 <https://wg21.link/LWG3946>`__","The definition of ``const_iterator_t`` should be reworked","Kona November 2023","","","" "`3947 <https://wg21.link/LWG3947>`__","Unexpected constraints on ``adjacent_transform_view::base()``","Kona November 2023","","","|ranges|" "`3948 <https://wg21.link/LWG3948>`__","``possibly-const-range and as-const-pointer`` should be ``noexcept``","Kona November 2023","","","|ranges|" diff --git a/libcxx/include/__memory/inout_ptr.h b/libcxx/include/__memory/inout_ptr.h index c2044a4642cf4ee..f91ecd8baff57d1 100644 --- a/libcxx/include/__memory/inout_ptr.h +++ b/libcxx/include/__memory/inout_ptr.h @@ -51,8 +51,10 @@ class _LIBCPP_TEMPLATE_VIS inout_ptr_t { _LIBCPP_HIDE_FROM_ABI inout_ptr_t(const inout_ptr_t&) = delete; _LIBCPP_HIDE_FROM_ABI ~inout_ptr_t() { - if (!__p_) { - return; + if constexpr (!is_pointer_v<_Smart>) { + if (!__p_) { + return; + } } using _SP = __pointer_of_or_t<_Smart, _Pointer>; @@ -90,7 +92,7 @@ class _LIBCPP_TEMPLATE_VIS inout_ptr_t { template <class _Pointer = void, class _Smart, class... _Args> _LIBCPP_HIDE_FROM_ABI auto inout_ptr(_Smart& __s, _Args&&... __args) { using _Ptr = conditional_t<is_void_v<_Pointer>, __pointer_of_t<_Smart>, _Pointer>; - return std::inout_ptr_t<_Smart, _Ptr, _Args&&...>{__s, std::forward<_Args>(__args)...}; + return std::inout_ptr_t<_Smart, _Ptr, _Args&&...>(__s, std::forward<_Args>(__args)...); } #endif // _LIBCPP_STD_VER >= 23 diff --git a/libcxx/include/__memory/out_ptr.h b/libcxx/include/__memory/out_ptr.h index 09c77cbafe69e01..eebc18c97fdcdb5 100644 --- a/libcxx/include/__memory/out_ptr.h +++ b/libcxx/include/__memory/out_ptr.h @@ -87,7 +87,7 @@ class _LIBCPP_TEMPLATE_VIS out_ptr_t { template <class _Pointer = void, class _Smart, class... _Args> _LIBCPP_HIDE_FROM_ABI auto out_ptr(_Smart& __s, _Args&&... __args) { using _Ptr = conditional_t<is_void_v<_Pointer>, __pointer_of_t<_Smart>, _Pointer>; - return std::out_ptr_t<_Smart, _Ptr, _Args&&...>{__s, std::forward<_Args>(__args)...}; + return std::out_ptr_t<_Smart, _Ptr, _Args&&...>(__s, std::forward<_Args>(__args)...); } #endif // _LIBCPP_STD_VER >= 23 diff --git a/libcxx/include/__memory/pointer_traits.h b/libcxx/include/__memory/pointer_traits.h index 2be0deb50cb8ed1..4e902746e6a35b1 100644 --- a/libcxx/include/__memory/pointer_traits.h +++ b/libcxx/include/__memory/pointer_traits.h @@ -15,11 +15,9 @@ #include <__type_traits/conditional.h> #include <__type_traits/conjunction.h> #include <__type_traits/decay.h> -#include <__type_traits/enable_if.h> #include <__type_traits/is_class.h> #include <__type_traits/is_function.h> #include <__type_traits/is_void.h> -#include <__type_traits/negation.h> #include <__type_traits/void_t.h> #include <__utility/declval.h> #include <__utility/forward.h> diff --git a/libcxx/include/version b/libcxx/include/version index 2203dfd0e600580..079e9f346a9172d 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -502,7 +502,7 @@ __cpp_lib_within_lifetime 202306L <type_traits> // # define __cpp_lib_hazard_pointer 202306L // # define __cpp_lib_linalg 202311L # undef __cpp_lib_out_ptr -// # define __cpp_lib_out_ptr 202311L +# define __cpp_lib_out_ptr 202311L # define __cpp_lib_ratio 202306L // # define __cpp_lib_rcu 202306L // # define __cpp_lib_saturation_arithmetic 202311L diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp index c3b37ed35a3ad0e..f50f1788cc497c2 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp @@ -616,17 +616,11 @@ # error "__cpp_lib_make_unique should have the value 201304L in c++26" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_out_ptr -# error "__cpp_lib_out_ptr should be defined in c++26" -# endif -# if __cpp_lib_out_ptr != 202311L -# error "__cpp_lib_out_ptr should have the value 202311L in c++26" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_out_ptr -# error "__cpp_lib_out_ptr should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_out_ptr +# error "__cpp_lib_out_ptr should be defined in c++26" +# endif +# if __cpp_lib_out_ptr != 202311L +# error "__cpp_lib_out_ptr should have the value 202311L in c++26" # endif # ifndef __cpp_lib_ranges diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp index 413fca0e79fecee..272177da0b444e0 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -6917,17 +6917,11 @@ # error "__cpp_lib_optional should have the value 202110L in c++26" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_out_ptr -# error "__cpp_lib_out_ptr should be defined in c++26" -# endif -# if __cpp_lib_out_ptr != 202311L -# error "__cpp_lib_out_ptr should have the value 202311L in c++26" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_out_ptr -# error "__cpp_lib_out_ptr should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_out_ptr +# error "__cpp_lib_out_ptr should be defined in c++26" +# endif +# if __cpp_lib_out_ptr != 202311L +# error "__cpp_lib_out_ptr should have the value 202311L in c++26" # endif # if !defined(_LIBCPP_VERSION) diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.compile.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.general.pass.cpp similarity index 92% rename from libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.compile.pass.cpp rename to libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.general.pass.cpp index d2eb8c3a6ac0081..1b45d04f7942d7c 100644 --- a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.compile.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.general.pass.cpp @@ -21,14 +21,18 @@ int main(int, char**) { std::unique_ptr<int> uPtr; auto inoutUPtr1 = std::inout_ptr(uPtr); + (void)inoutUPtr1; auto inoutUPtr2 = std::inout_ptr<int*>(uPtr); + (void)inoutUPtr2; } { auto deleter = [](auto* p) { delete p; }; std::unique_ptr<int, decltype(deleter)> uPtr; auto inoutUPtr1 = std::inout_ptr(uPtr, deleter); + (void)inoutUPtr1; auto inoutUPtr2 = std::inout_ptr<int*>(uPtr, deleter); + (void)inoutUPtr2; } return 0; diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.pass.cpp index ece562805342780..58f09dc3a9ec3b2 100644 --- a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.pass.cpp @@ -10,10 +10,6 @@ // <memory> -// [inout.ptr.t], class template inout_ptr_t -// template<class Smart, class Pointer, class... Args> -// class inout_ptr_t; // since c++23 - // [inout.ptr], function template inout_ptr // template<class Pointer = void, class Smart, class... Args> // auto inout_ptr(Smart& s, Args&&... args); // since c++23 diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.ctor.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.ctor.pass.cpp new file mode 100644 index 000000000000000..0a21a41539e432e --- /dev/null +++ b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.ctor.pass.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// 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++03, c++11, c++14, c++17, c++20 + +// <memory> + +// [inout.ptr.t], class template inout_ptr_t +// template<class Smart, class Pointer, class... Args> +// class inout_ptr_t; // since c++23 + +// explicit inout_ptr_t(Smart&, Args...); + +#include <memory> + +#include "test_convertible.h" + +int main(int, char**) { + { + std::unique_ptr<int> uPtr; + + std::inout_ptr_t<std::unique_ptr<int>, int*>{uPtr}; + + static_assert( + !test_convertible<std::inout_ptr_t<std::unique_ptr<int>, int*>>(), "This constructor must be explicit"); + } + { + auto deleter = [](auto* p) { delete p; }; + std::unique_ptr<int, decltype(deleter)> uPtr; + + std::inout_ptr_t<std::unique_ptr<int, decltype(deleter)>, int*>{uPtr}; + + static_assert(!test_convertible<std::inout_ptr_t<std::unique_ptr<int, decltype(deleter)>, int*>>(), + "This constructor must be explicit"); + } + + return 0; +} diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.compile.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.deref.pass.cpp similarity index 91% rename from libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.compile.pass.cpp rename to libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.deref.pass.cpp index 18979d014dc0137..86a055a7644e255 100644 --- a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.compile.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.deref.pass.cpp @@ -14,6 +14,9 @@ // template<class Smart, class Pointer, class... Args> // class inout_ptr_t; // since c++23 +// operator Pointer*() const noexcept; +// operator void**() const noexcept; + #include <memory> int main(int, char**) { diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.verify.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.verify.cpp index 3e23e543781206e..eb296767085b74a 100644 --- a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.verify.cpp +++ b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.verify.cpp @@ -23,6 +23,7 @@ int main(int, char**) { // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed due to requirement '!__is_specialization_v<std::shared_ptr<int>, std::shared_ptr>'{{.*}}std::shared_ptr<> is not supported}} auto inoutUPtr1 = std::inout_ptr(sPtr); + // expected-error@*:* {{no matching conversion for functional-style cast from 'std::shared_ptr<int>' to 'std::inout_ptr_t<shared_ptr<int>, _Ptr>' (aka 'inout_ptr_t<std::shared_ptr<int>, int *>'}} auto inoutUPtr2 = std::inout_ptr<int*>(sPtr); } diff --git a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.compile.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.general.pass.cpp similarity index 92% rename from libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.compile.pass.cpp rename to libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.general.pass.cpp index 71f78a5bf770a00..84bea7248e7a6ee 100644 --- a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.compile.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.general.pass.cpp @@ -21,13 +21,17 @@ int main(int, char**) { std::unique_ptr<int> uPtr; auto outUPtr1 = std::out_ptr(uPtr); + (void)outUPtr1; auto outUPtr2 = std::out_ptr<int*>(uPtr); + (void)outUPtr2; } { std::shared_ptr<int> sPtr; auto outSPtr1 = std::out_ptr(sPtr, [](auto* p) { delete p; }); + (void)outSPtr1; auto outSPtr2 = std::out_ptr<int*>(sPtr, [](auto* p) { delete p; }); + (void)outSPtr2; } return 0; diff --git a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.pass.cpp index 2ccf48643c3323d..a5189717fad6242 100644 --- a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.pass.cpp @@ -10,10 +10,6 @@ // <memory> -// [out.ptr.t], class template out_ptr_t -// template<class Smart, class Pointer, class... Args> -// class out_ptr_t; // since c++23 - // [out.ptr], function template out_ptr // template<class Pointer = void, class Smart, class... Args> // auto out_ptr(Smart& s, Args&&... args); // since c++23 diff --git a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.ctor.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.ctor.pass.cpp new file mode 100644 index 000000000000000..39604247216e817 --- /dev/null +++ b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.ctor.pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// 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++03, c++11, c++14, c++17, c++20 + +// <memory> + +// [out.ptr.t], class template out_ptr_t +// template<class Smart, class Pointer, class... Args> +// class out_ptr_t; // since c++23 + +// explicit out_ptr_t(Smart&, Args...); + +#include <memory> + +#include "test_convertible.h" + +int main(int, char**) { + { + std::unique_ptr<int> uPtr; + + std::out_ptr_t<std::unique_ptr<int>, int*>{uPtr}; + + static_assert(!test_convertible<std::out_ptr_t<std::unique_ptr<int>, int*>>(), "This constructor must be explicit"); + } + { + std::unique_ptr<int, std::default_delete<int>> uPtr; + + std::out_ptr_t<decltype(uPtr), int*, std::default_delete<int>>{uPtr, std::default_delete<int>{}}; + + static_assert(!test_convertible<std::out_ptr_t<decltype(uPtr), int*, std::default_delete<int>>>(), + "This constructor must be explicit"); + } + + return 0; +} diff --git a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.compile.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.deref.pass.cpp similarity index 92% rename from libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.compile.pass.cpp rename to libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.deref.pass.cpp index 12ad53ac3811e82..a0f3af8f87fd748 100644 --- a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.compile.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.deref.pass.cpp @@ -14,6 +14,9 @@ // template<class Smart, class Pointer, class... Args> // class out_ptr_t; // since c++23 +// operator Pointer*() const noexcept; +// operator void**() const noexcept; + #include <memory> int main(int, char**) { diff --git a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.verify.cpp b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.verify.cpp index f48592059ea0a08..3c51583421e7668 100644 --- a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.verify.cpp +++ b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.verify.cpp @@ -23,6 +23,7 @@ int main(int, char**) { // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed due to requirement '!__is_specialization_v<std::shared_ptr<int>, std::shared_ptr> || sizeof...(_Args) > 0'{{.*}}Specialization of std::shared_ptr<> requires a deleter.}} auto outSPtr1 = std::out_ptr(sPtr); + // expected-error@*:* {{no matching conversion for functional-style cast from 'std::shared_ptr<int>' to 'std::out_ptr_t<shared_ptr<int>, _Ptr>' (aka 'out_ptr_t<std::shared_ptr<int>, int *>')}} auto outSPtr2 = std::out_ptr<int*>(sPtr); } >From b23e91a1ca684b8454fe84ff570b7245f52e49d1 Mon Sep 17 00:00:00 2001 From: Hristo Hristov <zin...@outlook.com> Date: Thu, 30 Nov 2023 15:03:00 +0200 Subject: [PATCH 3/4] [out_ptr] Added tests --- .../inout.ptr.compile.pass.cpp} | 18 +- .../inout.ptr/inout.ptr.general.pass.cpp | 184 +++++++++++++++- .../adapt/inout.ptr/inout.ptr.pass.cpp | 201 ------------------ ....pass.cpp => inout.ptr.t.convert.pass.cpp} | 20 +- ...eral.pass.cpp => out.ptr.compile.pass.cpp} | 4 - .../{out.ptr.pass.cpp => out.ptr.general.cpp} | 0 .../adapt/out.ptr/out.ptr.t.convert.pass.cpp | 58 +++++ 7 files changed, 256 insertions(+), 229 deletions(-) rename libcxx/test/std/utilities/smartptr/adapt/{out.ptr/out.ptr.t.deref.pass.cpp => inout.ptr/inout.ptr.compile.pass.cpp} (54%) delete mode 100644 libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.pass.cpp rename libcxx/test/std/utilities/smartptr/adapt/inout.ptr/{inout.ptr.t.deref.pass.cpp => inout.ptr.t.convert.pass.cpp} (55%) rename libcxx/test/std/utilities/smartptr/adapt/out.ptr/{out.ptr.general.pass.cpp => out.ptr.compile.pass.cpp} (92%) rename libcxx/test/std/utilities/smartptr/adapt/out.ptr/{out.ptr.pass.cpp => out.ptr.general.cpp} (100%) create mode 100644 libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.convert.pass.cpp diff --git a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.deref.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.compile.pass.cpp similarity index 54% rename from libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.deref.pass.cpp rename to libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.compile.pass.cpp index a0f3af8f87fd748..d2eb8c3a6ac0081 100644 --- a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.deref.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.compile.pass.cpp @@ -10,12 +10,9 @@ // <memory> -// [out.ptr.t], class template out_ptr_t -// template<class Smart, class Pointer, class... Args> -// class out_ptr_t; // since c++23 - -// operator Pointer*() const noexcept; -// operator void**() const noexcept; +// [inout.ptr], function template inout_ptr +// template<class Pointer = void, class Smart, class... Args> +// auto inout_ptr(Smart& s, Args&&... args); // since c++23 #include <memory> @@ -23,12 +20,15 @@ int main(int, char**) { { std::unique_ptr<int> uPtr; - std::out_ptr_t<std::unique_ptr<int>, int*>{uPtr}; + auto inoutUPtr1 = std::inout_ptr(uPtr); + auto inoutUPtr2 = std::inout_ptr<int*>(uPtr); } { - std::unique_ptr<int, std::default_delete<int>> uPtr; + auto deleter = [](auto* p) { delete p; }; + std::unique_ptr<int, decltype(deleter)> uPtr; - std::out_ptr_t<decltype(uPtr), int*, std::default_delete<int>>{uPtr, std::default_delete<int>{}}; + auto inoutUPtr1 = std::inout_ptr(uPtr, deleter); + auto inoutUPtr2 = std::inout_ptr<int*>(uPtr, deleter); } return 0; diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.general.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.general.pass.cpp index 1b45d04f7942d7c..58f09dc3a9ec3b2 100644 --- a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.general.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.general.pass.cpp @@ -14,26 +14,188 @@ // template<class Pointer = void, class Smart, class... Args> // auto inout_ptr(Smart& s, Args&&... args); // since c++23 +#include <cassert> #include <memory> -int main(int, char**) { +#include "../types.h" + +// Test helpers. + +void replace_int_p(int** pp) { + assert(**pp == 90); + delete *pp; + *pp = new int{84}; +} + +void replace_int_p_with_nullptr(int** pp) { + assert(**pp == 90); + delete *pp; + *pp = nullptr; +} + +void replace_nullptr_with_int_p(int** pp) { + assert(*pp == nullptr); + *pp = new int{84}; +} + +void replace_int_void_p(void** pp) { + assert(*(static_cast<int*>(*pp)) == 90); + delete static_cast<int*>(*pp); + *pp = new int{84}; +} + +void replace_int_void_p_with_nullptr(void** pp) { + assert(*(static_cast<int*>(*pp)) == 90); + delete static_cast<int*>(*pp); + *pp = nullptr; +} + +void replace_nullptr_with_int_void_p(void** pp) { + assert(*pp == nullptr); + *pp = new int{84}; +} + +void replace_SomeInt_p(SomeInt** pp) { + auto si = **pp; + assert(si.value == 90); + delete static_cast<SomeInt*>(*pp); + *pp = new SomeInt{9084}; +} + +void replace_SomeInt_void_p(void** pp) { + assert(reinterpret_cast<SomeInt*>(*pp)->value == 90); + delete static_cast<SomeInt*>(*pp); + *pp = reinterpret_cast<void*>(new SomeInt{9084}); +} + +// Test `std::inout_ptr()` function. + +void test_raw_ptr() { + { + auto rPtr = new int{90}; + + replace_int_p(std::inout_ptr<int*>(rPtr)); + assert(*rPtr == 84); + + delete rPtr; + } + { + auto rPtr = new int{90}; + + replace_int_p_with_nullptr(std::inout_ptr<int*>(rPtr)); + assert(rPtr == nullptr); + } + { + int* rPtr = nullptr; + + replace_nullptr_with_int_p(std::inout_ptr<int*>(rPtr)); + assert(*rPtr == 84); + delete rPtr; + } + { + auto rPtr = new int{90}; + + replace_int_void_p(std::inout_ptr<int*>(rPtr)); + assert(*rPtr == 84); + delete rPtr; + } + { + auto rPtr = new int{90}; + + replace_int_void_p_with_nullptr(std::inout_ptr<int*>(rPtr)); + assert(rPtr == nullptr); + } + { + int* rPtr = nullptr; + + replace_nullptr_with_int_void_p(std::inout_ptr<int*>(rPtr)); + assert(*rPtr == 84); + delete rPtr; + } + { + auto* rPtr = new SomeInt{90}; + + replace_SomeInt_p(std::inout_ptr(rPtr)); + assert(rPtr->value == 9084); + delete rPtr; + } + { + auto* rPtr = new SomeInt{90}; + + replace_SomeInt_void_p(std::inout_ptr<SomeInt*>(rPtr)); + assert(rPtr->value == 9084); + delete rPtr; + } +} + +void test_unique_ptr() { + { + auto uPtr = std::make_unique<int>(90); + + replace_int_p(std::inout_ptr(uPtr)); + assert(*uPtr == 84); + } { std::unique_ptr<int> uPtr; - auto inoutUPtr1 = std::inout_ptr(uPtr); - (void)inoutUPtr1; - auto inoutUPtr2 = std::inout_ptr<int*>(uPtr); - (void)inoutUPtr2; + replace_nullptr_with_int_p(std::inout_ptr(uPtr)); + assert(*uPtr == 84); } { - auto deleter = [](auto* p) { delete p; }; - std::unique_ptr<int, decltype(deleter)> uPtr; + auto uPtr = std::make_unique<int>(90); - auto inoutUPtr1 = std::inout_ptr(uPtr, deleter); - (void)inoutUPtr1; - auto inoutUPtr2 = std::inout_ptr<int*>(uPtr, deleter); - (void)inoutUPtr2; + replace_int_void_p(std::inout_ptr(uPtr)); + assert(*uPtr == 84); } + { + std::unique_ptr<int> uPtr; + + replace_nullptr_with_int_void_p(std::inout_ptr(uPtr)); + assert(*uPtr == 84); + } + { + auto uPtr = std::make_unique<SomeInt>(90); + + replace_SomeInt_p(std::inout_ptr(uPtr)); + assert(uPtr->value == 9084); + } + { + auto uPtr = std::make_unique<SomeInt>(90); + + replace_SomeInt_void_p(std::inout_ptr<SomeInt*>(uPtr)); + assert(uPtr->value == 9084); + } +} + +void test_custom_ptr() { + // ConstructiblePtr + { + ConstructiblePtr<int> cPtr(new int{90}); + + replace_int_p(std::inout_ptr(cPtr)); + assert(cPtr == 84); + } + // ResettablePtr + { + ResettablePtr<int> rPtr(new int{90}); + + replace_int_p(std::inout_ptr(rPtr)); + assert(rPtr == 84); + } + // NonConstructiblePtr + { + NonConstructiblePtr<int> nPtr; + nPtr.reset(new int{90}); + + replace_int_p(std::inout_ptr(nPtr)); + assert(nPtr == 84); + } +} + +int main(int, char**) { + test_raw_ptr(); + test_unique_ptr(); + test_custom_ptr(); return 0; } diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.pass.cpp deleted file mode 100644 index 58f09dc3a9ec3b2..000000000000000 --- a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.pass.cpp +++ /dev/null @@ -1,201 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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++03, c++11, c++14, c++17, c++20 - -// <memory> - -// [inout.ptr], function template inout_ptr -// template<class Pointer = void, class Smart, class... Args> -// auto inout_ptr(Smart& s, Args&&... args); // since c++23 - -#include <cassert> -#include <memory> - -#include "../types.h" - -// Test helpers. - -void replace_int_p(int** pp) { - assert(**pp == 90); - delete *pp; - *pp = new int{84}; -} - -void replace_int_p_with_nullptr(int** pp) { - assert(**pp == 90); - delete *pp; - *pp = nullptr; -} - -void replace_nullptr_with_int_p(int** pp) { - assert(*pp == nullptr); - *pp = new int{84}; -} - -void replace_int_void_p(void** pp) { - assert(*(static_cast<int*>(*pp)) == 90); - delete static_cast<int*>(*pp); - *pp = new int{84}; -} - -void replace_int_void_p_with_nullptr(void** pp) { - assert(*(static_cast<int*>(*pp)) == 90); - delete static_cast<int*>(*pp); - *pp = nullptr; -} - -void replace_nullptr_with_int_void_p(void** pp) { - assert(*pp == nullptr); - *pp = new int{84}; -} - -void replace_SomeInt_p(SomeInt** pp) { - auto si = **pp; - assert(si.value == 90); - delete static_cast<SomeInt*>(*pp); - *pp = new SomeInt{9084}; -} - -void replace_SomeInt_void_p(void** pp) { - assert(reinterpret_cast<SomeInt*>(*pp)->value == 90); - delete static_cast<SomeInt*>(*pp); - *pp = reinterpret_cast<void*>(new SomeInt{9084}); -} - -// Test `std::inout_ptr()` function. - -void test_raw_ptr() { - { - auto rPtr = new int{90}; - - replace_int_p(std::inout_ptr<int*>(rPtr)); - assert(*rPtr == 84); - - delete rPtr; - } - { - auto rPtr = new int{90}; - - replace_int_p_with_nullptr(std::inout_ptr<int*>(rPtr)); - assert(rPtr == nullptr); - } - { - int* rPtr = nullptr; - - replace_nullptr_with_int_p(std::inout_ptr<int*>(rPtr)); - assert(*rPtr == 84); - delete rPtr; - } - { - auto rPtr = new int{90}; - - replace_int_void_p(std::inout_ptr<int*>(rPtr)); - assert(*rPtr == 84); - delete rPtr; - } - { - auto rPtr = new int{90}; - - replace_int_void_p_with_nullptr(std::inout_ptr<int*>(rPtr)); - assert(rPtr == nullptr); - } - { - int* rPtr = nullptr; - - replace_nullptr_with_int_void_p(std::inout_ptr<int*>(rPtr)); - assert(*rPtr == 84); - delete rPtr; - } - { - auto* rPtr = new SomeInt{90}; - - replace_SomeInt_p(std::inout_ptr(rPtr)); - assert(rPtr->value == 9084); - delete rPtr; - } - { - auto* rPtr = new SomeInt{90}; - - replace_SomeInt_void_p(std::inout_ptr<SomeInt*>(rPtr)); - assert(rPtr->value == 9084); - delete rPtr; - } -} - -void test_unique_ptr() { - { - auto uPtr = std::make_unique<int>(90); - - replace_int_p(std::inout_ptr(uPtr)); - assert(*uPtr == 84); - } - { - std::unique_ptr<int> uPtr; - - replace_nullptr_with_int_p(std::inout_ptr(uPtr)); - assert(*uPtr == 84); - } - { - auto uPtr = std::make_unique<int>(90); - - replace_int_void_p(std::inout_ptr(uPtr)); - assert(*uPtr == 84); - } - { - std::unique_ptr<int> uPtr; - - replace_nullptr_with_int_void_p(std::inout_ptr(uPtr)); - assert(*uPtr == 84); - } - { - auto uPtr = std::make_unique<SomeInt>(90); - - replace_SomeInt_p(std::inout_ptr(uPtr)); - assert(uPtr->value == 9084); - } - { - auto uPtr = std::make_unique<SomeInt>(90); - - replace_SomeInt_void_p(std::inout_ptr<SomeInt*>(uPtr)); - assert(uPtr->value == 9084); - } -} - -void test_custom_ptr() { - // ConstructiblePtr - { - ConstructiblePtr<int> cPtr(new int{90}); - - replace_int_p(std::inout_ptr(cPtr)); - assert(cPtr == 84); - } - // ResettablePtr - { - ResettablePtr<int> rPtr(new int{90}); - - replace_int_p(std::inout_ptr(rPtr)); - assert(rPtr == 84); - } - // NonConstructiblePtr - { - NonConstructiblePtr<int> nPtr; - nPtr.reset(new int{90}); - - replace_int_p(std::inout_ptr(nPtr)); - assert(nPtr == 84); - } -} - -int main(int, char**) { - test_raw_ptr(); - test_unique_ptr(); - test_custom_ptr(); - - return 0; -} diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.deref.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.convert.pass.cpp similarity index 55% rename from libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.deref.pass.cpp rename to libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.convert.pass.cpp index 86a055a7644e255..cee19c11c78c38a 100644 --- a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.deref.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.t.convert.pass.cpp @@ -17,18 +17,30 @@ // operator Pointer*() const noexcept; // operator void**() const noexcept; +#include <cassert> +#include <concepts> #include <memory> int main(int, char**) { { - std::unique_ptr<int> uPtr; + std::unique_ptr<int> uPtr = std::make_unique<int>(84); - std::inout_ptr_t<std::unique_ptr<int>, int*>{uPtr}; + const std::inout_ptr_t<std::unique_ptr<int>, int*> ioPtr{uPtr}; + + static_assert(noexcept(ioPtr.operator int**())); + std::same_as<int**> decltype(auto) pPtr = ioPtr.operator int**(); + + assert(**pPtr == 84); } { - std::unique_ptr<int> uPtr; + std::unique_ptr<int> uPtr = std::make_unique<int>(84); + + const std::inout_ptr_t<std::unique_ptr<int>, void*> ioPtr{uPtr}; + + static_assert(noexcept(ioPtr.operator void**())); + std::same_as<void**> decltype(auto) pPtr = ioPtr.operator void**(); - std::inout_ptr_t<std::unique_ptr<int>, int*>{uPtr}; + assert(**reinterpret_cast<int**>(pPtr) == 84); } return 0; diff --git a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.general.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.compile.pass.cpp similarity index 92% rename from libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.general.pass.cpp rename to libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.compile.pass.cpp index 84bea7248e7a6ee..71f78a5bf770a00 100644 --- a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.general.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.compile.pass.cpp @@ -21,17 +21,13 @@ int main(int, char**) { std::unique_ptr<int> uPtr; auto outUPtr1 = std::out_ptr(uPtr); - (void)outUPtr1; auto outUPtr2 = std::out_ptr<int*>(uPtr); - (void)outUPtr2; } { std::shared_ptr<int> sPtr; auto outSPtr1 = std::out_ptr(sPtr, [](auto* p) { delete p; }); - (void)outSPtr1; auto outSPtr2 = std::out_ptr<int*>(sPtr, [](auto* p) { delete p; }); - (void)outSPtr2; } return 0; diff --git a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.general.cpp similarity index 100% rename from libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.pass.cpp rename to libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.general.cpp diff --git a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.convert.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.convert.pass.cpp new file mode 100644 index 000000000000000..1e19d1ee5b4ec02 --- /dev/null +++ b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.t.convert.pass.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// 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++03, c++11, c++14, c++17, c++20 + +// <memory> + +// [out.ptr.t], class template out_ptr_t +// template<class Smart, class Pointer, class... Args> +// class out_ptr_t; // since c++23 + +// operator Pointer*() const noexcept; +// operator void**() const noexcept; + +#include <cassert> +#include <concepts> +#include <memory> +#include <iostream> + +int main(int, char**) { + { + std::unique_ptr<int> uPtr; + + const std::out_ptr_t<std::unique_ptr<int>, int*> oPtr{uPtr}; + + static_assert(noexcept(oPtr.operator int**())); + std::same_as<int**> decltype(auto) pPtr = oPtr.operator int**(); + + assert(*pPtr == nullptr); + } + { + std::unique_ptr<int, std::default_delete<int>> uPtr; + + const std::out_ptr_t<decltype(uPtr), int*, std::default_delete<int>> oPtr{uPtr, std::default_delete<int>{}}; + + static_assert(noexcept(oPtr.operator int**())); + std::same_as<int**> decltype(auto) pPtr = oPtr.operator int**(); + + assert(*pPtr == nullptr); + } + { + std::unique_ptr<int> uPtr; + + const std::out_ptr_t<std::unique_ptr<int>, void*> oPtr{uPtr}; + + static_assert(noexcept(oPtr.operator void**())); + std::same_as<void**> decltype(auto) pPtr = oPtr.operator void**(); + + assert(*pPtr == nullptr); + } + + return 0; +} >From cb71ea2e2942a85b85712a877f994b6189efd83b Mon Sep 17 00:00:00 2001 From: Hristo Hristov <zin...@outlook.com> Date: Thu, 30 Nov 2023 15:04:52 +0200 Subject: [PATCH 4/4] Removed tests files --- .../inout.ptr/inout.ptr.compile.pass.cpp | 35 ------------------- .../adapt/out.ptr/out.ptr.compile.pass.cpp | 34 ------------------ 2 files changed, 69 deletions(-) delete mode 100644 libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.compile.pass.cpp delete mode 100644 libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.compile.pass.cpp diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.compile.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.compile.pass.cpp deleted file mode 100644 index d2eb8c3a6ac0081..000000000000000 --- a/libcxx/test/std/utilities/smartptr/adapt/inout.ptr/inout.ptr.compile.pass.cpp +++ /dev/null @@ -1,35 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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++03, c++11, c++14, c++17, c++20 - -// <memory> - -// [inout.ptr], function template inout_ptr -// template<class Pointer = void, class Smart, class... Args> -// auto inout_ptr(Smart& s, Args&&... args); // since c++23 - -#include <memory> - -int main(int, char**) { - { - std::unique_ptr<int> uPtr; - - auto inoutUPtr1 = std::inout_ptr(uPtr); - auto inoutUPtr2 = std::inout_ptr<int*>(uPtr); - } - { - auto deleter = [](auto* p) { delete p; }; - std::unique_ptr<int, decltype(deleter)> uPtr; - - auto inoutUPtr1 = std::inout_ptr(uPtr, deleter); - auto inoutUPtr2 = std::inout_ptr<int*>(uPtr, deleter); - } - - return 0; -} diff --git a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.compile.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.compile.pass.cpp deleted file mode 100644 index 71f78a5bf770a00..000000000000000 --- a/libcxx/test/std/utilities/smartptr/adapt/out.ptr/out.ptr.compile.pass.cpp +++ /dev/null @@ -1,34 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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++03, c++11, c++14, c++17, c++20 - -// <memory> - -// [out.ptr], function template out_ptr -// template<class Pointer = void, class Smart, class... Args> -// auto out_ptr(Smart& s, Args&&... args); // since c++23 - -#include <memory> - -int main(int, char**) { - { - std::unique_ptr<int> uPtr; - - auto outUPtr1 = std::out_ptr(uPtr); - auto outUPtr2 = std::out_ptr<int*>(uPtr); - } - { - std::shared_ptr<int> sPtr; - - auto outSPtr1 = std::out_ptr(sPtr, [](auto* p) { delete p; }); - auto outSPtr2 = std::out_ptr<int*>(sPtr, [](auto* p) { delete p; }); - } - - return 0; -} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits