[PATCH] libstdc++: Reject user-defined specializations for allocator traits.

Tomasz Kamiński <[email protected]>
Newsgroups gmane.comp.gcc.patches,gmane.comp.gcc.libstdc++.devel
Message-ID <[email protected]>
Mark allocator_traits primary tempalte with [[_Clang::__no_specializations]]
attribute in C++23 or later.

This is QoI improvement for C++23 P2652R2, "Disallow User Specialization
of allocator_traits", that makes such cases ill-formed, but does not
require diagnostic.

libstdc++-v3/ChangeLog:

	* include/bits/alloc_traits.h
	(_GLIBCXX_NO_ALLOC_TRAITS_SPECIALIZATIONS): Define locally.
	(std::allocator_traits) [__cplusplus > 202002L]: Add
	clang::no_specializations attribute.
	(std::allocator_traits<allocator<_Tp>>)
	(std::allocator_traits<allocator<void>>): Locally ignore
	-Winvalid-specialization warnings.
	* include/bits/memory_resource.h
	(allocator_traits<pmr::polymorphic_allocator<_Tp>>): Likewise.
	* testsuite/20_util/allocator_traits/requirements/specializations_neg.cc:
	New test.
---
Went for _GLIBCXX_NO_ALLOC_TRAITS_SPECIALIZATIONS defined locally,
instead of something akin _GLIBCXX23_NO_SPECIALIZATIONS, as I do not
think we will have many conditionally enabled attributes.

Tested on x86_64-linux locally. OK for trunk?

 libstdc++-v3/include/bits/alloc_traits.h      | 15 ++++++++++++++-
 libstdc++-v3/include/bits/memory_resource.h   |  4 ++++
 .../requirements/specializations_neg.cc       | 19 +++++++++++++++++++
 3 files changed, 37 insertions(+), 1 deletion(-)
 create mode 100644 libstdc++-v3/testsuite/20_util/allocator_traits/requirements/specializations_neg.cc

diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h
index 101badff454..c113f798690 100644
--- a/libstdc++-v3/include/bits/alloc_traits.h
+++ b/libstdc++-v3/include/bits/alloc_traits.h
@@ -239,6 +239,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
   /// @endcond
 
+#if __cplusplus > 202002L
+# define _GLIBCXX_NO_ALLOC_TRAITS_SPECIALIZATIONS _GLIBCXX_NO_SPECIALIZATIONS
+#else
+# define _GLIBCXX_NO_ALLOC_TRAITS_SPECIALIZATIONS
+#endif
+
   /**
    * @brief  Uniform interface to all allocator types.
    * @headerfile memory
@@ -246,7 +252,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    * @since C++11
   */
   template<typename _Alloc>
-    struct allocator_traits : __allocator_traits_base
+    struct _GLIBCXX_NO_ALLOC_TRAITS_SPECIALIZATIONS allocator_traits
+    : __allocator_traits_base
     {
       /// The allocator type
       typedef _Alloc allocator_type;
@@ -571,7 +578,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     };
 #pragma GCC diagnostic pop
 
+#undef _GLIBCXX_NO_ALLOC_TRAITS_SPECIALIZATIONS
+
 #if _GLIBCXX_HOSTED
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Winvalid-specialization"
+ 
   /**
    * @brief  Partial specialization for `std::allocator`
    * @headerfile memory
@@ -876,6 +888,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       select_on_container_copy_construction(const allocator_type& __rhs)
       { return __rhs; }
     };
+#pragma GCC diagnostic pop
 #endif // _GLIBCXX_HOSTED
 
   /// @cond undocumented
diff --git a/libstdc++-v3/include/bits/memory_resource.h b/libstdc++-v3/include/bits/memory_resource.h
index a9db58b76a3..801184c1bbc 100644
--- a/libstdc++-v3/include/bits/memory_resource.h
+++ b/libstdc++-v3/include/bits/memory_resource.h
@@ -388,6 +388,9 @@ namespace pmr
 
   template<typename _Alloc> struct allocator_traits;
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Winvalid-specialization"
+
   /// Partial specialization for `std::pmr::polymorphic_allocator`
   /**
    * @ingroup pmr
@@ -534,6 +537,7 @@ namespace pmr
       max_size(const allocator_type&) noexcept
       { return size_t(-1) / sizeof(value_type); }
     };
+#pragma GCC diagnostic pop
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
diff --git a/libstdc++-v3/testsuite/20_util/allocator_traits/requirements/specializations_neg.cc b/libstdc++-v3/testsuite/20_util/allocator_traits/requirements/specializations_neg.cc
new file mode 100644
index 00000000000..1a46d8793f0
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/allocator_traits/requirements/specializations_neg.cc
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++11 } }
+
+#include <memory>
+
+template<typename T> struct Alloc : std::allocator<T>
+{
+  template<typename U>
+  struct rebind { using other = Alloc<U>; };
+};
+
+template<typename T>
+struct std::allocator_traits<Alloc<T>> // { dg-error "cannot be specialized" "" { target c++23 } }
+{};
+
+template<>
+struct std::allocator_traits<Alloc<void>> // { dg-error "cannot be specialized" "" { target c++23 } }
+{};
+
+// { dg-bogus "cannot be specialized" "" { target c++20_down } 0 }
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.