[libcxx-commits] [libcxx] 7d78ccf - [libc++][memory] P2652R2: Disallow Specialization of `allocator_traits` (#79978)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Feb 1 03:31:29 PST 2024


Author: Hristo Hristov
Date: 2024-02-01T12:31:25+01:00
New Revision: 7d78ccf7d5a9861839126d5899b443f55236cab9

URL: https://github.com/llvm/llvm-project/commit/7d78ccf7d5a9861839126d5899b443f55236cab9
DIFF: https://github.com/llvm/llvm-project/commit/7d78ccf7d5a9861839126d5899b443f55236cab9.diff

LOG: [libc++][memory] P2652R2: Disallow Specialization of `allocator_traits` (#79978)

Implements P2652R2 <https://wg21.link/P2652R2>:
- https://eel.is/c++draft/allocator.requirements.general
- https://eel.is/c++draft/memory.syn
- https://eel.is/c++draft/allocator.traits.general
- https://eel.is/c++draft/allocator.traits.members
- https://eel.is/c++draft/diff.cpp20.concepts
- https://eel.is/c++draft/diff.cpp20.utilities

---------

Co-authored-by: Zingam <zingam at outlook.com>

Added: 
    libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate_at_least.pass.cpp

Modified: 
    libcxx/docs/FeatureTestMacroTable.rst
    libcxx/docs/ReleaseNotes/19.rst
    libcxx/docs/Status/Cxx23Papers.csv
    libcxx/docs/Status/Cxx2cIssues.csv
    libcxx/include/__memory/allocate_at_least.h
    libcxx/include/__memory/allocator_traits.h
    libcxx/include/memory
    libcxx/include/version
    libcxx/modules/std/memory.inc
    libcxx/test/std/language.support/support.limits/support.limits.general/memory.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: 
    libcxx/test/std/utilities/memory/allocator.traits/allocate_at_least.pass.cpp


################################################################################
diff  --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index d0d057e6bbaf0..a5c6fa22cec06 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -304,7 +304,7 @@ Status
     ---------------------------------------------------------------------
     ``__cpp_lib_adaptor_iterator_pair_constructor``     ``202106L``
     --------------------------------------------------- -----------------
-    ``__cpp_lib_allocate_at_least``                     ``202106L``
+    ``__cpp_lib_allocate_at_least``                     ``202302L``
     --------------------------------------------------- -----------------
     ``__cpp_lib_associative_heterogeneous_erasure``     *unimplemented*
     --------------------------------------------------- -----------------

diff  --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index e96abc72c1648..db731de2e4399 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -37,7 +37,9 @@ What's New in Libc++ 19.0.0?
 
 Implemented Papers
 ------------------
+
 - P2637R3 - Member ``visit``
+- P2652R2 - Disallow User Specialization of ``allocator_traits``
 
 
 Improvements and New Features

diff  --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index ebab3ef735b61..eb415ed8c031f 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -115,7 +115,7 @@
 "`P2679R2 <https://wg21.link/P2679R2>`__","LWG", "Fixing ``std::start_lifetime_as`` for arrays","February 2023","","",""
 "`P2674R1 <https://wg21.link/P2674R1>`__","LWG", "A trait for implicit lifetime types","February 2023","","",""
 "`P2655R3 <https://wg21.link/P2655R3>`__","LWG", "``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type","February 2023","","",""
-"`P2652R2 <https://wg21.link/P2652R2>`__","LWG", "Disallow User Specialization of ``allocator_traits``","February 2023","","",""
+"`P2652R2 <https://wg21.link/P2652R2>`__","LWG", "Disallow User Specialization of ``allocator_traits``","February 2023","|Complete|","19.0",""
 "`P2787R1 <https://wg21.link/P2787R1>`__","LWG", "``pmr::generator`` - Promise Types are not Values","February 2023","","",""
 "`P2614R2 <https://wg21.link/P2614R2>`__","LWG", "Deprecate ``numeric_limits::has_denorm``","February 2023","|Complete|","18.0",""
 "`P2588R3 <https://wg21.link/P2588R3>`__","LWG", "``barrier``’s phase completion guarantees","February 2023","","",""

diff  --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index b69b094832541..58e995809777c 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -2,7 +2,7 @@
 "`2994 <https://wg21.link/LWG2994>`__","Needless UB for ``basic_string`` and ``basic_string_view``","Varna June 2023","|Complete|","5.0",""
 "`3884 <https://wg21.link/LWG3884>`__","``flat_foo`` is missing allocator-extended copy/move constructors","Varna June 2023","","","|flat_containers|"
 "`3885 <https://wg21.link/LWG3885>`__","``op`` should be in [zombie.names]","Varna June 2023","|Nothing To Do|","",""
-"`3887 <https://wg21.link/LWG3887>`__","Version macro for ``allocate_at_least``","Varna June 2023","","",""
+"`3887 <https://wg21.link/LWG3887>`__","Version macro for ``allocate_at_least``","Varna June 2023","|Complete|","19.0",""
 "`3893 <https://wg21.link/LWG3893>`__","LWG 3661 broke ``atomic<shared_ptr<T>> a; a = nullptr;``","Varna June 2023","","",""
 "`3894 <https://wg21.link/LWG3894>`__","``generator::promise_type::yield_value(ranges::elements_of<Rng, Alloc>)`` should not be ``noexcept``","Varna June 2023","","",""
 "`3903 <https://wg21.link/LWG3903>`__","span destructor is redundantly noexcept","Varna June 2023","|Complete|","7.0",""

diff  --git a/libcxx/include/__memory/allocate_at_least.h b/libcxx/include/__memory/allocate_at_least.h
index 05cbdee828839..b2e5dd3ff98a0 100644
--- a/libcxx/include/__memory/allocate_at_least.h
+++ b/libcxx/include/__memory/allocate_at_least.h
@@ -20,28 +20,14 @@
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 23
-template <class _Pointer>
-struct allocation_result {
-  _Pointer ptr;
-  size_t count;
-};
-_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(allocation_result);
-
-template <class _Alloc>
-[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr allocation_result<typename allocator_traits<_Alloc>::pointer>
-allocate_at_least(_Alloc& __alloc, size_t __n) {
-  if constexpr (requires { __alloc.allocate_at_least(__n); }) {
-    return __alloc.allocate_at_least(__n);
-  } else {
-    return {__alloc.allocate(__n), __n};
-  }
-}
 
 template <class _Alloc>
 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto __allocate_at_least(_Alloc& __alloc, size_t __n) {
-  return std::allocate_at_least(__alloc, __n);
+  return std::allocator_traits<_Alloc>::allocate_at_least(__alloc, __n);
 }
+
 #else
+
 template <class _Pointer>
 struct __allocation_result {
   _Pointer ptr;

diff  --git a/libcxx/include/__memory/allocator_traits.h b/libcxx/include/__memory/allocator_traits.h
index c4482872ea810..3c7fc863b77bc 100644
--- a/libcxx/include/__memory/allocator_traits.h
+++ b/libcxx/include/__memory/allocator_traits.h
@@ -22,6 +22,7 @@
 #include <__type_traits/void_t.h>
 #include <__utility/declval.h>
 #include <__utility/forward.h>
+#include <cstddef>
 #include <limits>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -231,6 +232,17 @@ struct __has_select_on_container_copy_construction<
 
 _LIBCPP_SUPPRESS_DEPRECATED_POP
 
+#if _LIBCPP_STD_VER >= 23
+
+template <class _Pointer, class _SizeType = size_t>
+struct allocation_result {
+  _Pointer ptr;
+  _SizeType count;
+};
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(allocation_result);
+
+#endif // _LIBCPP_STD_VER
+
 template <class _Alloc>
 struct _LIBCPP_TEMPLATE_VIS allocator_traits {
   using allocator_type     = _Alloc;
@@ -284,6 +296,18 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits {
     return __a.allocate(__n);
   }
 
+#if _LIBCPP_STD_VER >= 23
+  template <class _Ap = _Alloc>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr allocation_result<pointer, size_type>
+  allocate_at_least(_Ap& __alloc, size_type __n) {
+    if constexpr (requires { __alloc.allocate_at_least(__n); }) {
+      return __alloc.allocate_at_least(__n);
+    } else {
+      return {__alloc.allocate(__n), __n};
+    }
+  }
+#endif
+
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void
   deallocate(allocator_type& __a, pointer __p, size_type __n) _NOEXCEPT {
     __a.deallocate(__p, __n);

diff  --git a/libcxx/include/memory b/libcxx/include/memory
index 19c11ee949872..0ada7cdfa2069 100644
--- a/libcxx/include/memory
+++ b/libcxx/include/memory
@@ -88,6 +88,9 @@ struct allocator_traits
     static pointer allocate(allocator_type& a, size_type n);                          // constexpr and [[nodiscard]] in C++20
     static pointer allocate(allocator_type& a, size_type n, const_void_pointer hint); // constexpr and [[nodiscard]] in C++20
 
+    [[nodiscard]] static constexpr allocation_result<pointer, size_type>
+      allocate_at_least(Alloc& a, size_type n);                                 // Since C++23
+
     static void deallocate(allocator_type& a, pointer p, size_type n) noexcept; // constexpr in C++20
 
     template <class T, class... Args>
@@ -100,15 +103,11 @@ struct allocator_traits
     static allocator_type select_on_container_copy_construction(const allocator_type& a); // constexpr in C++20
 };
 
-template<class Pointer>
+template<class Pointer, class SizeType = size_t>
 struct allocation_result {
     Pointer ptr;
-    size_t count;
-}; // since C++23
-
-template<class Allocator>
-[[nodiscard]] constexpr allocation_result<typename allocator_traits<Allocator>::pointer>
-    allocate_at_least(Allocator& a, size_t n); // since C++23
+    SizeType count;
+}; // Since C++23
 
 template <>
 class allocator<void> // removed in C++20

diff  --git a/libcxx/include/version b/libcxx/include/version
index 9e26da8c1b242..e4dbb7bdd5fc2 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -16,7 +16,7 @@
 Macro name                                              Value   Headers
 __cpp_lib_adaptor_iterator_pair_constructor             202106L <queue> <stack>
 __cpp_lib_addressof_constexpr                           201603L <memory>
-__cpp_lib_allocate_at_least                             202106L <memory>
+__cpp_lib_allocate_at_least                             202302L <memory>
 __cpp_lib_allocator_traits_is_always_equal              201411L <deque> <forward_list> <list>
                                                                 <map> <memory> <scoped_allocator>
                                                                 <set> <string> <unordered_map>
@@ -433,7 +433,7 @@ __cpp_lib_within_lifetime                               202306L <type_traits>
 
 #if _LIBCPP_STD_VER >= 23
 # define __cpp_lib_adaptor_iterator_pair_constructor    202106L
-# define __cpp_lib_allocate_at_least                    202106L
+# define __cpp_lib_allocate_at_least                    202302L
 // # define __cpp_lib_associative_heterogeneous_erasure    202110L
 // # define __cpp_lib_bind_back                            202202L
 # define __cpp_lib_byteswap                             202110L

diff  --git a/libcxx/modules/std/memory.inc b/libcxx/modules/std/memory.inc
index ef89845457fbb..56c621c0cf17f 100644
--- a/libcxx/modules/std/memory.inc
+++ b/libcxx/modules/std/memory.inc
@@ -43,8 +43,6 @@ export namespace std {
 
 #if _LIBCPP_STD_VER >= 23
   using std::allocation_result;
-
-  using std::allocate_at_least;
 #endif
 
   // [default.allocator], the default allocator

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 b1f6c76d84739..45d9271faa578 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
@@ -17,7 +17,7 @@
 
 /*  Constant                                      Value
     __cpp_lib_addressof_constexpr                 201603L [C++17]
-    __cpp_lib_allocate_at_least                   202106L [C++23]
+    __cpp_lib_allocate_at_least                   202302L [C++23]
     __cpp_lib_allocator_traits_is_always_equal    201411L [C++17]
     __cpp_lib_assume_aligned                      201811L [C++20]
     __cpp_lib_atomic_value_initialization         201911L [C++20]
@@ -432,8 +432,8 @@
 # ifndef __cpp_lib_allocate_at_least
 #   error "__cpp_lib_allocate_at_least should be defined in c++23"
 # endif
-# if __cpp_lib_allocate_at_least != 202106L
-#   error "__cpp_lib_allocate_at_least should have the value 202106L in c++23"
+# if __cpp_lib_allocate_at_least != 202302L
+#   error "__cpp_lib_allocate_at_least should have the value 202302L in c++23"
 # endif
 
 # ifndef __cpp_lib_allocator_traits_is_always_equal
@@ -569,8 +569,8 @@
 # ifndef __cpp_lib_allocate_at_least
 #   error "__cpp_lib_allocate_at_least should be defined in c++26"
 # endif
-# if __cpp_lib_allocate_at_least != 202106L
-#   error "__cpp_lib_allocate_at_least should have the value 202106L in c++26"
+# if __cpp_lib_allocate_at_least != 202302L
+#   error "__cpp_lib_allocate_at_least should have the value 202302L in c++26"
 # endif
 
 # ifndef __cpp_lib_allocator_traits_is_always_equal

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 c319940fe6e49..29f0ba89330bb 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
@@ -18,7 +18,7 @@
 /*  Constant                                         Value
     __cpp_lib_adaptor_iterator_pair_constructor      202106L [C++23]
     __cpp_lib_addressof_constexpr                    201603L [C++17]
-    __cpp_lib_allocate_at_least                      202106L [C++23]
+    __cpp_lib_allocate_at_least                      202302L [C++23]
     __cpp_lib_allocator_traits_is_always_equal       201411L [C++17]
     __cpp_lib_any                                    201606L [C++17]
     __cpp_lib_apply                                  201603L [C++17]
@@ -4279,8 +4279,8 @@
 # ifndef __cpp_lib_allocate_at_least
 #   error "__cpp_lib_allocate_at_least should be defined in c++23"
 # endif
-# if __cpp_lib_allocate_at_least != 202106L
-#   error "__cpp_lib_allocate_at_least should have the value 202106L in c++23"
+# if __cpp_lib_allocate_at_least != 202302L
+#   error "__cpp_lib_allocate_at_least should have the value 202302L in c++23"
 # endif
 
 # ifndef __cpp_lib_allocator_traits_is_always_equal
@@ -5846,8 +5846,8 @@
 # ifndef __cpp_lib_allocate_at_least
 #   error "__cpp_lib_allocate_at_least should be defined in c++26"
 # endif
-# if __cpp_lib_allocate_at_least != 202106L
-#   error "__cpp_lib_allocate_at_least should have the value 202106L in c++26"
+# if __cpp_lib_allocate_at_least != 202302L
+#   error "__cpp_lib_allocate_at_least should have the value 202302L in c++26"
 # endif
 
 # ifndef __cpp_lib_allocator_traits_is_always_equal

diff  --git a/libcxx/test/std/utilities/memory/allocator.traits/allocate_at_least.pass.cpp b/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate_at_least.pass.cpp
similarity index 91%
rename from libcxx/test/std/utilities/memory/allocator.traits/allocate_at_least.pass.cpp
rename to libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate_at_least.pass.cpp
index ad9a2381cbfa1..88ae44c627584 100644
--- a/libcxx/test/std/utilities/memory/allocator.traits/allocate_at_least.pass.cpp
+++ b/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate_at_least.pass.cpp
@@ -39,22 +39,22 @@ struct has_allocate_at_least {
 
   constexpr T* allocate(std::size_t) { return &t1; }
   constexpr void deallocate(T*, std::size_t) {}
-  constexpr std::allocation_result<T*> allocate_at_least(std::size_t) {
-    return {&t2, 2};
-  }
+  constexpr std::allocation_result<T*> allocate_at_least(std::size_t) { return {&t2, 2}; }
 };
 
 constexpr bool test() {
   { // check that std::allocate_at_least forwards to allocator::allocate if no allocate_at_least exists
     no_allocate_at_least<int> alloc;
-    std::same_as<std::allocation_result<int*>> decltype(auto) ret = std::allocate_at_least(alloc, 1);
+    std::same_as<std::allocation_result<int*>> decltype(auto) ret =
+        std::allocator_traits<decltype(alloc)>::allocate_at_least(alloc, 1);
     assert(ret.count == 1);
     assert(ret.ptr == &alloc.t);
   }
 
   { // check that std::allocate_at_least forwards to allocator::allocate_at_least if allocate_at_least exists
     has_allocate_at_least<int> alloc;
-    std::same_as<std::allocation_result<int*>> decltype(auto) ret = std::allocate_at_least(alloc, 1);
+    std::same_as<std::allocation_result<int*>> decltype(auto) ret =
+        std::allocator_traits<decltype(alloc)>::allocate_at_least(alloc, 1);
     assert(ret.count == 2);
     assert(ret.ptr == &alloc.t2);
   }

diff  --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 065b70620cd17..6078e811c8e1e 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -88,9 +88,8 @@ def add_version_header(tc):
         {
             "name": "__cpp_lib_allocate_at_least",
             "values": {
-                "c++23": 202106,
                 # Note LWG3887 Version macro for allocate_at_least
-                # "c++26": 202302, # P2652R2 Disallow User Specialization of allocator_traits
+                "c++23": 202302,  # P2652R2 Disallow User Specialization of allocator_traits
             },
             "headers": ["memory"],
         },


        


More information about the libcxx-commits mailing list