[gcc r17-2852] libstdc++: Reject user-defined specializations for allocator traits.
Tomasz Kaminski via Gcc-cvs <[email protected]> Fri, 31 Jul 2026 13:14:13 +0000 (GMT)
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <20260731131413.3976A4B19708__24560.0813346513$1785503694$gmane$org@sourceware.org> |
https://gcc.gnu.org/g:55a1efc2e04d7d7ecd5a19db3945b4231dbdc050 commit r17-2852-g55a1efc2e04d7d7ecd5a19db3945b4231dbdc050 Author: Tomasz Kamiński <[email protected]> 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 <[email protected]> Signed-off-by: Tomasz Kamiński <[email protected]> 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 }