[libcxx-commits] [libcxx] [libc++][math] Add `constexpr` to `copysign` functions (PR #216285)
Lucas Mellone via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Aug 17 11:09:52 PDT 2026
https://github.com/lknknm updated https://github.com/llvm/llvm-project/pull/216285
>From 714be78ad730429ed9591a77d040b9def148f0e7 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Fri, 14 Aug 2026 11:35:19 +0200
Subject: [PATCH 1/5] constexpr cxx23 copysign
---
libcxx/include/__math/copysign.h | 20 ++++++++++++++++---
libcxx/include/cmath | 6 +++---
.../c.math/constexpr-cxx23-clang.pass.cpp | 10 +++++-----
3 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/libcxx/include/__math/copysign.h b/libcxx/include/__math/copysign.h
index 4c297cb0894e9..ea67c8d8704e3 100644
--- a/libcxx/include/__math/copysign.h
+++ b/libcxx/include/__math/copysign.h
@@ -24,19 +24,33 @@ namespace __math {
// copysign
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI float copysign(float __x, float __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI float
+copysign(float __x, float __y) _NOEXCEPT {
return ::__builtin_copysignf(__x, __y);
}
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI long double copysign(long double __x, long double __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI long double
+copysign(long double __x, long double __y) _NOEXCEPT {
return ::__builtin_copysignl(__x, __y);
}
template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> copysign(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2>
+copysign(_A1 __x, _A2 __y) _NOEXCEPT {
return ::__builtin_copysign(__x, __y);
}
+#ifdef _LIBCPP_PREFERRED_OVERLOAD
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD float copysignf(float __x, float __y) _NOEXCEPT {
+ return __builtin_copysignf(__x, __y);
+}
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD long double
+copysignl(long double __x, long double __y) _NOEXCEPT {
+ return __builtin_copysignl(__x, __y);
+}
+#endif
+
} // namespace __math
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index c4f4030c2049b..8cc48912b46bb 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -424,8 +424,8 @@ using ::atanhf _LIBCPP_USING_IF_EXISTS;
using ::cbrt _LIBCPP_USING_IF_EXISTS;
using ::cbrtf _LIBCPP_USING_IF_EXISTS;
-using ::copysign _LIBCPP_USING_IF_EXISTS;
-using ::copysignf _LIBCPP_USING_IF_EXISTS;
+using std::__math::copysign _LIBCPP_USING_IF_EXISTS;
+using std::__math::copysignf _LIBCPP_USING_IF_EXISTS;
using ::erf _LIBCPP_USING_IF_EXISTS;
using ::erff _LIBCPP_USING_IF_EXISTS;
@@ -518,7 +518,7 @@ using ::asinhl _LIBCPP_USING_IF_EXISTS;
using ::atanhl _LIBCPP_USING_IF_EXISTS;
using ::cbrtl _LIBCPP_USING_IF_EXISTS;
-using ::copysignl _LIBCPP_USING_IF_EXISTS;
+using std::__math::copysignl _LIBCPP_USING_IF_EXISTS;
using ::erfl _LIBCPP_USING_IF_EXISTS;
using ::erfcl _LIBCPP_USING_IF_EXISTS;
diff --git a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp
index beca4907284ad..3b8b418884d3d 100644
--- a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp
+++ b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp
@@ -161,11 +161,11 @@ int main(int, char**) {
ASSERT_NOT_CONSTEXPR_CXX23(std::remquof(0.5f, 1.0f, &DummyInt) == 0.5f);
ASSERT_NOT_CONSTEXPR_CXX23(std::remquol(0.5L, 1.0L, &DummyInt) == 0.5L);
- ASSERT_NOT_CONSTEXPR_CXX23(std::copysign(1.0f, 1.0f) == 1.0f);
- ASSERT_NOT_CONSTEXPR_CXX23(std::copysign(1.0, 1.0) == 1.0);
- ASSERT_NOT_CONSTEXPR_CXX23(std::copysign(1.0L, 1.0L) == 1.0L);
- ASSERT_NOT_CONSTEXPR_CXX23(std::copysignf(1.0f, 1.0f) == 1.0f);
- ASSERT_NOT_CONSTEXPR_CXX23(std::copysignl(1.0L, 1.0L) == 1.0L);
+ ASSERT_CONSTEXPR_CXX23(std::copysign(1.0f, 1.0f) == 1.0f);
+ ASSERT_CONSTEXPR_CXX23(std::copysign(1.0, 1.0) == 1.0);
+ ASSERT_CONSTEXPR_CXX23(std::copysign(1.0L, 1.0L) == 1.0L);
+ ASSERT_CONSTEXPR_CXX23(std::copysignf(1.0f, 1.0f) == 1.0f);
+ ASSERT_CONSTEXPR_CXX23(std::copysignl(1.0L, 1.0L) == 1.0L);
ASSERT_NOT_CONSTEXPR_CXX23(std::nextafter(0.0f, 0.0f) == 0.0f);
ASSERT_NOT_CONSTEXPR_CXX23(std::nextafter(0.0, 0.0) == 0.0);
>From 9b8bf93665db2c2e1bd1c2e973b2a4d24cf7984e Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Sat, 15 Aug 2026 17:57:51 +0200
Subject: [PATCH 2/5] revert few changes
---
libcxx/include/__math/copysign.h | 11 -----------
libcxx/include/cmath | 6 +++---
2 files changed, 3 insertions(+), 14 deletions(-)
diff --git a/libcxx/include/__math/copysign.h b/libcxx/include/__math/copysign.h
index ea67c8d8704e3..7e3b5db2d9887 100644
--- a/libcxx/include/__math/copysign.h
+++ b/libcxx/include/__math/copysign.h
@@ -40,17 +40,6 @@ copysign(_A1 __x, _A2 __y) _NOEXCEPT {
return ::__builtin_copysign(__x, __y);
}
-#ifdef _LIBCPP_PREFERRED_OVERLOAD
-[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD float copysignf(float __x, float __y) _NOEXCEPT {
- return __builtin_copysignf(__x, __y);
-}
-[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD long double
-copysignl(long double __x, long double __y) _NOEXCEPT {
- return __builtin_copysignl(__x, __y);
-}
-#endif
-
} // namespace __math
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index 8cc48912b46bb..c4f4030c2049b 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -424,8 +424,8 @@ using ::atanhf _LIBCPP_USING_IF_EXISTS;
using ::cbrt _LIBCPP_USING_IF_EXISTS;
using ::cbrtf _LIBCPP_USING_IF_EXISTS;
-using std::__math::copysign _LIBCPP_USING_IF_EXISTS;
-using std::__math::copysignf _LIBCPP_USING_IF_EXISTS;
+using ::copysign _LIBCPP_USING_IF_EXISTS;
+using ::copysignf _LIBCPP_USING_IF_EXISTS;
using ::erf _LIBCPP_USING_IF_EXISTS;
using ::erff _LIBCPP_USING_IF_EXISTS;
@@ -518,7 +518,7 @@ using ::asinhl _LIBCPP_USING_IF_EXISTS;
using ::atanhl _LIBCPP_USING_IF_EXISTS;
using ::cbrtl _LIBCPP_USING_IF_EXISTS;
-using std::__math::copysignl _LIBCPP_USING_IF_EXISTS;
+using ::copysignl _LIBCPP_USING_IF_EXISTS;
using ::erfl _LIBCPP_USING_IF_EXISTS;
using ::erfcl _LIBCPP_USING_IF_EXISTS;
>From b3d9ed5dcbb701de1928eb093b4f380e444e69cb Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Mon, 17 Aug 2026 01:36:39 +0200
Subject: [PATCH 3/5] wip: namespace resolution
---
libcxx/include/__math/copysign.h | 7 +++++--
libcxx/include/cmath | 15 +++++++++++++++
libcxx/include/math.h | 1 -
3 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/libcxx/include/__math/copysign.h b/libcxx/include/__math/copysign.h
index 7e3b5db2d9887..e87097ba85449 100644
--- a/libcxx/include/__math/copysign.h
+++ b/libcxx/include/__math/copysign.h
@@ -29,6 +29,9 @@ copysign(float __x, float __y) _NOEXCEPT {
return ::__builtin_copysignf(__x, __y);
}
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
+double copysign(double __x, double __y) _NOEXCEPT { return __builtin_copysign(__x, __y); }
+
[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI long double
copysign(long double __x, long double __y) _NOEXCEPT {
return ::__builtin_copysignl(__x, __y);
@@ -36,8 +39,8 @@ copysign(long double __x, long double __y) _NOEXCEPT {
template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2>
-copysign(_A1 __x, _A2 __y) _NOEXCEPT {
- return ::__builtin_copysign(__x, __y);
+ copysign(_A1 __x, _A2 __y) _NOEXCEPT {
+ return ::__builtin_copysign(__x, __y);
}
} // namespace __math
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index c4f4030c2049b..2ee9f078a843e 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -424,8 +424,17 @@ using ::atanhf _LIBCPP_USING_IF_EXISTS;
using ::cbrt _LIBCPP_USING_IF_EXISTS;
using ::cbrtf _LIBCPP_USING_IF_EXISTS;
+#if _LIBCPP_STD_VER >= 23 && __has_constexpr_builtin(__builtin_copysign)
+_LIBCPP_HIDE_FROM_ABI constexpr double copysign(double __x, double __y) _NOEXCEPT {
+ return __builtin_copysign(__x, __y);
+}
+_LIBCPP_HIDE_FROM_ABI constexpr float copysignf(float __x, float __y) _NOEXCEPT {
+ return __builtin_copysignf(__x, __y);
+}
+#else
using ::copysign _LIBCPP_USING_IF_EXISTS;
using ::copysignf _LIBCPP_USING_IF_EXISTS;
+#endif
using ::erf _LIBCPP_USING_IF_EXISTS;
using ::erff _LIBCPP_USING_IF_EXISTS;
@@ -518,7 +527,13 @@ using ::asinhl _LIBCPP_USING_IF_EXISTS;
using ::atanhl _LIBCPP_USING_IF_EXISTS;
using ::cbrtl _LIBCPP_USING_IF_EXISTS;
+#if _LIBCPP_STD_VER >= 23 && __has_constexpr_builtin(__builtin_copysignl)
+_LIBCPP_HIDE_FROM_ABI constexpr long double copysignl(long double __x, long double __y) _NOEXCEPT {
+ return __builtin_copysignl(__x, __y);
+}
+#else
using ::copysignl _LIBCPP_USING_IF_EXISTS;
+#endif
using ::erfl _LIBCPP_USING_IF_EXISTS;
using ::erfcl _LIBCPP_USING_IF_EXISTS;
diff --git a/libcxx/include/math.h b/libcxx/include/math.h
index 9d0642398b7d4..6f520634d0646 100644
--- a/libcxx/include/math.h
+++ b/libcxx/include/math.h
@@ -491,7 +491,6 @@ using std::__math::atan2;
using std::__math::atanh;
using std::__math::cbrt;
using std::__math::ceil;
-using std::__math::copysign;
using std::__math::cos;
using std::__math::cosh;
using std::__math::erf;
>From c3454b8f9e1cbc99b3ed03413d83f6afd386a870 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Mon, 17 Aug 2026 01:40:37 +0200
Subject: [PATCH 4/5] fix: clang-format
---
libcxx/include/__math/copysign.h | 10 ++++++----
libcxx/include/cmath | 12 ++++++------
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/libcxx/include/__math/copysign.h b/libcxx/include/__math/copysign.h
index e87097ba85449..c100c03650733 100644
--- a/libcxx/include/__math/copysign.h
+++ b/libcxx/include/__math/copysign.h
@@ -29,8 +29,10 @@ copysign(float __x, float __y) _NOEXCEPT {
return ::__builtin_copysignf(__x, __y);
}
-[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
-double copysign(double __x, double __y) _NOEXCEPT { return __builtin_copysign(__x, __y); }
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI double
+copysign(double __x, double __y) _NOEXCEPT {
+ return __builtin_copysign(__x, __y);
+}
[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI long double
copysign(long double __x, long double __y) _NOEXCEPT {
@@ -39,8 +41,8 @@ copysign(long double __x, long double __y) _NOEXCEPT {
template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2>
- copysign(_A1 __x, _A2 __y) _NOEXCEPT {
- return ::__builtin_copysign(__x, __y);
+copysign(_A1 __x, _A2 __y) _NOEXCEPT {
+ return ::__builtin_copysign(__x, __y);
}
} // namespace __math
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index 2ee9f078a843e..dd53594ea7380 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -424,17 +424,17 @@ using ::atanhf _LIBCPP_USING_IF_EXISTS;
using ::cbrt _LIBCPP_USING_IF_EXISTS;
using ::cbrtf _LIBCPP_USING_IF_EXISTS;
-#if _LIBCPP_STD_VER >= 23 && __has_constexpr_builtin(__builtin_copysign)
+# if _LIBCPP_STD_VER >= 23 && __has_constexpr_builtin(__builtin_copysign)
_LIBCPP_HIDE_FROM_ABI constexpr double copysign(double __x, double __y) _NOEXCEPT {
return __builtin_copysign(__x, __y);
}
_LIBCPP_HIDE_FROM_ABI constexpr float copysignf(float __x, float __y) _NOEXCEPT {
return __builtin_copysignf(__x, __y);
}
-#else
+# else
using ::copysign _LIBCPP_USING_IF_EXISTS;
using ::copysignf _LIBCPP_USING_IF_EXISTS;
-#endif
+# endif
using ::erf _LIBCPP_USING_IF_EXISTS;
using ::erff _LIBCPP_USING_IF_EXISTS;
@@ -527,13 +527,13 @@ using ::asinhl _LIBCPP_USING_IF_EXISTS;
using ::atanhl _LIBCPP_USING_IF_EXISTS;
using ::cbrtl _LIBCPP_USING_IF_EXISTS;
-#if _LIBCPP_STD_VER >= 23 && __has_constexpr_builtin(__builtin_copysignl)
+# if _LIBCPP_STD_VER >= 23 && __has_constexpr_builtin(__builtin_copysignl)
_LIBCPP_HIDE_FROM_ABI constexpr long double copysignl(long double __x, long double __y) _NOEXCEPT {
return __builtin_copysignl(__x, __y);
}
-#else
+# else
using ::copysignl _LIBCPP_USING_IF_EXISTS;
-#endif
+# endif
using ::erfl _LIBCPP_USING_IF_EXISTS;
using ::erfcl _LIBCPP_USING_IF_EXISTS;
>From 77f55c816bbbbcb37986a805925a6fab7c68a636 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Mon, 17 Aug 2026 20:09:35 +0200
Subject: [PATCH 5/5] working example
---
libcxx/include/__math/copysign.h | 6 +++++-
libcxx/include/cmath | 8 +++-----
libcxx/include/math.h | 1 +
.../libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp | 4 ++--
4 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/libcxx/include/__math/copysign.h b/libcxx/include/__math/copysign.h
index c100c03650733..d55e32b88e16f 100644
--- a/libcxx/include/__math/copysign.h
+++ b/libcxx/include/__math/copysign.h
@@ -29,7 +29,11 @@ copysign(float __x, float __y) _NOEXCEPT {
return ::__builtin_copysignf(__x, __y);
}
-[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI double
+// This is a template to avoid conflicting with the C library's non-template `copysign(double, double)` overload
+// when both are visible in the same scope (e.g. after `using std::__math::copysign;` at global scope in <math.h>,
+// where the C library's own declaration for `double` is already present).
+template <class = int>
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI double
copysign(double __x, double __y) _NOEXCEPT {
return __builtin_copysign(__x, __y);
}
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index dd53594ea7380..283077b25d174 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -424,15 +424,13 @@ using ::atanhf _LIBCPP_USING_IF_EXISTS;
using ::cbrt _LIBCPP_USING_IF_EXISTS;
using ::cbrtf _LIBCPP_USING_IF_EXISTS;
-# if _LIBCPP_STD_VER >= 23 && __has_constexpr_builtin(__builtin_copysign)
-_LIBCPP_HIDE_FROM_ABI constexpr double copysign(double __x, double __y) _NOEXCEPT {
- return __builtin_copysign(__x, __y);
-}
+using std::__math::copysign;
+
+# if _LIBCPP_STD_VER >= 23 && __has_constexpr_builtin(__builtin_copysignf)
_LIBCPP_HIDE_FROM_ABI constexpr float copysignf(float __x, float __y) _NOEXCEPT {
return __builtin_copysignf(__x, __y);
}
# else
-using ::copysign _LIBCPP_USING_IF_EXISTS;
using ::copysignf _LIBCPP_USING_IF_EXISTS;
# endif
diff --git a/libcxx/include/math.h b/libcxx/include/math.h
index 6f520634d0646..9d0642398b7d4 100644
--- a/libcxx/include/math.h
+++ b/libcxx/include/math.h
@@ -491,6 +491,7 @@ using std::__math::atan2;
using std::__math::atanh;
using std::__math::cbrt;
using std::__math::ceil;
+using std::__math::copysign;
using std::__math::cos;
using std::__math::cosh;
using std::__math::erf;
diff --git a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp
index 0ae3f5802e21f..9df526e2bfdd3 100644
--- a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp
+++ b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp
@@ -155,9 +155,9 @@ int main(int, char**) {
ASSERT_NOT_CONSTEXPR_CXX23(std::remquof(0.5f, 1.0f, &DummyInt) == 0.5f);
ASSERT_NOT_CONSTEXPR_CXX23(std::remquol(0.5L, 1.0L, &DummyInt) == 0.5L);
- ASSERT_NOT_CONSTEXPR_CXX23(std::copysign(1.0f, 1.0f) == 1.0f);
+ ASSERT_CONSTEXPR_CXX23(std::copysign(1.0f, 1.0f) == 1.0f);
ASSERT_CONSTEXPR_CXX23(std::copysign(1.0, 1.0) == 1.0);
- ASSERT_NOT_CONSTEXPR_CXX23(std::copysign(1.0L, 1.0L) == 1.0L);
+ ASSERT_CONSTEXPR_CXX23(std::copysign(1.0L, 1.0L) == 1.0L);
ASSERT_CONSTEXPR_CXX23(std::copysignf(1.0f, 1.0f) == 1.0f);
ASSERT_CONSTEXPR_CXX23(std::copysignl(1.0L, 1.0L) == 1.0L);
More information about the libcxx-commits
mailing list