[libcxx-commits] [libcxx] 3bdfca5 - [libc++] Workaround for a bug of overloads in MS UCRT's `<math.h>` (#149234)

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Aug 5 02:47:15 PDT 2025


Author: A. Jiang
Date: 2025-08-05T17:47:11+08:00
New Revision: 3bdfca58a6c04272c70413f07b206f0b95743309

URL: https://github.com/llvm/llvm-project/commit/3bdfca58a6c04272c70413f07b206f0b95743309
DIFF: https://github.com/llvm/llvm-project/commit/3bdfca58a6c04272c70413f07b206f0b95743309.diff

LOG: [libc++] Workaround for a bug of overloads in MS UCRT's `<math.h>` (#149234)

MS UCRT seems confused on the status of LWG1327, and still provides
pre-LWG1327 overload set the related math functions, which can't handle
integer types as required. It is probably that UCRT won't fixed this in
a near future, per
https://developercommunity.visualstudio.com/t/10294165.

Before C++20, libc++ worked around this bug by relying on
`-fdelayed-template-parsing`. However, this non-conforming option is off
by default since C++20. I think we should use `requires` instead.

---------

Co-authored-by: Louis Dionne <ldionne.2 at gmail.com>

Added: 
    

Modified: 
    libcxx/include/__math/traits.h
    libcxx/include/math.h
    libcxx/test/libcxx/fuzzing/random.pass.cpp
    libcxx/test/std/depr/depr.c.headers/math_h.pass.cpp
    libcxx/test/std/numerics/c.math/cmath.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h
index 4a6e58c6da8ad..00db2a8289fb3 100644
--- a/libcxx/include/__math/traits.h
+++ b/libcxx/include/__math/traits.h
@@ -189,6 +189,82 @@ template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_ar
   return __builtin_isunordered((type)__x, (type)__y);
 }
 
+// MS UCRT incorrectly defines some functions in a way not working with integer types. Until C++20, this was worked
+// around by -fdelayed-template-parsing. Since C++20, we can use standard feature "requires" instead.
+
+// TODO: Remove the workaround once UCRT fixes these functions. Note that this doesn't seem planned as of 2025-07 per
+// https://developercommunity.visualstudio.com/t/10294165.
+
+#if defined(_LIBCPP_MSVCRT) && _LIBCPP_STD_VER >= 20
+namespace __ucrt {
+template <class _A1>
+  requires is_integral_v<_A1>
+[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) noexcept {
+  return true;
+}
+
+template <class _A1>
+  requires is_integral_v<_A1>
+[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1) noexcept {
+  return false;
+}
+
+template <class _A1>
+  requires is_integral_v<_A1>
+[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1) noexcept {
+  return false;
+}
+
+template <class _A1>
+  requires is_integral_v<_A1>
+[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) noexcept {
+  return __x != 0;
+}
+
+template <class _A1, class _A2>
+  requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>
+[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) noexcept {
+  using type = __promote_t<_A1, _A2>;
+  return __builtin_isgreater((type)__x, (type)__y);
+}
+
+template <class _A1, class _A2>
+  requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>
+[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) noexcept {
+  using type = __promote_t<_A1, _A2>;
+  return __builtin_isgreaterequal((type)__x, (type)__y);
+}
+
+template <class _A1, class _A2>
+  requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>
+[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) noexcept {
+  using type = __promote_t<_A1, _A2>;
+  return __builtin_isless((type)__x, (type)__y);
+}
+
+template <class _A1, class _A2>
+  requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>
+[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) noexcept {
+  using type = __promote_t<_A1, _A2>;
+  return __builtin_islessequal((type)__x, (type)__y);
+}
+
+template <class _A1, class _A2>
+  requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>
+[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) noexcept {
+  using type = __promote_t<_A1, _A2>;
+  return __builtin_islessgreater((type)__x, (type)__y);
+}
+
+template <class _A1, class _A2>
+  requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>
+[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) noexcept {
+  using type = __promote_t<_A1, _A2>;
+  return __builtin_isunordered((type)__x, (type)__y);
+}
+} // namespace __ucrt
+#endif
+
 } // namespace __math
 
 _LIBCPP_END_NAMESPACE_STD

diff  --git a/libcxx/include/math.h b/libcxx/include/math.h
index 929bef6385043..1db61538e995f 100644
--- a/libcxx/include/math.h
+++ b/libcxx/include/math.h
@@ -429,6 +429,25 @@ using std::__math::isnormal;
 using std::__math::isunordered;
 #      endif // _LIBCPP_MSVCRT
 
+#      if defined(_LIBCPP_MSVCRT) && _LIBCPP_STD_VER >= 20
+// MS UCRT incorrectly defines some functions in a way not working with integer types. Until C++20, this was worked
+// around by -fdelayed-template-parsing. Since C++20, we can use standard feature "requires" instead.
+
+// TODO: Remove the workaround once UCRT fixes these functions. Note that this doesn't seem planned as of 2025-07 per
+// https://developercommunity.visualstudio.com/t/10294165.
+
+using std::__math::__ucrt::isfinite;
+using std::__math::__ucrt::isgreater;
+using std::__math::__ucrt::isgreaterequal;
+using std::__math::__ucrt::isinf;
+using std::__math::__ucrt::isless;
+using std::__math::__ucrt::islessequal;
+using std::__math::__ucrt::islessgreater;
+using std::__math::__ucrt::isnan;
+using std::__math::__ucrt::isnormal;
+using std::__math::__ucrt::isunordered;
+#      endif // defined(_LIBCPP_MSVCRT) && _LIBCPP_STD_VER >= 20
+
 // We have to provide double overloads for <math.h> to work on platforms that don't provide the full set of math
 // functions. To make the overload set work with multiple functions that take the same arguments, we make our overloads
 // templates. Functions are preferred over function templates during overload resolution, which means that our overload

diff  --git a/libcxx/test/libcxx/fuzzing/random.pass.cpp b/libcxx/test/libcxx/fuzzing/random.pass.cpp
index f0256a01f29ae..79ab7ac41151c 100644
--- a/libcxx/test/libcxx/fuzzing/random.pass.cpp
+++ b/libcxx/test/libcxx/fuzzing/random.pass.cpp
@@ -6,11 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-// This doesn't work on Windows because in the MSVC UCRT headers the math.h is
-// actually intended to implement the full C++ spec requirements. For details
-// see https://github.com/llvm/llvm-project/issues/70225#issuecomment-1992528828
-// XFAIL: msvc
-
 // UNSUPPORTED: c++03, c++11
 
 #include <cassert>

diff  --git a/libcxx/test/std/depr/depr.c.headers/math_h.pass.cpp b/libcxx/test/std/depr/depr.c.headers/math_h.pass.cpp
index f9f81d22ff80e..3934e5177da14 100644
--- a/libcxx/test/std/depr/depr.c.headers/math_h.pass.cpp
+++ b/libcxx/test/std/depr/depr.c.headers/math_h.pass.cpp
@@ -6,11 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-// This doesn't work on Windows because in the MSVC UCRT headers the math.h is
-// actually intended to implement the full C++ spec requirements. For details
-// see https://github.com/llvm/llvm-project/issues/70225#issuecomment-1992528828
-// XFAIL: msvc
-
 // <math.h>
 
 // GCC warns about signbit comparing `bool_v < 0`, which we're testing

diff  --git a/libcxx/test/std/numerics/c.math/cmath.pass.cpp b/libcxx/test/std/numerics/c.math/cmath.pass.cpp
index 8d261e9fcbdb2..1f7c697784c10 100644
--- a/libcxx/test/std/numerics/c.math/cmath.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/cmath.pass.cpp
@@ -6,11 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-// This doesn't work on Windows because in the MSVC UCRT headers the math.h is
-// actually intended to implement the full C++ spec requirements. For details
-// see https://github.com/llvm/llvm-project/issues/70225#issuecomment-1992528828
-// XFAIL: msvc
-
 // <cmath>
 
 #include <cmath>


        


More information about the libcxx-commits mailing list