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 >