diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -260,7 +260,7 @@ ------------------------------------------------- ----------------- ``__cpp_lib_math_constants`` ``201907L`` ------------------------------------------------- ----------------- - ``__cpp_lib_polymorphic_allocator`` *unimplemented* + ``__cpp_lib_polymorphic_allocator`` ``201902L`` ------------------------------------------------- ----------------- ``__cpp_lib_ranges`` ``201811L`` ------------------------------------------------- ----------------- diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -48,6 +48,7 @@ - P0482R6 - char8_t: A type for UTF-8 characters and strings - P2438R2 - ``std::string::substr() &&`` - P0600R1 - ``nodiscard`` in the library +- P0339R6 - ``polymorphic_allocator<>`` as a vocabulary type Improvements and New Features ----------------------------- diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv --- a/libcxx/docs/Status/Cxx20Issues.csv +++ b/libcxx/docs/Status/Cxx20Issues.csv @@ -201,7 +201,7 @@ "`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","","" -"`3237 `__","LWG 3038 and 3190 have inconsistent PRs","Prague","|Complete|","14.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|","Clang 14","|format|" "`3243 `__","``std::format``\ and negative zeroes","Prague","|Complete|","14.0","|format|" @@ -232,9 +232,9 @@ "`3301 `__","``transform_view::iterator``\ has incorrect ``iterator_category``\ ","Prague","|Complete|","15.0","|ranges|" "`3302 `__","Range adaptor objects ``keys``\ and ``values``\ are unspecified","Prague","","","|ranges|" "`3303 `__","Bad ""``constexpr``\ "" marker for ``destroy/destroy_n``\ ","Prague","","" -"`3304 `__","Allocate functions of ``std::polymorphic_allocator``\ should require ``[[nodiscard]]``\ ","Prague","","" +"`3304 `__","Allocate functions of ``std::polymorphic_allocator``\ should require ``[[nodiscard]]``\ ","Prague","|Complete|","16.0" "`3307 `__","``std::allocator().allocate(n)``\ ","Prague","","" -"`3310 `__","Replace ``SIZE_MAX``\ with ``numeric_limits::max()``\ ","Prague","","" +"`3310 `__","Replace ``SIZE_MAX``\ with ``numeric_limits::max()``\ ","Prague","|Complete|","16.0" "`3313 `__","``join_view::iterator::operator--``\ is incorrectly constrained","Prague","|Complete|","14.0","|ranges|" "`3314 `__","Is stream insertion behavior locale dependent when ``Period::type``\ is ``micro``\ ?","Prague","|Complete|","16.0","|chrono|" "`3315 `__","Correct Allocator Default Behavior","Prague","","" diff --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv --- a/libcxx/docs/Status/Cxx20Papers.csv +++ b/libcxx/docs/Status/Cxx20Papers.csv @@ -80,7 +80,7 @@ "`P1285R0 `__","LWG","Improving Completeness Requirements for Type Traits","San Diego","* *","" "`P1353R0 `__","CWG","Missing feature test macros","San Diego","* *","" "","","","","","" -"`P0339R6 `__","LWG","polymorphic_allocator<> as a vocabulary type","Kona","","" +"`P0339R6 `__","LWG","polymorphic_allocator<> as a vocabulary type","Kona","|Complete|","16.0" "`P0340R3 `__","LWG","Making std::underlying_type SFINAE-friendly","Kona","|Complete|","9.0" "`P0738R2 `__","LWG","I Stream, You Stream, We All Stream for istream_iterator","Kona","","" "`P0811R3 `__","LWG","Well-behaved interpolation for numbers and pointers","Kona","|Complete|","9.0" diff --git a/libcxx/include/__memory_resource/polymorphic_allocator.h b/libcxx/include/__memory_resource/polymorphic_allocator.h --- a/libcxx/include/__memory_resource/polymorphic_allocator.h +++ b/libcxx/include/__memory_resource/polymorphic_allocator.h @@ -12,6 +12,7 @@ #include <__assert> #include <__config> #include <__memory_resource/memory_resource.h> +#include <__utility/transaction.h> #include #include #include @@ -33,8 +34,13 @@ // [mem.poly.allocator.class] -template +template = 20 + = byte +# endif + > class _LIBCPP_TEMPLATE_VIS polymorphic_allocator { + public: using value_type = _ValueType; @@ -66,6 +72,46 @@ __res_->deallocate(__p, __n * sizeof(_ValueType), alignof(_ValueType)); } +# if _LIBCPP_STD_VER >= 20 + + [[nodiscard]] [[using __gnu__: __alloc_size__(2), __alloc_align__(3)]] void* + allocate_bytes(size_t __nbytes, size_t __alignment = alignof(max_align_t)) { + return __res_->allocate(__nbytes, __alignment); + } + + void deallocate_bytes(void* __ptr, size_t __nbytes, size_t __alignment = alignof(max_align_t)) { + __res_->deallocate(__ptr, __nbytes, __alignment); + } + + template + [[nodiscard]] _Type* allocate_object(size_t __n = 1) { + if (numeric_limits::max() / sizeof(_Type) < __n) + std::__throw_bad_array_new_length(); + return static_cast<_Type*>(allocate_bytes(__n * sizeof(_Type), alignof(_Type))); + } + + template + void deallocate_object(_Type* __ptr, size_t __n = 1) { + deallocate_bytes(__ptr, __n * sizeof(_Type), alignof(_Type)); + } + + template + [[nodiscard]] _Type* new_object(_CtorArgs&&... __ctor_args) { + _Type* __ptr = allocate_object<_Type>(); + __transaction __guard([&] { deallocate_object(__ptr); }); + construct(__ptr, std::forward<_CtorArgs>(__ctor_args)...); + __guard.__complete(); + return __ptr; + } + + template + void delete_object(_Type* __ptr) { + destroy(__ptr); + deallocate_object(__ptr); + } + +# endif // _LIBCPP_STD_VER >= 20 + template _LIBCPP_HIDE_FROM_ABI void construct(_Tp* __p, _Ts&&... __args) { std::__user_alloc_construct_impl( diff --git a/libcxx/include/__utility/exchange.h b/libcxx/include/__utility/exchange.h --- a/libcxx/include/__utility/exchange.h +++ b/libcxx/include/__utility/exchange.h @@ -10,9 +10,10 @@ #define _LIBCPP___UTILITY_EXCHANGE_H #include <__config> +#include <__type_traits/is_nothrow_assignable.h> +#include <__type_traits/is_nothrow_move_constructible.h> #include <__utility/forward.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__utility/move.h b/libcxx/include/__utility/move.h --- a/libcxx/include/__utility/move.h +++ b/libcxx/include/__utility/move.h @@ -11,7 +11,10 @@ #define _LIBCPP___UTILITY_MOVE_H #include <__config> -#include +#include <__type_traits/conditional.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/remove_reference.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__utility/transaction.h b/libcxx/include/__utility/transaction.h --- a/libcxx/include/__utility/transaction.h +++ b/libcxx/include/__utility/transaction.h @@ -10,9 +10,9 @@ #define _LIBCPP___UTILITY_TRANSACTION_H #include <__config> +#include <__type_traits/is_nothrow_move_constructible.h> #include <__utility/exchange.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/experimental/iterator b/libcxx/include/experimental/iterator --- a/libcxx/include/experimental/iterator +++ b/libcxx/include/experimental/iterator @@ -118,4 +118,8 @@ #endif // _LIBCPP_STD_VER > 11 +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include +#endif + #endif // _LIBCPP_EXPERIMENTAL_ITERATOR diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -354,7 +354,7 @@ # endif # define __cpp_lib_list_remove_return_type 201806L # define __cpp_lib_math_constants 201907L -// # define __cpp_lib_polymorphic_allocator 201902L +# define __cpp_lib_polymorphic_allocator 201902L # define __cpp_lib_ranges 201811L # define __cpp_lib_remove_cvref 201711L # if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore) diff --git a/libcxx/test/libcxx/transitive_includes/cxx2b.csv b/libcxx/test/libcxx/transitive_includes/cxx2b.csv --- a/libcxx/test/libcxx/transitive_includes/cxx2b.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx2b.csv @@ -189,7 +189,6 @@ experimental/iterator cstddef experimental/iterator iosfwd experimental/iterator iterator -experimental/iterator type_traits experimental/list experimental/memory_resource experimental/list list experimental/map experimental/memory_resource diff --git a/libcxx/test/libcxx/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate_vocabulary.attributes.verify.cpp b/libcxx/test/libcxx/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate_vocabulary.attributes.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate_vocabulary.attributes.verify.cpp @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// check that clang warns on non-power-of-two alignment + +#include + +void func() { + std::pmr::polymorphic_allocator<> allocator; + (void)allocator.allocate_bytes(0, 3); // expected-warning {{requested alignment is not a power of 2}} + +} diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/memory_resource.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/memory_resource.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/memory_resource.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/memory_resource.version.compile.pass.cpp @@ -65,17 +65,11 @@ # error "__cpp_lib_memory_resource should have the value 201603L in c++20" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_polymorphic_allocator -# error "__cpp_lib_polymorphic_allocator should be defined in c++20" -# endif -# if __cpp_lib_polymorphic_allocator != 201902L -# error "__cpp_lib_polymorphic_allocator should have the value 201902L in c++20" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_polymorphic_allocator -# error "__cpp_lib_polymorphic_allocator should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_polymorphic_allocator +# error "__cpp_lib_polymorphic_allocator should be defined in c++20" +# endif +# if __cpp_lib_polymorphic_allocator != 201902L +# error "__cpp_lib_polymorphic_allocator should have the value 201902L in c++20" # endif #elif TEST_STD_VER > 20 @@ -87,17 +81,11 @@ # error "__cpp_lib_memory_resource should have the value 201603L in c++2b" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_polymorphic_allocator -# error "__cpp_lib_polymorphic_allocator should be defined in c++2b" -# endif -# if __cpp_lib_polymorphic_allocator != 201902L -# error "__cpp_lib_polymorphic_allocator should have the value 201902L in c++2b" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_polymorphic_allocator -# error "__cpp_lib_polymorphic_allocator should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_polymorphic_allocator +# error "__cpp_lib_polymorphic_allocator should be defined in c++2b" +# endif +# if __cpp_lib_polymorphic_allocator != 201902L +# error "__cpp_lib_polymorphic_allocator should have the value 201902L in c++2b" # endif #endif // TEST_STD_VER > 20 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 --- 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 @@ -3208,17 +3208,11 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_polymorphic_allocator -# error "__cpp_lib_polymorphic_allocator should be defined in c++20" -# endif -# if __cpp_lib_polymorphic_allocator != 201902L -# error "__cpp_lib_polymorphic_allocator should have the value 201902L in c++20" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_polymorphic_allocator -# error "__cpp_lib_polymorphic_allocator should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_polymorphic_allocator +# error "__cpp_lib_polymorphic_allocator should be defined in c++20" +# endif +# if __cpp_lib_polymorphic_allocator != 201902L +# error "__cpp_lib_polymorphic_allocator should have the value 201902L in c++20" # endif # ifndef __cpp_lib_quoted_string_io @@ -4478,17 +4472,11 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_polymorphic_allocator -# error "__cpp_lib_polymorphic_allocator should be defined in c++2b" -# endif -# if __cpp_lib_polymorphic_allocator != 201902L -# error "__cpp_lib_polymorphic_allocator should have the value 201902L in c++2b" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_polymorphic_allocator -# error "__cpp_lib_polymorphic_allocator should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_polymorphic_allocator +# error "__cpp_lib_polymorphic_allocator should be defined in c++2b" +# endif +# if __cpp_lib_polymorphic_allocator != 201902L +# error "__cpp_lib_polymorphic_allocator should have the value 201902L in c++2b" # endif # ifndef __cpp_lib_quoted_string_io diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate_deallocate_bytes.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate_deallocate_bytes.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate_deallocate_bytes.pass.cpp @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}} +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{11.0|12.0}} + +// test_memory_resource requires RTTI for dynamic_cast +// UNSUPPORTED: no-rtti + +// + +// polymorphic_allocator::allocate_bytes() +// polymorphic_allocator::deallocate_bytes() + +#include +#include +#include +#include + +#include "tracking_mem_res.h" + +template +void test() { + size_t last_size = 0; + size_t last_alignment = 0; + TrackingMemRes resource(&last_size, &last_alignment); + + std::pmr::polymorphic_allocator allocator(&resource); + + { + std::same_as decltype(auto) allocation = allocator.allocate_bytes(13); + auto ptr = static_cast(allocation); + std::fill(ptr, ptr + 13, '0'); + assert(last_size == 13); + assert(last_alignment == alignof(max_align_t)); + allocator.deallocate_bytes(allocation, 13); + assert(last_size == 13); + assert(last_alignment == alignof(max_align_t)); + } + { + void* allocation = allocator.allocate_bytes(13, 64); + auto ptr = static_cast(allocation); + std::fill(ptr, ptr + 13, '0'); + assert(last_size == 13); + assert(last_alignment == 64); + allocator.deallocate_bytes(allocation, 13, 64); + assert(last_size == 13); + assert(last_alignment == 64); + } +} + +struct S {}; + +int main(int, char**) { + test(); + test(); + + return 0; +} diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate_deallocate_object.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate_deallocate_object.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate_deallocate_object.pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}} +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{11.0|12.0}} + +// test_memory_resource requires RTTI for dynamic_cast +// UNSUPPORTED: no-rtti + +// + +// polymorphic_allocator::allocate_object() +// polymorphic_allocator::deallocate_object() + +#include +#include +#include +#include + +#include "tracking_mem_res.h" + +template +void test() { + size_t last_size = 0; + size_t last_alignment = 0; + TrackingMemRes resource(&last_size, &last_alignment); + + std::pmr::polymorphic_allocator allocator(&resource); + + { + std::same_as decltype(auto) allocation = allocator.template allocate_object(); + std::fill(allocation, allocation + 1, 3); + assert(last_size == sizeof(int)); + assert(last_alignment == alignof(int)); + allocator.deallocate_object(allocation); + assert(last_size == sizeof(int)); + assert(last_alignment == alignof(int)); + } + { + int* allocation = allocator.template allocate_object(3); + std::fill(allocation, allocation + 3, 3); + assert(last_size == sizeof(int) * 3); + assert(last_alignment == alignof(int)); + allocator.deallocate_object(allocation, 3); + assert(last_size == sizeof(int) * 3); + assert(last_alignment == alignof(int)); + } +} + +struct S {}; + +int main(int, char**) { + test(); + test(); + + return 0; +} diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate_deallocate_vocabulary.nodiscard.verify.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate_deallocate_vocabulary.nodiscard.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate_deallocate_vocabulary.nodiscard.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 +// +//===----------------------------------------------------------------------===// + +// check that functions are marked [[nodiscard]] + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// test_memory_resource requires RTTI for dynamic_cast +// UNSUPPORTED: no-rtti + +// + +// polymorphic_allocator::allocate_bytes() +// polymorphic_allocator::allocate_object() +// polymorphic_allocator::new_object() + +#include + +void func() { + std::pmr::polymorphic_allocator<> allocator; + allocator.allocate_bytes(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + allocator.allocate_object(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + allocator.new_object(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} +} diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/default_type.compile.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/default_type.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/default_type.compile.pass.cpp @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}} +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{11.0|12.0}} + +// test_memory_resource requires RTTI for dynamic_cast +// UNSUPPORTED: no-rtti + +#include +#include + +static_assert(std::is_same_v, std::pmr::polymorphic_allocator>); diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/new_delete_object.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/new_delete_object.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/new_delete_object.pass.cpp @@ -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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}} +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{11.0|12.0}} + +// test_memory_resource requires RTTI for dynamic_cast +// UNSUPPORTED: no-rtti + +// + +// polymorphic_allocator::new_object() +// polymorphic_allocator::delete_object() + +#include +#include +#include +#include + +#include "tracking_mem_res.h" + +template +void test() { + size_t last_size = 0; + size_t last_alignment = 0; + TrackingMemRes resource(&last_size, &last_alignment); + + std::pmr::polymorphic_allocator allocator(&resource); + + { + std::same_as decltype(auto) allocation = allocator.template new_object(); + std::fill(allocation, allocation + 1, 4); + assert(last_size == sizeof(int)); + assert(last_alignment == alignof(int)); + allocator.delete_object(allocation); + } + { + std::same_as decltype(auto) allocation = allocator.template new_object(3); + assert(*allocation == 3); + std::fill(allocation, allocation + 1, 4); + assert(last_size == sizeof(int)); + assert(last_alignment == alignof(int)); + allocator.delete_object(allocation); + } + { + struct TrackConstruction { + bool* is_constructed_; + TrackConstruction(bool* is_constructed) : is_constructed_(is_constructed) { *is_constructed = true; } + ~TrackConstruction() { *is_constructed_ = false; } + }; + + bool is_constructed = false; + + std::same_as decltype(auto) allocation = + allocator.template new_object(&is_constructed); + assert(is_constructed); + assert(last_size == sizeof(TrackConstruction)); + assert(last_alignment == alignof(TrackConstruction)); + allocator.delete_object(allocation); + assert(!is_constructed); + } +} + +struct S {}; + +int main(int, char**) { + test(); + test(); + + return 0; +} diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/tracking_mem_res.h b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/tracking_mem_res.h new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/tracking_mem_res.h @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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 TRACKING_MEM_RES_H +#define TRACKING_MEM_RES_H + +#include + +class TrackingMemRes : public std::pmr::memory_resource { +public: + TrackingMemRes(size_t* last_size, size_t* last_alginment) : last_size_(last_size), last_alginment_(last_alginment) {} + +private: + size_t* last_size_; + size_t* last_alginment_; + void* do_allocate(size_t size, size_t alignment) override { + *last_size_ = size; + *last_alginment_ = alignment; + + return std::pmr::new_delete_resource()->allocate(size, alignment); + } + + void do_deallocate(void* ptr, size_t size, size_t alignment) override { + *last_size_ = size; + *last_alginment_ = alignment; + std::pmr::new_delete_resource()->deallocate(ptr, size, alignment); + } + + bool do_is_equal(const memory_resource& ptr) const noexcept override { return &ptr == this; } +}; + +#endif // TRACKING_MEM_RES_H diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -525,7 +525,6 @@ "name": "__cpp_lib_polymorphic_allocator", "values": { "c++20": 201902 }, "headers": ["memory_resource"], - "unimplemented": True, }, { "name": "__cpp_lib_quoted_string_io", "values": { "c++14": 201304 },