Skip to content

[libc++] Use [[clang::no_specializations]] to diagnose invalid user specializations #118167

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 23, 2025

Conversation

philnik777
Copy link
Contributor

@philnik777 philnik777 commented Nov 30, 2024

Some templates in the standard library are illegal to specialize for users
(even if the specialization contains user-defined types). The [[clang::no_specializations]]
attribute allows marking such base templates so that the compiler will
diagnose if users try adding a specialization.

Copy link

github-actions bot commented Nov 30, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@philnik777 philnik777 force-pushed the use_diagnose_specializations branch 3 times, most recently from 881e0f3 to 216d9aa Compare December 20, 2024 14:58
@philnik777 philnik777 marked this pull request as ready for review December 20, 2024 14:58
@philnik777 philnik777 requested a review from a team as a code owner December 20, 2024 14:58
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Dec 20, 2024
@llvmbot
Copy link
Member

llvmbot commented Dec 20, 2024

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

Changes

Patch is 92.66 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/118167.diff

89 Files Affected:

  • (modified) libcxx/include/__compare/compare_three_way_result.h (+2-1)
  • (modified) libcxx/include/__config (+6)
  • (modified) libcxx/include/__cxx03/__type_traits/add_const.h (+1-1)
  • (modified) libcxx/include/__cxx03/__type_traits/add_cv.h (+1-1)
  • (modified) libcxx/include/__cxx03/__type_traits/add_volatile.h (+1-1)
  • (modified) libcxx/include/__format/format_arg.h (+1-1)
  • (modified) libcxx/include/__ranges/range_adaptor.h (+1-1)
  • (modified) libcxx/include/__type_traits/add_cv_quals.h (+3-3)
  • (modified) libcxx/include/__type_traits/add_lvalue_reference.h (+1-1)
  • (modified) libcxx/include/__type_traits/add_pointer.h (+1-1)
  • (modified) libcxx/include/__type_traits/add_rvalue_reference.h (+1-1)
  • (modified) libcxx/include/__type_traits/aligned_storage.h (+1-1)
  • (modified) libcxx/include/__type_traits/aligned_union.h (+1-1)
  • (modified) libcxx/include/__type_traits/alignment_of.h (+3-2)
  • (modified) libcxx/include/__type_traits/conjunction.h (+1-1)
  • (modified) libcxx/include/__type_traits/decay.h (+1-1)
  • (modified) libcxx/include/__type_traits/disjunction.h (+2-2)
  • (modified) libcxx/include/__type_traits/extent.h (+2-2)
  • (modified) libcxx/include/__type_traits/has_unique_object_representation.h (+3-2)
  • (modified) libcxx/include/__type_traits/has_virtual_destructor.h (+3-2)
  • (modified) libcxx/include/__type_traits/integral_constant.h (+1-1)
  • (modified) libcxx/include/__type_traits/invoke.h (+13-10)
  • (modified) libcxx/include/__type_traits/is_abstract.h (+3-2)
  • (modified) libcxx/include/__type_traits/is_aggregate.h (+3-2)
  • (modified) libcxx/include/__type_traits/is_arithmetic.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_array.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_assignable.h (+6-6)
  • (modified) libcxx/include/__type_traits/is_base_of.h (+6-4)
  • (modified) libcxx/include/__type_traits/is_class.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_compound.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_const.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_constructible.h (+10-8)
  • (modified) libcxx/include/__type_traits/is_convertible.h (+3-2)
  • (modified) libcxx/include/__type_traits/is_destructible.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_empty.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_enum.h (+4-4)
  • (modified) libcxx/include/__type_traits/is_final.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_floating_point.h (+3-2)
  • (modified) libcxx/include/__type_traits/is_function.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_fundamental.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_implicit_lifetime.h (+3-2)
  • (modified) libcxx/include/__type_traits/is_integral.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_literal_type.h (+3-3)
  • (modified) libcxx/include/__type_traits/is_member_pointer.h (+8-6)
  • (modified) libcxx/include/__type_traits/is_nothrow_assignable.h (+7-7)
  • (modified) libcxx/include/__type_traits/is_nothrow_constructible.h (+11-8)
  • (modified) libcxx/include/__type_traits/is_nothrow_convertible.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_nothrow_destructible.h (+3-2)
  • (modified) libcxx/include/__type_traits/is_null_pointer.h (+3-2)
  • (modified) libcxx/include/__type_traits/is_object.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_pod.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_pointer.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_polymorphic.h (+3-2)
  • (modified) libcxx/include/__type_traits/is_reference.h (+8-6)
  • (modified) libcxx/include/__type_traits/is_same.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_scalar.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_signed.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_standard_layout.h (+3-2)
  • (modified) libcxx/include/__type_traits/is_swappable.h (+11-8)
  • (modified) libcxx/include/__type_traits/is_trivial.h (+3-2)
  • (modified) libcxx/include/__type_traits/is_trivially_assignable.h (+9-6)
  • (modified) libcxx/include/__type_traits/is_trivially_constructible.h (+12-8)
  • (modified) libcxx/include/__type_traits/is_trivially_copyable.h (+3-2)
  • (modified) libcxx/include/__type_traits/is_trivially_destructible.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_union.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_unsigned.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_void.h (+2-2)
  • (modified) libcxx/include/__type_traits/is_volatile.h (+2-2)
  • (modified) libcxx/include/__type_traits/make_signed.h (+1-1)
  • (modified) libcxx/include/__type_traits/make_unsigned.h (+1-1)
  • (modified) libcxx/include/__type_traits/negation.h (+2-2)
  • (modified) libcxx/include/__type_traits/remove_all_extents.h (+1-1)
  • (modified) libcxx/include/__type_traits/remove_const.h (+1-1)
  • (modified) libcxx/include/__type_traits/remove_cv.h (+1-1)
  • (modified) libcxx/include/__type_traits/remove_cvref.h (+1-1)
  • (modified) libcxx/include/__type_traits/remove_extent.h (+1-1)
  • (modified) libcxx/include/__type_traits/remove_pointer.h (+1-1)
  • (modified) libcxx/include/__type_traits/remove_reference.h (+1-1)
  • (modified) libcxx/include/__type_traits/remove_volatile.h (+1-1)
  • (modified) libcxx/include/__type_traits/type_identity.h (+1-1)
  • (modified) libcxx/include/__type_traits/underlying_type.h (+1-1)
  • (modified) libcxx/include/__type_traits/unwrap_ref.h (+2-2)
  • (modified) libcxx/include/variant (+1-1)
  • (added) libcxx/test/libcxx/algorithms/no_specializations.verify.cpp (+23)
  • (added) libcxx/test/libcxx/language.support/no_specializations.verify.cpp (+23)
  • (added) libcxx/test/libcxx/ranges/no_specializations.verify.cpp (+23)
  • (added) libcxx/test/libcxx/type_traits/no_specializations.verify.cpp (+176)
  • (added) libcxx/test/libcxx/utilities/format/no_specializations.verify.cpp (+23)
  • (added) libcxx/test/libcxx/utilities/no_specializations.verify.cpp (+23)
diff --git a/libcxx/include/__compare/compare_three_way_result.h b/libcxx/include/__compare/compare_three_way_result.h
index d7508073433af4..6ee2eff00302d0 100644
--- a/libcxx/include/__compare/compare_three_way_result.h
+++ b/libcxx/include/__compare/compare_three_way_result.h
@@ -33,7 +33,8 @@ struct _LIBCPP_HIDE_FROM_ABI __compare_three_way_result<
 };
 
 template <class _Tp, class _Up = _Tp>
-struct _LIBCPP_TEMPLATE_VIS compare_three_way_result : __compare_three_way_result<_Tp, _Up, void> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS compare_three_way_result
+    : __compare_three_way_result<_Tp, _Up, void> {};
 
 template <class _Tp, class _Up = _Tp>
 using compare_three_way_result_t = typename compare_three_way_result<_Tp, _Up>::type;
diff --git a/libcxx/include/__config b/libcxx/include/__config
index fe01b58b8e6274..da0b9038a6dafe 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -1176,6 +1176,12 @@ typedef __char32_t char32_t;
 #    define _LIBCPP_NODEBUG
 #  endif
 
+#  if __has_cpp_attribute(_Clang::__no_specializations__)
+#    define _LIBCPP_NO_SPECIALIZATIONS [[_Clang::__no_specializations__]]
+#  else
+#    define _LIBCPP_NO_SPECIALIZATIONS
+#  endif
+
 #  if __has_attribute(__standalone_debug__)
 #    define _LIBCPP_STANDALONE_DEBUG __attribute__((__standalone_debug__))
 #  else
diff --git a/libcxx/include/__cxx03/__type_traits/add_const.h b/libcxx/include/__cxx03/__type_traits/add_const.h
index 004ce05c03996f..9b3cf913b46d17 100644
--- a/libcxx/include/__cxx03/__type_traits/add_const.h
+++ b/libcxx/include/__cxx03/__type_traits/add_const.h
@@ -18,7 +18,7 @@
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS add_const {
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_DIAGNOSE_SPECIALIZATIONS add_const {
   typedef _LIBCPP_NODEBUG const _Tp type;
 };
 
diff --git a/libcxx/include/__cxx03/__type_traits/add_cv.h b/libcxx/include/__cxx03/__type_traits/add_cv.h
index 8445b863b5c2ef..940e1a4452b00b 100644
--- a/libcxx/include/__cxx03/__type_traits/add_cv.h
+++ b/libcxx/include/__cxx03/__type_traits/add_cv.h
@@ -18,7 +18,7 @@
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS add_cv {
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_DIAGNOSE_SPECIALIZATIONS add_cv {
   typedef _LIBCPP_NODEBUG const volatile _Tp type;
 };
 
diff --git a/libcxx/include/__cxx03/__type_traits/add_volatile.h b/libcxx/include/__cxx03/__type_traits/add_volatile.h
index 9f649e4978d65b..e85c92db595df1 100644
--- a/libcxx/include/__cxx03/__type_traits/add_volatile.h
+++ b/libcxx/include/__cxx03/__type_traits/add_volatile.h
@@ -18,7 +18,7 @@
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS add_volatile {
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_DIAGNOSE_SPECIALIZATIONS add_volatile {
   typedef _LIBCPP_NODEBUG volatile _Tp type;
 };
 
diff --git a/libcxx/include/__format/format_arg.h b/libcxx/include/__format/format_arg.h
index a973ccd43c4207..06922bce5a1b4b 100644
--- a/libcxx/include/__format/format_arg.h
+++ b/libcxx/include/__format/format_arg.h
@@ -277,7 +277,7 @@ class __basic_format_arg_value {
 };
 
 template <class _Context>
-class _LIBCPP_TEMPLATE_VIS basic_format_arg {
+class _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS basic_format_arg {
 public:
   class _LIBCPP_TEMPLATE_VIS handle;
 
diff --git a/libcxx/include/__ranges/range_adaptor.h b/libcxx/include/__ranges/range_adaptor.h
index d944a83406ba7f..4bcb53e1a58465 100644
--- a/libcxx/include/__ranges/range_adaptor.h
+++ b/libcxx/include/__ranges/range_adaptor.h
@@ -85,7 +85,7 @@ template <_RangeAdaptorClosure _Closure, _RangeAdaptorClosure _OtherClosure>
 #  if _LIBCPP_STD_VER >= 23
 template <class _Tp>
   requires is_class_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>>
-class range_adaptor_closure : public __range_adaptor_closure<_Tp> {};
+class _LIBCPP_NO_SPECIALIZATIONS range_adaptor_closure : public __range_adaptor_closure<_Tp> {};
 #  endif // _LIBCPP_STD_VER >= 23
 
 } // namespace ranges
diff --git a/libcxx/include/__type_traits/add_cv_quals.h b/libcxx/include/__type_traits/add_cv_quals.h
index 1d35b89f42c2d1..d4525457d72754 100644
--- a/libcxx/include/__type_traits/add_cv_quals.h
+++ b/libcxx/include/__type_traits/add_cv_quals.h
@@ -18,7 +18,7 @@
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS add_const {
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS add_const {
   typedef _LIBCPP_NODEBUG const _Tp type;
 };
 
@@ -28,7 +28,7 @@ using add_const_t = typename add_const<_Tp>::type;
 #endif
 
 template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS add_cv {
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS add_cv {
   typedef _LIBCPP_NODEBUG const volatile _Tp type;
 };
 
@@ -38,7 +38,7 @@ using add_cv_t = typename add_cv<_Tp>::type;
 #endif
 
 template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS add_volatile {
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS add_volatile {
   typedef _LIBCPP_NODEBUG volatile _Tp type;
 };
 
diff --git a/libcxx/include/__type_traits/add_lvalue_reference.h b/libcxx/include/__type_traits/add_lvalue_reference.h
index a633e390453205..fa3e830aff18c8 100644
--- a/libcxx/include/__type_traits/add_lvalue_reference.h
+++ b/libcxx/include/__type_traits/add_lvalue_reference.h
@@ -40,7 +40,7 @@ using __add_lvalue_reference_t = typename __add_lvalue_reference_impl<_Tp>::type
 #endif // __has_builtin(__add_lvalue_reference)
 
 template <class _Tp>
-struct add_lvalue_reference {
+struct _LIBCPP_NO_SPECIALIZATIONS add_lvalue_reference {
   using type _LIBCPP_NODEBUG = __add_lvalue_reference_t<_Tp>;
 };
 
diff --git a/libcxx/include/__type_traits/add_pointer.h b/libcxx/include/__type_traits/add_pointer.h
index 5aac7d5cfa90d8..bb5dd212ea00aa 100644
--- a/libcxx/include/__type_traits/add_pointer.h
+++ b/libcxx/include/__type_traits/add_pointer.h
@@ -41,7 +41,7 @@ using __add_pointer_t = typename __add_pointer_impl<_Tp>::type;
 #endif // !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__add_pointer)
 
 template <class _Tp>
-struct add_pointer {
+struct _LIBCPP_NO_SPECIALIZATIONS add_pointer {
   using type _LIBCPP_NODEBUG = __add_pointer_t<_Tp>;
 };
 
diff --git a/libcxx/include/__type_traits/add_rvalue_reference.h b/libcxx/include/__type_traits/add_rvalue_reference.h
index a54aae7ec8de5d..39121d70bc5d8b 100644
--- a/libcxx/include/__type_traits/add_rvalue_reference.h
+++ b/libcxx/include/__type_traits/add_rvalue_reference.h
@@ -40,7 +40,7 @@ using __add_rvalue_reference_t = typename __add_rvalue_reference_impl<_Tp>::type
 #endif // __has_builtin(__add_rvalue_reference)
 
 template <class _Tp>
-struct add_rvalue_reference {
+struct _LIBCPP_NO_SPECIALIZATIONS add_rvalue_reference {
   using type = __add_rvalue_reference_t<_Tp>;
 };
 
diff --git a/libcxx/include/__type_traits/aligned_storage.h b/libcxx/include/__type_traits/aligned_storage.h
index 2e39afb7f88088..ecc65c76cdb603 100644
--- a/libcxx/include/__type_traits/aligned_storage.h
+++ b/libcxx/include/__type_traits/aligned_storage.h
@@ -70,7 +70,7 @@ struct __find_max_align<__type_list<_Hp, _Tp>, _Len>
     : public integral_constant<size_t, __select_align<_Len, _Hp::value, __find_max_align<_Tp, _Len>::value>::value> {};
 
 template <size_t _Len, size_t _Align = __find_max_align<__all_types, _Len>::value>
-struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_TEMPLATE_VIS aligned_storage {
+struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS aligned_storage {
   union _ALIGNAS(_Align) type {
     unsigned char __data[(_Len + _Align - 1) / _Align * _Align];
   };
diff --git a/libcxx/include/__type_traits/aligned_union.h b/libcxx/include/__type_traits/aligned_union.h
index de62a4b1c2a331..dd88d54f5979b3 100644
--- a/libcxx/include/__type_traits/aligned_union.h
+++ b/libcxx/include/__type_traits/aligned_union.h
@@ -34,7 +34,7 @@ struct __static_max<_I0, _I1, _In...> {
 };
 
 template <size_t _Len, class _Type0, class... _Types>
-struct _LIBCPP_DEPRECATED_IN_CXX23 aligned_union {
+struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_NO_SPECIALIZATIONS aligned_union {
   static const size_t alignment_value =
       __static_max<_LIBCPP_PREFERRED_ALIGNOF(_Type0), _LIBCPP_PREFERRED_ALIGNOF(_Types)...>::value;
   static const size_t __len = __static_max<_Len, sizeof(_Type0), sizeof(_Types)...>::value;
diff --git a/libcxx/include/__type_traits/alignment_of.h b/libcxx/include/__type_traits/alignment_of.h
index 8871c8ce110d67..9801cac2cadd26 100644
--- a/libcxx/include/__type_traits/alignment_of.h
+++ b/libcxx/include/__type_traits/alignment_of.h
@@ -20,11 +20,12 @@
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS alignment_of : public integral_constant<size_t, _LIBCPP_ALIGNOF(_Tp)> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS alignment_of
+    : public integral_constant<size_t, _LIBCPP_ALIGNOF(_Tp)> {};
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr size_t alignment_of_v = _LIBCPP_ALIGNOF(_Tp);
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr size_t alignment_of_v = _LIBCPP_ALIGNOF(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/conjunction.h b/libcxx/include/__type_traits/conjunction.h
index c2995591bbc28f..e18ae46b01aee9 100644
--- a/libcxx/include/__type_traits/conjunction.h
+++ b/libcxx/include/__type_traits/conjunction.h
@@ -56,7 +56,7 @@ template <class _Arg, class... _Args>
 struct conjunction<_Arg, _Args...> : conditional_t<!bool(_Arg::value), _Arg, conjunction<_Args...>> {};
 
 template <class... _Args>
-inline constexpr bool conjunction_v = conjunction<_Args...>::value;
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool conjunction_v = conjunction<_Args...>::value;
 
 #endif // _LIBCPP_STD_VER >= 17
 
diff --git a/libcxx/include/__type_traits/decay.h b/libcxx/include/__type_traits/decay.h
index 7412044f931796..aa6bd459853a08 100644
--- a/libcxx/include/__type_traits/decay.h
+++ b/libcxx/include/__type_traits/decay.h
@@ -30,7 +30,7 @@ template <class _Tp>
 using __decay_t _LIBCPP_NODEBUG = __decay(_Tp);
 
 template <class _Tp>
-struct decay {
+struct _LIBCPP_NO_SPECIALIZATIONS decay {
   using type _LIBCPP_NODEBUG = __decay_t<_Tp>;
 };
 
diff --git a/libcxx/include/__type_traits/disjunction.h b/libcxx/include/__type_traits/disjunction.h
index 2c89528d9f2fc0..9d26d8d752faa3 100644
--- a/libcxx/include/__type_traits/disjunction.h
+++ b/libcxx/include/__type_traits/disjunction.h
@@ -46,10 +46,10 @@ using _Or _LIBCPP_NODEBUG = typename _OrImpl<sizeof...(_Args) != 0>::template _R
 #if _LIBCPP_STD_VER >= 17
 
 template <class... _Args>
-struct disjunction : _Or<_Args...> {};
+struct _LIBCPP_NO_SPECIALIZATIONS disjunction : _Or<_Args...> {};
 
 template <class... _Args>
-inline constexpr bool disjunction_v = _Or<_Args...>::value;
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool disjunction_v = _Or<_Args...>::value;
 
 #endif // _LIBCPP_STD_VER >= 17
 
diff --git a/libcxx/include/__type_traits/extent.h b/libcxx/include/__type_traits/extent.h
index 1c34a4db1c4b52..6f3db916f96dce 100644
--- a/libcxx/include/__type_traits/extent.h
+++ b/libcxx/include/__type_traits/extent.h
@@ -22,11 +22,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 #if __has_builtin(__array_extent)
 
 template <class _Tp, size_t _Dim = 0>
-struct _LIBCPP_TEMPLATE_VIS extent : integral_constant<size_t, __array_extent(_Tp, _Dim)> {};
+struct _LIBCPP_NO_SPECIALIZATIONS _LIBCPP_TEMPLATE_VIS extent : integral_constant<size_t, __array_extent(_Tp, _Dim)> {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp, unsigned _Ip = 0>
-inline constexpr size_t extent_v = __array_extent(_Tp, _Ip);
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr size_t extent_v = __array_extent(_Tp, _Ip);
 #  endif
 
 #else // __has_builtin(__array_extent)
diff --git a/libcxx/include/__type_traits/has_unique_object_representation.h b/libcxx/include/__type_traits/has_unique_object_representation.h
index 98c440c16bf26b..d92fef0b5d2baa 100644
--- a/libcxx/include/__type_traits/has_unique_object_representation.h
+++ b/libcxx/include/__type_traits/has_unique_object_representation.h
@@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 #if _LIBCPP_STD_VER >= 17
 
 template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS has_unique_object_representations
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS has_unique_object_representations
     // TODO: We work around a Clang and GCC bug in __has_unique_object_representations by using remove_all_extents
     //       even though it should not be necessary. This was reported to the compilers:
     //         - Clang: https://github.com/llvm/llvm-project/issues/95311
@@ -31,7 +31,8 @@ struct _LIBCPP_TEMPLATE_VIS has_unique_object_representations
     : public integral_constant<bool, __has_unique_object_representations(remove_all_extents_t<_Tp>)> {};
 
 template <class _Tp>
-inline constexpr bool has_unique_object_representations_v = __has_unique_object_representations(_Tp);
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool has_unique_object_representations_v =
+    __has_unique_object_representations(_Tp);
 
 #endif
 
diff --git a/libcxx/include/__type_traits/has_virtual_destructor.h b/libcxx/include/__type_traits/has_virtual_destructor.h
index 4ce96e649e67a1..98fa3cf6923987 100644
--- a/libcxx/include/__type_traits/has_virtual_destructor.h
+++ b/libcxx/include/__type_traits/has_virtual_destructor.h
@@ -19,11 +19,12 @@
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS has_virtual_destructor : public integral_constant<bool, __has_virtual_destructor(_Tp)> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS has_virtual_destructor
+    : public integral_constant<bool, __has_virtual_destructor(_Tp)> {};
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool has_virtual_destructor_v = __has_virtual_destructor(_Tp);
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool has_virtual_destructor_v = __has_virtual_destructor(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/integral_constant.h b/libcxx/include/__type_traits/integral_constant.h
index b8c75c546aa942..8feeff630d8741 100644
--- a/libcxx/include/__type_traits/integral_constant.h
+++ b/libcxx/include/__type_traits/integral_constant.h
@@ -18,7 +18,7 @@
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Tp, _Tp __v>
-struct _LIBCPP_TEMPLATE_VIS integral_constant {
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS integral_constant {
   static inline _LIBCPP_CONSTEXPR const _Tp value = __v;
   typedef _Tp value_type;
   typedef integral_constant type;
diff --git a/libcxx/include/__type_traits/invoke.h b/libcxx/include/__type_traits/invoke.h
index 71db32ae6a3cef..c386355ea0d7bd 100644
--- a/libcxx/include/__type_traits/invoke.h
+++ b/libcxx/include/__type_traits/invoke.h
@@ -230,35 +230,38 @@ struct __invoke_void_return_wrapper<_Ret, true> {
 // is_invocable
 
 template <class _Fn, class... _Args>
-struct _LIBCPP_TEMPLATE_VIS is_invocable : integral_constant<bool, __invokable<_Fn, _Args...>::value> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS is_invocable
+    : integral_constant<bool, __invokable<_Fn, _Args...>::value> {};
 
 template <class _Ret, class _Fn, class... _Args>
-struct _LIBCPP_TEMPLATE_VIS is_invocable_r : integral_constant<bool, __invokable_r<_Ret, _Fn, _Args...>::value> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS is_invocable_r
+    : integral_constant<bool, __invokable_r<_Ret, _Fn, _Args...>::value> {};
 
 template <class _Fn, class... _Args>
-inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value;
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value;
 
 template <class _Ret, class _Fn, class... _Args>
-inline constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value;
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value;
 
 // is_nothrow_invocable
 
 template <class _Fn, class... _Args>
-struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable : integral_constant<bool, __nothrow_invokable<_Fn, _Args...>::value> {
-};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS is_nothrow_invocable
+    : integral_constant<bool, __nothrow_invokable<_Fn, _Args...>::value> {};
 
 template <class _Ret, class _Fn, class... _Args>
-struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable_r
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS is_nothrow_invocable_r
     : integral_constant<bool, __nothrow_invokable_r<_Ret, _Fn, _Args...>::value> {};
 
 template <class _Fn, class... _Args>
-inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fn, _Args...>::value;
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fn, _Args...>::value;
 
 template <class _Ret, class _Fn, class... _Args>
-inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value;
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_nothrow_invocable_r_v =
+    is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value;
 
 template <class _Fn, class... _Args>
-struct _LIBCPP_TEMPLATE_VIS invoke_result : __invoke_of<_Fn, _Args...> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS invoke_result : __invoke_of<_Fn, _Args...> {};
 
 template <class _Fn, class... _Args>
 using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;
diff --git a/libcxx/include/__type_traits/is_abstract.h b/libcxx/include/__type_traits/is_abstract.h
index 4aa456be1c48e8..20b9e56cd60ebd 100644
--- a/libcxx/include/__type_traits/is_abstract.h
+++ b/libcxx/include/__type_traits/is_abstract.h
@@ -19,11 +19,12 @@
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS is_abstract : public integral_constant<bool, __is_abstract(_Tp)> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS is_abstract
+    : public integral_constant<bool, __is_abstract(_Tp)> {};
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_abstract_v = __is_abstract(_Tp);
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_abstract_v = __is_abstract(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_aggregate.h b/libcxx/include/__type_traits/is_aggregate.h
index 4e0988071adeec..b5098ee1bcf1a2 100644
--- a/libcxx/include/__type_traits/is_aggregate.h
+++ b/libcxx/include/__type_traits/is_aggregate.h
@@ -21,10 +21,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 #if _LIBCPP_STD_VER >= 17
 
 template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS is_aggregate : public integral_constant<bool, __is_aggregate(_Tp)> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS is_aggregate
+    : public integral_constant<bool, __is_aggregate(_Tp)> {};
 
 template <class _Tp>
-inline constexpr bool is_aggregate_v = __is_aggregate(_Tp);
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_aggregate_v = __is_aggregate(_Tp);
 
 #endif // _LIBCPP_STD_VER >= 17
 
diff --git a/libcxx/include/__type_traits/is_arithmetic.h b/libcxx/include/__type_traits/is_arithmetic.h
index c9713e1840a7b1..fcb31e9f5d5da4 100644
--- a/libcxx/include/__type_traits/is_arithmetic.h
+++ b/libcxx/include/__type_traits/is_arithmetic.h
@@ -21,12 +21,12 @@
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS is_arithmetic
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS is_arithmetic
     : public integral_constant<bool, is_integral<_Tp>::value || is_floating_point<_Tp>::value> {};
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_array.h b/libcxx/include/__type_traits/is_array.h
index f34204e19ed899..0bde0aa970f884 100644
--- a/libcxx/include/__type_traits/is_array.h
+++ b/libcxx/include/__type_traits/is_array.h
@@ -23,11 +23,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
     (!defined(_LIBCPP_COMPILER_CLANG_BASED) || (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1900))
 
 template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS is_array : _BoolConstant<__is_array(_Tp)> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS is_array : _BoolConstant<__is_array(_Tp)> {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline con...
[truncated]

Copy link

github-actions bot commented Dec 20, 2024

✅ With the latest revision this PR passed the undef deprecator.

Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a nice improvement to me, but I have some comments.

@philnik777 philnik777 force-pushed the use_diagnose_specializations branch from ced8a0c to e5cf1f4 Compare January 15, 2025 18:24
@philnik777 philnik777 force-pushed the use_diagnose_specializations branch from e5cf1f4 to f54cb52 Compare January 20, 2025 11:45
@philnik777 philnik777 force-pushed the use_diagnose_specializations branch 3 times, most recently from 2572102 to c930ddc Compare January 21, 2025 14:21
@philnik777 philnik777 force-pushed the use_diagnose_specializations branch from c930ddc to eeb2343 Compare January 22, 2025 09:42
@philnik777
Copy link
Contributor Author

I'm pretty sure the CI failures are unrelated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants