git: fcfb38a25f07 - stable/14 - Revert commit 925a11a5f221 from llvm-project (by Nikolas Klauser):

From: Dimitry Andric <dim_at_FreeBSD.org>
Date: Sat, 20 Apr 2024 10:32:49 UTC
The branch stable/14 has been updated by dim:

URL: https://cgit.FreeBSD.org/src/commit/?id=fcfb38a25f074c3677e9c672a6c4550b3430bd04

commit fcfb38a25f074c3677e9c672a6c4550b3430bd04
Author:     Dimitry Andric <dim@FreeBSD.org>
AuthorDate: 2024-04-13 08:44:26 +0000
Commit:     Dimitry Andric <dim@FreeBSD.org>
CommitDate: 2024-04-20 10:03:26 +0000

    Revert commit 925a11a5f221 from llvm-project (by Nikolas Klauser):
    
      [libc++] Simplify is_convertible
    
      GCC 13 has added __is_convertible(), so we don't need to keep the fallback implementation around.
    
      Reviewed By: #libc, Mordante
    
      Spies: Mordante, libcxx-commits
    
      Differential Revision: https://reviews.llvm.org/D157939
    
    This should allow buildworld with gcc 12 to work again.
    
    PR:             276104
    MFC after:      1 month
    
    (cherry picked from commit 2365f012951e5f0333cf31c690f668299c86b30e)
---
 .../libcxx/include/__type_traits/is_convertible.h  | 79 +++++++++++++++++++++-
 1 file changed, 78 insertions(+), 1 deletion(-)

diff --git a/contrib/llvm-project/libcxx/include/__type_traits/is_convertible.h b/contrib/llvm-project/libcxx/include/__type_traits/is_convertible.h
index bc91d8b23430..b378a20cedeb 100644
--- a/contrib/llvm-project/libcxx/include/__type_traits/is_convertible.h
+++ b/contrib/llvm-project/libcxx/include/__type_traits/is_convertible.h
@@ -24,12 +24,89 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+#if __has_builtin(__is_convertible) && !defined(_LIBCPP_USE_IS_CONVERTIBLE_FALLBACK)
+
 template <class _T1, class _T2>
 struct _LIBCPP_TEMPLATE_VIS is_convertible : public integral_constant<bool, __is_convertible(_T1, _T2)> {};
 
+#elif __has_builtin(__is_convertible_to) && !defined(_LIBCPP_USE_IS_CONVERTIBLE_FALLBACK)
+
+template <class _T1, class _T2>
+struct _LIBCPP_TEMPLATE_VIS is_convertible : public integral_constant<bool, __is_convertible_to(_T1, _T2)> {};
+
+// TODO: Remove this fallback when GCC < 13 support is no longer required.
+// GCC 13 has the __is_convertible built-in.
+#else // __has_builtin(__is_convertible_to) && !defined(_LIBCPP_USE_IS_CONVERTIBLE_FALLBACK)
+
+namespace __is_convertible_imp {
+template <class _Tp>
+void __test_convert(_Tp);
+
+template <class _From, class _To, class = void>
+struct __is_convertible_test : public false_type {};
+
+template <class _From, class _To>
+struct __is_convertible_test<_From, _To, decltype(__is_convertible_imp::__test_convert<_To>(std::declval<_From>()))>
+    : public true_type {};
+
+// clang-format off
+template <class _Tp,
+          bool _IsArray    = is_array<_Tp>::value,
+          bool _IsFunction = is_function<_Tp>::value,
+          bool _IsVoid     = is_void<_Tp>::value>
+                     struct __is_array_function_or_void                          { enum { value = 0 }; };
+template <class _Tp> struct __is_array_function_or_void<_Tp, true, false, false> { enum { value = 1 }; };
+template <class _Tp> struct __is_array_function_or_void<_Tp, false, true, false> { enum { value = 2 }; };
+template <class _Tp> struct __is_array_function_or_void<_Tp, false, false, true> { enum { value = 3 }; };
+// clang-format on
+} // namespace __is_convertible_imp
+
+template <class _Tp,
+          unsigned = __is_convertible_imp::__is_array_function_or_void<__libcpp_remove_reference_t<_Tp> >::value>
+struct __is_convertible_check {
+  static const size_t __v = 0;
+};
+
+template <class _Tp>
+struct __is_convertible_check<_Tp, 0> {
+  static const size_t __v = sizeof(_Tp);
+};
+
+template <class _T1,
+          class _T2,
+          unsigned _T1_is_array_function_or_void = __is_convertible_imp::__is_array_function_or_void<_T1>::value,
+          unsigned _T2_is_array_function_or_void = __is_convertible_imp::__is_array_function_or_void<_T2>::value>
+struct __is_convertible
+    : public integral_constant<bool, __is_convertible_imp::__is_convertible_test<_T1, _T2>::value >{};
+
+// clang-format off
+template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 0, 1> : public false_type{};
+template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 1, 1> : public false_type{};
+template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 2, 1> : public false_type{};
+template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 3, 1> : public false_type{};
+
+template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 0, 2> : public false_type{};
+template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 1, 2> : public false_type{};
+template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 2, 2> : public false_type{};
+template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 3, 2> : public false_type{};
+
+template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 0, 3> : public false_type{};
+template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 1, 3> : public false_type{};
+template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 2, 3> : public false_type{};
+template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 3, 3> : public true_type{};
+// clang-format on
+
+template <class _T1, class _T2>
+struct _LIBCPP_TEMPLATE_VIS is_convertible : public __is_convertible<_T1, _T2> {
+  static const size_t __complete_check1 = __is_convertible_check<_T1>::__v;
+  static const size_t __complete_check2 = __is_convertible_check<_T2>::__v;
+};
+
+#endif // __has_builtin(__is_convertible_to) && !defined(_LIBCPP_USE_IS_CONVERTIBLE_FALLBACK)
+
 #if _LIBCPP_STD_VER >= 17
 template <class _From, class _To>
-inline constexpr bool is_convertible_v = __is_convertible(_From, _To);
+inline constexpr bool is_convertible_v = is_convertible<_From, _To>::value;
 #endif
 
 _LIBCPP_END_NAMESPACE_STD