[gcc r17-2852] libstdc++: Reject user-defined specializations for allocator traits.
Tomasz Kaminski
tkaminsk@gcc.gnu.org
Fri Jul 31 13:14:13 GMT 2026
https://gcc.gnu.org/g:55a1efc2e04d7d7ecd5a19db3945b4231dbdc050
commit r17-2852-g55a1efc2e04d7d7ecd5a19db3945b4231dbdc050
Author: Tomasz Kamiński <tkaminsk@redhat.com>
Date: Wed Jul 29 12:14:39 2026 +0200
libstdc++: Reject user-defined specializations for allocator traits.
Marks 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.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
Diff:
---
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(-)
diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h
index 101badff4549..c113f798690d 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 a9db58b76a34..801184c1bbc6 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 000000000000..1a46d8793f0a
--- /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 }
More information about the Libstdc++-cvs
mailing list