From: Tomasz Kamiński Date: Wed, 29 Jul 2026 10:14:39 +0000 (+0200) Subject: libstdc++: Reject user-defined specializations for allocator traits. X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=55a1efc2e04d7d7ecd5a19db3945b4231dbdc050;p=thirdparty%2Fgcc.git 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>) (std::allocator_traits>): Locally ignore -Winvalid-specialization warnings. * include/bits/memory_resource.h (allocator_traits>): Likewise. * testsuite/20_util/allocator_traits/requirements/specializations_neg.cc: New test. Reviewed-by: Jonathan Wakely Signed-off-by: Tomasz Kamiński --- 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 - 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 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 + +template struct Alloc : std::allocator +{ + template + struct rebind { using other = Alloc; }; +}; + +template +struct std::allocator_traits> // { dg-error "cannot be specialized" "" { target c++23 } } +{}; + +template<> +struct std::allocator_traits> // { dg-error "cannot be specialized" "" { target c++23 } } +{}; + +// { dg-bogus "cannot be specialized" "" { target c++20_down } 0 }