On Wed, 15 Jul 2026, 18:14 Jakub Jelinek, <[email protected]> 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 <[email protected]> > > 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 > >
