[PATCH] libstdc++, v2: Use _Clang::__no_specializations__ attribute in a few spots [PR120635]
Jonathan Wakely
jwakely.gcc@gmail.com
Thu Jul 16 07:26:14 GMT 2026
On Wed, 15 Jul 2026, 18:14 Jakub Jelinek, <jakub@redhat.com> wrote:
> On Wed, Jul 15, 2026 at 06:45:30PM +0200, Jakub Jelinek wrote:
> > On Wed, Jul 15, 2026 at 05:00:03PM +0100, Jonathan Wakely wrote:
> > > So we could just use an object-like macro instead of a function-like
> macro:
> > >
> > > template<typename...> struct _GLIBCXX_NO_SPECIALIZATIONS tuple {
> >
> > If you are fine with the default warning when no_specialization doesn't
> > have argument, so just
> > error: '...' cannot be specialized
> > then sure. Will adjust the patch.
>
> Here is the updated patch with object-like macro instead, and no argument
> to the attribute.
> I've also added LWG2129 (initializer_list) stuff because PR119561 clearly
> shows there is some missing case (I was trying explicit specialization
> and that was rejected, but partial specialization might not if it declares
> the expected NSDMs).
>
OK, thanks
> 2026-07-15 Jakub Jelinek <jakub@redhat.com>
>
> PR c++/119561
> PR c++/120635
> * include/bits/c++config (_GLIBCXX_NO_SPECIALIZATIONS): Define.
> * include/std/variant (std::variant): Use it to resolve LWG3990.
> * include/std/format (std::basic_format_parse_context,
> std::basic_format_context): Use it to resolve LWG3975.
> * libsupc++/compare (std::type_order): Use it to resolve LWG4305.
> * libsupc++/initializer_list (std::initializer_list): Use it to
> resolve LWG2129.
> * include/std/tuple (std::tuple): Use it to resolve LWG3990.
> Temporarily ignore -Winvalid-specialization around specializations
> of tuple.
> * testsuite/18_support/comparisons/type_order/lwg4305.cc: New test.
> * testsuite/18_support/initializer_list/lwg2129.cc: New test.
> * testsuite/std/format/lwg3975.cc: New test.
> * testsuite/20_util/tuple/lwg3990.cc: New test.
> * testsuite/20_util/variant/lwg3990.cc: New test.
>
> --- libstdc++-v3/include/bits/c++config.jj 2026-01-02
> 22:41:17.624547836 +0100
> +++ libstdc++-v3/include/bits/c++config 2026-07-15 12:24:00.321648893 +0200
> @@ -927,6 +927,12 @@ namespace __gnu_cxx
> # define _GLIBCXX_USE_BUILTIN_TRAIT(BT) 0
> #endif
>
> +#if __has_cpp_attribute(_Clang::__no_specializations__)
> +# define _GLIBCXX_NO_SPECIALIZATIONS [[_Clang::__no_specializations__]]
> +#else
> +# define _GLIBCXX_NO_SPECIALIZATIONS
> +#endif
> +
> // Whether deducing this is usable either officially, if in C++23 mode, or
> // as an extension (Clang doesn't support the latter).
> #if __cpp_explicit_this_parameter \
> --- libstdc++-v3/include/std/variant.jj 2026-01-02 22:41:17.673547024 +0100
> +++ libstdc++-v3/include/std/variant 2026-07-15 13:16:35.639939009 +0200
> @@ -1450,7 +1450,10 @@ namespace __detail::__variant
> };
>
> template<typename... _Types>
> - class variant
> + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> + // 3990. Program-defined specializations of std::tuple and
> std::variant
> + // can't be properly supported
> + class _GLIBCXX_NO_SPECIALIZATIONS variant
> : private __detail::__variant::_Variant_base<_Types...>,
> private _Enable_copy_move<
> __detail::__variant::_Traits<_Types...>::_S_copy_ctor,
> --- libstdc++-v3/include/std/format.jj 2026-07-09 23:02:50.052419808 +0200
> +++ libstdc++-v3/include/std/format 2026-07-15 12:39:12.876753834 +0200
> @@ -286,7 +286,9 @@ namespace __format
> #endif
>
> template<typename _CharT>
> - class basic_format_parse_context
> + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> + // 3975. Specializations of basic_format_context should not be
> permitted
> + class _GLIBCXX_NO_SPECIALIZATIONS basic_format_parse_context
> {
> public:
> using char_type = _CharT;
> @@ -5015,7 +5017,9 @@ namespace __format
> * @since C++20
> */
> template<typename _Out, typename _CharT>
> - class basic_format_context
> + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> + // 3975. Specializations of basic_format_context should not be
> permitted
> + class _GLIBCXX_NO_SPECIALIZATIONS basic_format_context
> {
> static_assert( output_iterator<_Out, const _CharT&> );
>
> --- libstdc++-v3/include/std/tuple.jj 2026-05-14 21:26:54.625211399 +0200
> +++ libstdc++-v3/include/std/tuple 2026-07-15 13:14:56.950203385 +0200
> @@ -791,7 +791,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
> /// Primary class template, tuple
> template<typename... _Elements>
> - class tuple : public _Tuple_impl<0, _Elements...>
> + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> + // 3990. Program-defined specializations of std::tuple and
> std::variant
> + // can't be properly supported
> + class _GLIBCXX_NO_SPECIALIZATIONS tuple
> + : public _Tuple_impl<0, _Elements...>
> {
> using _Inherited = _Tuple_impl<0, _Elements...>;
>
> @@ -1942,6 +1946,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) ->
> tuple<_UTypes...>;
> #endif
>
> +#pragma GCC diagnostic push
> +#pragma GCC diagnostic ignored "-Winvalid-specialization"
> // Explicit specialization, zero-element tuple.
> template<>
> class tuple<>
> @@ -2416,6 +2422,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> { _Inherited::_M_swap(__in); }
> };
> #endif // concepts && conditional_explicit
> +#pragma GCC diagnostic pop
>
> /// class tuple_size
> template<typename... _Elements>
> --- libstdc++-v3/libsupc++/compare.jj 2026-01-19 22:16:24.654213651 +0100
> +++ libstdc++-v3/libsupc++/compare 2026-07-15 13:03:05.962281429 +0200
> @@ -1267,7 +1267,9 @@ namespace std _GLIBCXX_VISIBILITY(defaul
> /// @since C++26
>
> template<typename _Tp, typename _Up>
> - struct type_order
> + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> + // 4305. Missing user requirements on type_order template
> + struct _GLIBCXX_NO_SPECIALIZATIONS type_order
> {
> static constexpr strong_ordering value = __builtin_type_order(_Tp,
> _Up);
> using value_type = strong_ordering;
> --- libstdc++-v3/libsupc++/initializer_list.jj 2026-05-25
> 11:49:03.153901251 +0200
> +++ libstdc++-v3/libsupc++/initializer_list 2026-07-15
> 18:57:27.735630582 +0200
> @@ -47,7 +47,9 @@ namespace std _GLIBCXX_VISIBILITY(defaul
> {
> /// initializer_list
> template<class _E>
> - class initializer_list
> + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> + // 2129. User specializations of std::initializer_list
> + class _GLIBCXX_NO_SPECIALIZATIONS initializer_list
> {
> public:
> typedef _E value_type;
> ---
> libstdc++-v3/testsuite/18_support/comparisons/type_order/lwg4305.cc.jj
> 2026-07-15 13:04:03.355551554 +0200
> +++ libstdc++-v3/testsuite/18_support/comparisons/type_order/lwg4305.cc
> 2026-07-15 13:06:12.380910724 +0200
> @@ -0,0 +1,15 @@
> +// { dg-do compile { target c++26 } }
> +
> +// LWG 4305. Missing user requirements on type_order template
> +
> +#include <compare>
> +
> +struct A {};
> +template<typename T>
> +struct B {};
> +
> +template<>
> +struct std::type_order<A, A> {}; // { dg-error "cannot be
> specialized" }
> +
> +template<typename T>
> +struct std::type_order<B<T>, T> {}; // { dg-error "cannot be
> specialized" }
> --- libstdc++-v3/testsuite/18_support/initializer_list/lwg2129.cc.jj
> 2026-07-15 18:58:11.052086039 +0200
> +++ libstdc++-v3/testsuite/18_support/initializer_list/lwg2129.cc
> 2026-07-15 19:06:40.875676889 +0200
> @@ -0,0 +1,12 @@
> +// { dg-do compile { target c++11 } }
> +
> +// LWG 2129. User specializations of std::initializer_list
> +
> +#include <initializer_list>
> +
> +template<class T>
> +class std::initializer_list<T*> { // { dg-error "cannot be
> specialized" }
> +private:
> + void* array;
> + decltype(sizeof(0)) len;
> +};
> --- libstdc++-v3/testsuite/std/format/lwg3975.cc.jj 2026-07-15
> 12:48:54.752220096 +0200
> +++ libstdc++-v3/testsuite/std/format/lwg3975.cc 2026-07-15
> 13:06:25.909738675 +0200
> @@ -0,0 +1,18 @@
> +// { dg-do compile { target c++20 } }
> +
> +// LWG 3975. Specializations of basic_format_context should not be
> permitted
> +
> +#include <format>
> +
> +struct A {};
> +template<typename T>
> +struct B {};
> +
> +template<>
> +class std::basic_format_parse_context<A> {}; // { dg-error "cannot be
> specialized" }
> +
> +template<>
> +class std::basic_format_context<std::back_insert_iterator<std::string>,
> A> {}; // { dg-error "cannot be specialized" }
> +
> +template<typename T>
> +class std::basic_format_context<B<T>, T> {}; // { dg-error "cannot be
> specialized" }
> --- libstdc++-v3/testsuite/20_util/tuple/lwg3990.cc.jj 2026-07-15
> 13:18:53.806168876 +0200
> +++ libstdc++-v3/testsuite/20_util/tuple/lwg3990.cc 2026-07-15
> 13:20:38.915822255 +0200
> @@ -0,0 +1,16 @@
> +// { dg-do compile { target c++11 } }
> +
> +// LWG 3990. Program-defined specializations of std::tuple and
> std::variant
> +// can't be properly supported
> +
> +#include <tuple>
> +
> +struct A {};
> +template<typename T>
> +struct B {};
> +
> +template<>
> +class std::tuple<A, A> {}; // { dg-error "cannot be specialized" }
> +
> +template<typename T>
> +class std::tuple<B<T>, T> {}; // { dg-error "cannot be specialized" }
> --- libstdc++-v3/testsuite/20_util/variant/lwg3990.cc.jj 2026-07-15
> 13:18:57.962115630 +0200
> +++ libstdc++-v3/testsuite/20_util/variant/lwg3990.cc 2026-07-15
> 13:21:06.574467909 +0200
> @@ -0,0 +1,16 @@
> +// { dg-do compile { target c++11 } }
> +
> +// LWG 3990. Program-defined specializations of std::tuple and
> std::variant
> +// can't be properly supported
> +
> +#include <variant>
> +
> +struct A {};
> +template<typename T>
> +struct B {};
> +
> +template<>
> +class std::variant<A, A> {}; // { dg-error "cannot be specialized" }
> +
> +template<typename T>
> +class std::variant<B<T>, T> {}; // { dg-error "cannot be
> specialized" }
>
>
> Jakub
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260716/02cc8b39/attachment-0001.htm>
More information about the Libstdc++
mailing list