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

Jonathan Wakely <[email protected]>
Newsgroups gmane.comp.gcc.patches,gmane.comp.gcc.libstdc++.devel
Message-ID <CACb0b4kYshT4o13SrZnT4ZjK9W-+x5pUt+d75Nz81BH4ms=gkw@mail.gmail.com>
On Fri, 31 Jul 2026 at 13:56, Tomasz Kamiński <[email protected]> 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
>
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.