[libcxx-commits] [libcxx] 181cce6 - [libc++] Implement P0339R6 (polymorphic_allocator<> as a vocabulary type)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Dec 7 09:50:31 PST 2022
Author: Nikolas Klauser
Date: 2022-12-07T18:50:26+01:00
New Revision: 181cce6b696e032735fb3e3d23b1db1fb9fca5cb
URL: https://github.com/llvm/llvm-project/commit/181cce6b696e032735fb3e3d23b1db1fb9fca5cb
DIFF: https://github.com/llvm/llvm-project/commit/181cce6b696e032735fb3e3d23b1db1fb9fca5cb.diff
LOG: [libc++] Implement P0339R6 (polymorphic_allocator<> as a vocabulary type)
Reviewed By: ldionne, #libc
Spies: LRFLEW, libcxx-commits, arichardson, krytarowski, jdoerfert
Differential Revision: https://reviews.llvm.org/D137739
Added:
libcxx/test/libcxx/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate_vocabulary.attributes.verify.cpp
libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate_deallocate_bytes.pass.cpp
libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate_deallocate_object.pass.cpp
libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/allocate_deallocate_vocabulary.nodiscard.verify.cpp
libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/default_type.compile.pass.cpp
libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/new_delete_object.pass.cpp
libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/tracking_mem_res.h
Modified:
libcxx/docs/FeatureTestMacroTable.rst
libcxx/docs/ReleaseNotes.rst
libcxx/docs/Status/Cxx20Issues.csv
libcxx/docs/Status/Cxx20Papers.csv
libcxx/include/__memory_resource/polymorphic_allocator.h
libcxx/include/__type_traits/is_nothrow_constructible.h
libcxx/include/__utility/transaction.h
libcxx/include/experimental/iterator
libcxx/include/version
libcxx/test/libcxx/transitive_includes/cxx03.csv
libcxx/test/libcxx/transitive_includes/cxx11.csv
libcxx/test/libcxx/transitive_includes/cxx14.csv
libcxx/test/libcxx/transitive_includes/cxx17.csv
libcxx/test/libcxx/transitive_includes/cxx20.csv
libcxx/test/libcxx/transitive_includes/cxx2b.csv
libcxx/test/std/language.support/support.limits/support.limits.general/memory_resource.version.compile.pass.cpp
libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
libcxx/utils/generate_feature_test_macro_components.py
Removed:
################################################################################
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 5ba070e7a1ea8..a1371267cd32b 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -260,7 +260,7 @@ Status
------------------------------------------------- -----------------
``__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
index f37751b72665f..a04eacbd4ba9f 100644
--- a/libcxx/docs/ReleaseNotes.rst
+++ b/libcxx/docs/ReleaseNotes.rst
@@ -48,6 +48,7 @@ Implemented Papers
- 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
index d1ba4a167fc48..1a51daa0ec641 100644
--- a/libcxx/docs/Status/Cxx20Issues.csv
+++ b/libcxx/docs/Status/Cxx20Issues.csv
@@ -201,7 +201,7 @@
"`3201 <https://wg21.link/LWG3201>`__","``lerp``\ should be marked as ``noexcept``\ ","Prague","|Complete|",""
"`3226 <https://wg21.link/LWG3226>`__","``zoned_time``\ constructor from ``string_view``\ should accept ``zoned_time<Duration2, TimeZonePtr2>``\ ","Prague","","","|chrono|"
"`3233 <https://wg21.link/LWG3233>`__","Broken requirements for ``shared_ptr``\ converting constructors","Prague","",""
-"`3237 <https://wg21.link/LWG3237>`__","LWG 3038 and 3190 have inconsistent PRs","Prague","|Complete|","14.0"
+"`3237 <https://wg21.link/LWG3237>`__","LWG 3038 and 3190 have inconsistent PRs","Prague","|Complete|","16.0"
"`3238 <https://wg21.link/LWG3238>`__","Insufficiently-defined behavior of ``std::function``\ deduction guides","Prague","",""
"`3242 <https://wg21.link/LWG3242>`__","``std::format``\ : missing rules for ``arg-id``\ in ``width``\ and ``precision``\ ","Prague","|Complete|","Clang 14","|format|"
"`3243 <https://wg21.link/LWG3243>`__","``std::format``\ and negative zeroes","Prague","|Complete|","14.0","|format|"
@@ -232,9 +232,9 @@
"`3301 <https://wg21.link/LWG3301>`__","``transform_view::iterator``\ has incorrect ``iterator_category``\ ","Prague","|Complete|","15.0","|ranges|"
"`3302 <https://wg21.link/LWG3302>`__","Range adaptor objects ``keys``\ and ``values``\ are unspecified","Prague","","","|ranges|"
"`3303 <https://wg21.link/LWG3303>`__","Bad ""``constexpr``\ "" marker for ``destroy/destroy_n``\ ","Prague","",""
-"`3304 <https://wg21.link/LWG3304>`__","Allocate functions of ``std::polymorphic_allocator``\ should require ``[[nodiscard]]``\ ","Prague","",""
+"`3304 <https://wg21.link/LWG3304>`__","Allocate functions of ``std::polymorphic_allocator``\ should require ``[[nodiscard]]``\ ","Prague","|Complete|","16.0"
"`3307 <https://wg21.link/LWG3307>`__","``std::allocator<void>().allocate(n)``\ ","Prague","",""
-"`3310 <https://wg21.link/LWG3310>`__","Replace ``SIZE_MAX``\ with ``numeric_limits<size_t>::max()``\ ","Prague","",""
+"`3310 <https://wg21.link/LWG3310>`__","Replace ``SIZE_MAX``\ with ``numeric_limits<size_t>::max()``\ ","Prague","|Complete|","16.0"
"`3313 <https://wg21.link/LWG3313>`__","``join_view::iterator::operator--``\ is incorrectly constrained","Prague","|Complete|","14.0","|ranges|"
"`3314 <https://wg21.link/LWG3314>`__","Is stream insertion behavior locale dependent when ``Period::type``\ is ``micro``\ ?","Prague","|Complete|","16.0","|chrono|"
"`3315 <https://wg21.link/LWG3315>`__","Correct Allocator Default Behavior","Prague","",""
diff --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv
index 70f13a902f9fb..95e3c4cc51493 100644
--- a/libcxx/docs/Status/Cxx20Papers.csv
+++ b/libcxx/docs/Status/Cxx20Papers.csv
@@ -80,7 +80,7 @@
"`P1285R0 <https://wg21.link/P1285R0>`__","LWG","Improving Completeness Requirements for Type Traits","San Diego","* *",""
"`P1353R0 <https://wg21.link/P1353R0>`__","CWG","Missing feature test macros","San Diego","* *",""
"","","","","",""
-"`P0339R6 <https://wg21.link/P0339R6>`__","LWG","polymorphic_allocator<> as a vocabulary type","Kona","",""
+"`P0339R6 <https://wg21.link/P0339R6>`__","LWG","polymorphic_allocator<> as a vocabulary type","Kona","|Complete|","16.0"
"`P0340R3 <https://wg21.link/P0340R3>`__","LWG","Making std::underlying_type SFINAE-friendly","Kona","|Complete|","9.0"
"`P0738R2 <https://wg21.link/P0738R2>`__","LWG","I Stream, You Stream, We All Stream for istream_iterator","Kona","",""
"`P0811R3 <https://wg21.link/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
index a5ca39b57e69d..8e59dfc55d78c 100644
--- 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 <cstddef>
#include <limits>
#include <new>
@@ -33,8 +34,13 @@ namespace pmr {
// [mem.poly.allocator.class]
-template <class _ValueType>
+template <class _ValueType
+# if _LIBCPP_STD_VER >= 20
+ = byte
+# endif
+ >
class _LIBCPP_TEMPLATE_VIS polymorphic_allocator {
+
public:
using value_type = _ValueType;
@@ -66,6 +72,46 @@ class _LIBCPP_TEMPLATE_VIS polymorphic_allocator {
__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 <class _Type>
+ [[nodiscard]] _Type* allocate_object(size_t __n = 1) {
+ if (numeric_limits<size_t>::max() / sizeof(_Type) < __n)
+ std::__throw_bad_array_new_length();
+ return static_cast<_Type*>(allocate_bytes(__n * sizeof(_Type), alignof(_Type)));
+ }
+
+ template <class _Type>
+ void deallocate_object(_Type* __ptr, size_t __n = 1) {
+ deallocate_bytes(__ptr, __n * sizeof(_Type), alignof(_Type));
+ }
+
+ template <class _Type, class... _CtorArgs>
+ [[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 <class _Type>
+ void delete_object(_Type* __ptr) {
+ destroy(__ptr);
+ deallocate_object(__ptr);
+ }
+
+# endif // _LIBCPP_STD_VER >= 20
+
template <class _Tp, class... _Ts>
_LIBCPP_HIDE_FROM_ABI void construct(_Tp* __p, _Ts&&... __args) {
std::__user_alloc_construct_impl(
diff --git a/libcxx/include/__type_traits/is_nothrow_constructible.h b/libcxx/include/__type_traits/is_nothrow_constructible.h
index 6dc6ccd450d88..6272298889be8 100644
--- a/libcxx/include/__type_traits/is_nothrow_constructible.h
+++ b/libcxx/include/__type_traits/is_nothrow_constructible.h
@@ -11,6 +11,9 @@
#include <__config>
#include <__type_traits/integral_constant.h>
+#include <__type_traits/is_constructible.h>
+#include <__type_traits/is_reference.h>
+#include <__utility/declval.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
index dc65c349d13c7..3baedd2baf7b8 100644
--- 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 <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
diff --git a/libcxx/include/experimental/iterator b/libcxx/include/experimental/iterator
index 3e460d6a7f5db..399365ed0c744 100644
--- a/libcxx/include/experimental/iterator
+++ b/libcxx/include/experimental/iterator
@@ -118,4 +118,8 @@ _LIBCPP_END_NAMESPACE_LFTS
#endif // _LIBCPP_STD_VER > 11
+#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
+# include <type_traits>
+#endif
+
#endif // _LIBCPP_EXPERIMENTAL_ITERATOR
diff --git a/libcxx/include/version b/libcxx/include/version
index 5e2b8cd43a998..9443564b0466b 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -354,7 +354,7 @@ __cpp_lib_void_t 201411L <type_traits>
# 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/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv
index e6dcd70c25087..c3eff22f1fee6 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx03.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv
@@ -556,6 +556,7 @@ memory_resource mutex
memory_resource new
memory_resource stdexcept
memory_resource tuple
+memory_resource type_traits
memory_resource version
mutex atomic
mutex concepts
diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv
index 34c2f0f0e8877..0ab039f113f14 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx11.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv
@@ -556,6 +556,7 @@ memory_resource mutex
memory_resource new
memory_resource stdexcept
memory_resource tuple
+memory_resource type_traits
memory_resource version
mutex atomic
mutex concepts
diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv
index 3f4f7879faa59..491b28707c291 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv
@@ -558,6 +558,7 @@ memory_resource mutex
memory_resource new
memory_resource stdexcept
memory_resource tuple
+memory_resource type_traits
memory_resource version
mutex atomic
mutex concepts
diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv
index 3f4f7879faa59..491b28707c291 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv
@@ -558,6 +558,7 @@ memory_resource mutex
memory_resource new
memory_resource stdexcept
memory_resource tuple
+memory_resource type_traits
memory_resource version
mutex atomic
mutex concepts
diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv
index 6462223d630e8..1f3798909e533 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -569,6 +569,7 @@ memory_resource mutex
memory_resource new
memory_resource stdexcept
memory_resource tuple
+memory_resource type_traits
memory_resource version
mutex atomic
mutex concepts
diff --git a/libcxx/test/libcxx/transitive_includes/cxx2b.csv b/libcxx/test/libcxx/transitive_includes/cxx2b.csv
index 18803bc804d3b..bcc949bc4233a 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx2b.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx2b.csv
@@ -438,6 +438,7 @@ memory_resource mutex
memory_resource new
memory_resource stdexcept
memory_resource tuple
+memory_resource type_traits
memory_resource version
mutex atomic
mutex cstddef
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
index 0000000000000..d5cd62ec28b2a
--- /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 <memory_resource>
+
+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
index 53f5e5c38210a..573fd0fbc0a3c 100644
--- 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
index 971bb22523ab1..50632e68e1d66 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
@@ -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
index 0000000000000..a4db295f9ac32
--- /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
+
+// <memory_resource>
+
+// polymorphic_allocator::allocate_bytes()
+// polymorphic_allocator::deallocate_bytes()
+
+#include <algorithm>
+#include <cassert>
+#include <concepts>
+#include <memory_resource>
+
+#include "tracking_mem_res.h"
+
+template <class T>
+void test() {
+ size_t last_size = 0;
+ size_t last_alignment = 0;
+ TrackingMemRes resource(&last_size, &last_alignment);
+
+ std::pmr::polymorphic_allocator<T> allocator(&resource);
+
+ {
+ std::same_as<void*> decltype(auto) allocation = allocator.allocate_bytes(13);
+ auto ptr = static_cast<char*>(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<char*>(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<std::byte>();
+ test<S>();
+
+ 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
index 0000000000000..b061afbbae0f1
--- /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
+
+// <memory_resource>
+
+// polymorphic_allocator::allocate_object()
+// polymorphic_allocator::deallocate_object()
+
+#include <algorithm>
+#include <cassert>
+#include <concepts>
+#include <memory_resource>
+
+#include "tracking_mem_res.h"
+
+template <class T>
+void test() {
+ size_t last_size = 0;
+ size_t last_alignment = 0;
+ TrackingMemRes resource(&last_size, &last_alignment);
+
+ std::pmr::polymorphic_allocator<T> allocator(&resource);
+
+ {
+ std::same_as<int*> decltype(auto) allocation = allocator.template allocate_object<int>();
+ 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<int>(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<std::byte>();
+ test<S>();
+
+ 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
index 0000000000000..f3b0391d37619
--- /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
+
+// <memory_resource>
+
+// polymorphic_allocator::allocate_bytes()
+// polymorphic_allocator::allocate_object()
+// polymorphic_allocator::new_object()
+
+#include <memory_resource>
+
+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<int>(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ allocator.new_object<int>(); // 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
index 0000000000000..67d552ca9d11d
--- /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
+// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}}
+// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{11.0|12.0}}
+
+// test_memory_resource requires RTTI for dynamic_cast
+// UNSUPPORTED: no-rtti
+
+#include <memory_resource>
+#include <type_traits>
+
+static_assert(std::is_same_v<std::pmr::polymorphic_allocator<>, std::pmr::polymorphic_allocator<std::byte>>);
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
index 0000000000000..463a8157e7233
--- /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
+
+// <memory_resource>
+
+// polymorphic_allocator::new_object()
+// polymorphic_allocator::delete_object()
+
+#include <algorithm>
+#include <cassert>
+#include <concepts>
+#include <memory_resource>
+
+#include "tracking_mem_res.h"
+
+template <class T>
+void test() {
+ size_t last_size = 0;
+ size_t last_alignment = 0;
+ TrackingMemRes resource(&last_size, &last_alignment);
+
+ std::pmr::polymorphic_allocator<T> allocator(&resource);
+
+ {
+ std::same_as<int*> decltype(auto) allocation = allocator.template new_object<int>();
+ std::fill(allocation, allocation + 1, 4);
+ assert(last_size == sizeof(int));
+ assert(last_alignment == alignof(int));
+ allocator.delete_object(allocation);
+ }
+ {
+ std::same_as<int*> decltype(auto) allocation = allocator.template new_object<int>(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<TrackConstruction*> decltype(auto) allocation =
+ allocator.template new_object<TrackConstruction>(&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<std::byte>();
+ test<S>();
+
+ 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
index 0000000000000..d0b9eab578092
--- /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 <memory_resource>
+
+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
index 85629e11755e4..81086993a5f49 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -525,7 +525,6 @@ def add_version_header(tc):
"name": "__cpp_lib_polymorphic_allocator",
"values": { "c++20": 201902 },
"headers": ["memory_resource"],
- "unimplemented": True,
}, {
"name": "__cpp_lib_quoted_string_io",
"values": { "c++14": 201304 },
More information about the libcxx-commits
mailing list