[PATCH] libstdc++: Reject user-defined specializations for allocator traits.
Jonathan Wakely
jwakely@redhat.com
Fri Jul 31 12:58:07 GMT 2026
On Fri, 31 Jul 2026 at 13:56, Tomasz Kamiński <tkaminsk@redhat.com> wrote:
>
> 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.
Yes, that makes sense to me.
>
> Tested on x86_64-linux locally. OK for trunk?
OK thanks.
>
> 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
>
More information about the Libstdc++
mailing list