[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