From: Jakub Jelinek Date: Thu, 16 Jul 2026 07:51:48 +0000 (+0200) Subject: libstdc++: Use _Clang::__no_specializations__ attribute in a few spots [PR120635] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=26446cad5768b74f6c777ca135bc5bcfbd0f3f3d;p=thirdparty%2Fgcc.git libstdc++: Use _Clang::__no_specializations__ attribute in a few spots [PR120635] The following patch adds _Clang::__no_specializations__ attribute to a couple of templates: 1) LWG3975 - basic_format_{,parse_}context 2) LWG3990 - variant, tuple 3) LWG4305 - type_order 4) LWG2129 - std::initializer_list This assumes all those issues were handled as defect reports. What I haven't touched, but has similar wording: 5) P2652R2 - std::allocator_traits 6) P3019R14 - std::indirect 7) P0912R5 - std::coroutine_handle 8) LWG4535 - Anything else I'm missing? Note, seems libcxx adds the attribute to significantly more places, but not sure if that is desirable. [namespace.std] has some restrictions, but those generally say that it is UB in that case, which I'm not sure is the right case for unconditional error. Compared to that, the above mentioned library issues talk about ill-formed (and not IFNDR, so we really should be diagnosing that). 2026-07-16 Jakub Jelinek 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. Reviewed-by: Jonathan Wakely --- diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index e23d9dd3c9d..60456a48681 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -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 \ diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index 9bf5e78573b..729cb89ec60 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -286,7 +286,9 @@ namespace __format #endif template - 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; @@ -5014,7 +5016,9 @@ namespace __format * @since C++20 */ template - 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&> ); diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 64b96fe4f59..63b4010c0b5 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -791,7 +791,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Primary class template, tuple template - 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 diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index 55568ee913e..6e1388363ca 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -1450,7 +1450,10 @@ namespace __detail::__variant }; template - 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, diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare index 3847d0fb141..797e11df55e 100644 --- a/libstdc++-v3/libsupc++/compare +++ b/libstdc++-v3/libsupc++/compare @@ -1267,7 +1267,9 @@ namespace std _GLIBCXX_VISIBILITY(default) /// @since C++26 template - 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; diff --git a/libstdc++-v3/libsupc++/initializer_list b/libstdc++-v3/libsupc++/initializer_list index fbea49dfb01..5e164bec42e 100644 --- a/libstdc++-v3/libsupc++/initializer_list +++ b/libstdc++-v3/libsupc++/initializer_list @@ -47,7 +47,9 @@ namespace std _GLIBCXX_VISIBILITY(default) { /// initializer_list template - 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; diff --git a/libstdc++-v3/testsuite/18_support/comparisons/type_order/lwg4305.cc b/libstdc++-v3/testsuite/18_support/comparisons/type_order/lwg4305.cc new file mode 100644 index 00000000000..4a49d57df63 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/comparisons/type_order/lwg4305.cc @@ -0,0 +1,15 @@ +// { dg-do compile { target c++26 } } + +// LWG 4305. Missing user requirements on type_order template + +#include + +struct A {}; +template +struct B {}; + +template<> +struct std::type_order {}; // { dg-error "cannot be specialized" } + +template +struct std::type_order, T> {}; // { dg-error "cannot be specialized" } diff --git a/libstdc++-v3/testsuite/18_support/initializer_list/lwg2129.cc b/libstdc++-v3/testsuite/18_support/initializer_list/lwg2129.cc new file mode 100644 index 00000000000..375f874d1ec --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/initializer_list/lwg2129.cc @@ -0,0 +1,12 @@ +// { dg-do compile { target c++11 } } + +// LWG 2129. User specializations of std::initializer_list + +#include + +template +class std::initializer_list { // { dg-error "cannot be specialized" } +private: + void* array; + decltype(sizeof(0)) len; +}; diff --git a/libstdc++-v3/testsuite/20_util/tuple/lwg3990.cc b/libstdc++-v3/testsuite/20_util/tuple/lwg3990.cc new file mode 100644 index 00000000000..d10442074fd --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/lwg3990.cc @@ -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 + +struct A {}; +template +struct B {}; + +template<> +class std::tuple {}; // { dg-error "cannot be specialized" } + +template +class std::tuple, T> {}; // { dg-error "cannot be specialized" } diff --git a/libstdc++-v3/testsuite/20_util/variant/lwg3990.cc b/libstdc++-v3/testsuite/20_util/variant/lwg3990.cc new file mode 100644 index 00000000000..eab23c71a5d --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/variant/lwg3990.cc @@ -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 + +struct A {}; +template +struct B {}; + +template<> +class std::variant {}; // { dg-error "cannot be specialized" } + +template +class std::variant, T> {}; // { dg-error "cannot be specialized" } diff --git a/libstdc++-v3/testsuite/std/format/lwg3975.cc b/libstdc++-v3/testsuite/std/format/lwg3975.cc new file mode 100644 index 00000000000..470387130fb --- /dev/null +++ b/libstdc++-v3/testsuite/std/format/lwg3975.cc @@ -0,0 +1,18 @@ +// { dg-do compile { target c++20 } } + +// LWG 3975. Specializations of basic_format_context should not be permitted + +#include + +struct A {}; +template +struct B {}; + +template<> +class std::basic_format_parse_context {}; // { dg-error "cannot be specialized" } + +template<> +class std::basic_format_context, A> {}; // { dg-error "cannot be specialized" } + +template +class std::basic_format_context, T> {}; // { dg-error "cannot be specialized" }