[libcxx-commits] [libcxx] [libc++][math] Add `constexpr` to `std::fmax()` and `std::fmin()` (PR #222953)
Atharva Potdar via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Sep 22 07:47:02 PDT 2026
https://github.com/atharva-potdar updated https://github.com/llvm/llvm-project/pull/222953
>From 46f5f9d8cef1ebbe8143d9913acf119cb34f4ac7 Mon Sep 17 00:00:00 2001
From: atharva-potdar <atharvapotdar07 at gmail.com>
Date: Fri, 11 Sep 2026 19:21:07 +0530
Subject: [PATCH 1/3] add constexpr for fmax() and fmin()
---
libcxx/include/__math/min_max.h | 16 ++--
libcxx/include/cmath | 12 +--
.../c.math/constexpr-cxx23-clang.pass.cpp | 22 +++---
.../c.math/constexpr-cxx23-gcc.pass.cpp | 8 +-
libcxx/test/std/numerics/c.math/fmax.pass.cpp | 75 +++++++++++++++++++
libcxx/test/std/numerics/c.math/fmin.pass.cpp | 75 +++++++++++++++++++
6 files changed, 179 insertions(+), 29 deletions(-)
create mode 100644 libcxx/test/std/numerics/c.math/fmax.pass.cpp
create mode 100644 libcxx/test/std/numerics/c.math/fmin.pass.cpp
diff --git a/libcxx/include/__math/min_max.h b/libcxx/include/__math/min_max.h
index 1ddbb557d1e8f..c4257fea5dcc3 100644
--- a/libcxx/include/__math/min_max.h
+++ b/libcxx/include/__math/min_max.h
@@ -25,21 +25,21 @@ namespace __math {
// fmax
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI float fmax(float __x, float __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 float fmax(float __x, float __y) _NOEXCEPT {
return __builtin_fmaxf(__x, __y);
}
template <class = int>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI double fmax(double __x, double __y) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 double fmax(double __x, double __y) _NOEXCEPT {
return __builtin_fmax(__x, __y);
}
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI long double fmax(long double __x, long double __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 long double fmax(long double __x, long double __y) _NOEXCEPT {
return __builtin_fmaxl(__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> fmax(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 __promote_t<_A1, _A2> fmax(_A1 __x, _A2 __y) _NOEXCEPT {
using __result_type = __promote_t<_A1, _A2>;
static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), "");
return __math::fmax((__result_type)__x, (__result_type)__y);
@@ -47,21 +47,21 @@ template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_ar
// fmin
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI float fmin(float __x, float __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 float fmin(float __x, float __y) _NOEXCEPT {
return __builtin_fminf(__x, __y);
}
template <class = int>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI double fmin(double __x, double __y) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 double fmin(double __x, double __y) _NOEXCEPT {
return __builtin_fmin(__x, __y);
}
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI long double fmin(long double __x, long double __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 long double fmin(long double __x, long double __y) _NOEXCEPT {
return __builtin_fminl(__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> fmin(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 __promote_t<_A1, _A2> fmin(_A1 __x, _A2 __y) _NOEXCEPT {
using __result_type = __promote_t<_A1, _A2>;
static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), "");
return __math::fmin((__result_type)__x, (__result_type)__y);
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index c4f4030c2049b..e1289180a379d 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -196,13 +196,13 @@ floating_point fma (arithmetic x, arithmetic y, arithmetic z);
float fmaf(float x, float y, float z);
long double fmal(long double x, long double y, long double z);
-floating_point fmax (arithmetic x, arithmetic y);
-float fmaxf(float x, float y);
-long double fmaxl(long double x, long double y);
+floating_point fmax (arithmetic x, arithmetic y); // constexpr since C++23
+float fmaxf(float x, float y); // constexpr since C++23
+long double fmaxl(long double x, long double y); // constexpr since C++23
-floating_point fmin (arithmetic x, arithmetic y);
-float fminf(float x, float y);
-long double fminl(long double x, long double y);
+floating_point fmin (arithmetic x, arithmetic y); // constexpr since C++23
+float fminf(float x, float y); // constexpr since C++23
+long double fminl(long double x, long double y); // constexpr since C++23
double hermite(unsigned n, double x); // C++17
float hermite(unsigned n, float x); // C++17
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..95c21eb144bf4 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
@@ -185,17 +185,17 @@ int main(int, char**) {
ASSERT_NOT_CONSTEXPR_CXX23(std::fdimf(1.0f, 0.0f) == 1.0f);
ASSERT_NOT_CONSTEXPR_CXX23(std::fdiml(1.0L, 0.0L) == 1.0L);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmax(1.0f, 0.0f) == 1.0f);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmax(1.0, 0.0) == 1.0);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmax(1.0L, 0.0L) == 1.0L);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmaxf(1.0f, 0.0f) == 1.0f);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmaxl(1.0L, 0.0L) == 1.0L);
-
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmin(1.0f, 0.0f) == 0.0f);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmin(1.0, 0.0) == 0.0);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmin(1.0L, 0.0L) == 0.0L);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fminf(1.0f, 0.0f) == 0.0f);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fminl(1.0L, 0.0L) == 0.0L);
+ ASSERT_CONSTEXPR_CXX23(std::fmax(1.0f, 0.0f) == 1.0f);
+ ASSERT_CONSTEXPR_CXX23(std::fmax(1.0, 0.0) == 1.0);
+ ASSERT_CONSTEXPR_CXX23(std::fmax(1.0L, 0.0L) == 1.0L);
+ ASSERT_CONSTEXPR_CXX23(std::fmaxf(1.0f, 0.0f) == 1.0f);
+ ASSERT_CONSTEXPR_CXX23(std::fmaxl(1.0L, 0.0L) == 1.0L);
+
+ ASSERT_CONSTEXPR_CXX23(std::fmin(1.0f, 0.0f) == 0.0f);
+ ASSERT_CONSTEXPR_CXX23(std::fmin(1.0, 0.0) == 0.0);
+ ASSERT_CONSTEXPR_CXX23(std::fmin(1.0L, 0.0L) == 0.0L);
+ ASSERT_CONSTEXPR_CXX23(std::fminf(1.0f, 0.0f) == 0.0f);
+ ASSERT_CONSTEXPR_CXX23(std::fminl(1.0L, 0.0L) == 0.0L);
ASSERT_NOT_CONSTEXPR_CXX23(std::fma(1.0f, 1.0f, 1.0f) == 2.0f);
ASSERT_NOT_CONSTEXPR_CXX23(std::fma(1.0, 1.0, 1.0) == 2.0);
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..b444d39a7a6cc 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
@@ -179,15 +179,15 @@ int main(int, char**) {
ASSERT_CONSTEXPR_CXX23(std::fdimf(1.0f, 0.0f) == 1.0f);
ASSERT_CONSTEXPR_CXX23(std::fdiml(1.0L, 0.0L) == 1.0L);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmax(1.0f, 0.0f) == 1.0f);
+ ASSERT_CONSTEXPR_CXX23(std::fmax(1.0f, 0.0f) == 1.0f);
ASSERT_CONSTEXPR_CXX23(std::fmax(1.0, 0.0) == 1.0);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmax(1.0L, 0.0L) == 1.0L);
+ ASSERT_CONSTEXPR_CXX23(std::fmax(1.0L, 0.0L) == 1.0L);
ASSERT_CONSTEXPR_CXX23(std::fmaxf(1.0f, 0.0f) == 1.0f);
ASSERT_CONSTEXPR_CXX23(std::fmaxl(1.0L, 0.0L) == 1.0L);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmin(1.0f, 0.0f) == 0.0f);
+ ASSERT_CONSTEXPR_CXX23(std::fmin(1.0f, 0.0f) == 0.0f);
ASSERT_CONSTEXPR_CXX23(std::fmin(1.0, 0.0) == 0.0);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmin(1.0L, 0.0L) == 0.0L);
+ ASSERT_CONSTEXPR_CXX23(std::fmin(1.0L, 0.0L) == 0.0L);
ASSERT_CONSTEXPR_CXX23(std::fminf(1.0f, 0.0f) == 0.0f);
ASSERT_CONSTEXPR_CXX23(std::fminl(1.0L, 0.0L) == 0.0L);
diff --git a/libcxx/test/std/numerics/c.math/fmax.pass.cpp b/libcxx/test/std/numerics/c.math/fmax.pass.cpp
new file mode 100644
index 0000000000000..590e40f448e69
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/fmax.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// floating-point-type fmax(floating-point-type x, floating-point-type y); // constexpr since C++23
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() const {
+ using lim = std::numeric_limits<T>;
+ TEST_CONSTEXPR_CXX23 T inf = lim::infinity();
+ TEST_CONSTEXPR_CXX23 T nan = lim::quiet_NaN();
+ TEST_CONSTEXPR_CXX23 T s_nan = lim::signaling_NaN();
+
+ assert(std::fmax(T(1), T(2)) == T(2));
+ assert(std::fmax(T(2), T(1)) == T(2));
+ assert(std::fmax(T(-1), T(0)) == T(0));
+
+ assert(std::fmax(inf, T(1)) == inf);
+ assert(std::fmax(T(1), inf) == inf);
+ assert(std::fmax(-inf, T(1)) == T(1));
+ assert(std::fmax(T(1), -inf) == T(1));
+
+ assert(std::fmax(nan, T(1)) == T(1));
+ assert(std::fmax(T(1), nan) == T(1));
+ assert(std::fmax(s_nan, T(1)) == T(1));
+
+ assert(std::isnan(std::fmax(nan, nan)));
+ }
+};
+
+struct TestInt {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() const {
+ using lim = std::numeric_limits<T>;
+ TEST_CONSTEXPR_CXX23 T max = lim::max();
+ TEST_CONSTEXPR_CXX23 T low = lim::lowest();
+
+ assert(std::fmax(T(0), T(1)) == T(1));
+ assert(std::fmax(T(1), T(0)) == T(1));
+ assert(std::fmax(low, max) == max);
+
+ if (std::is_signed<T>::value) {
+ assert(std::fmax(T(-1), T(0)) == T(0));
+ assert(std::fmax(low, T(0)) == T(0));
+ }
+ }
+};
+
+TEST_CONSTEXPR_CXX23 bool test() {
+ types::for_each(types::floating_point_types(), TestFloat());
+ types::for_each(types::integral_types(), TestInt());
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 23
+ static_assert(test());
+#endif
+ return 0;
+}
diff --git a/libcxx/test/std/numerics/c.math/fmin.pass.cpp b/libcxx/test/std/numerics/c.math/fmin.pass.cpp
new file mode 100644
index 0000000000000..a2c41bfa94021
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/fmin.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// floating-point-type fmin(floating-point-type x, floating-point-type y); // constexpr since C++23
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() const {
+ using lim = std::numeric_limits<T>;
+ TEST_CONSTEXPR_CXX23 T inf = lim::infinity();
+ TEST_CONSTEXPR_CXX23 T nan = lim::quiet_NaN();
+ TEST_CONSTEXPR_CXX23 T s_nan = lim::signaling_NaN();
+
+ assert(std::fmin(T(1), T(2)) == T(1));
+ assert(std::fmin(T(2), T(1)) == T(1));
+ assert(std::fmin(T(-1), T(0)) == T(-1));
+
+ assert(std::fmin(inf, T(1)) == T(1));
+ assert(std::fmin(T(1), inf) == T(1));
+ assert(std::fmin(-inf, T(1)) == -inf);
+ assert(std::fmin(T(1), -inf) == -inf);
+
+ assert(std::fmin(nan, T(1)) == T(1));
+ assert(std::fmin(T(1), nan) == T(1));
+ assert(std::fmin(s_nan, T(1)) == T(1));
+
+ assert(std::isnan(std::fmin(nan, nan)));
+ }
+};
+
+struct TestInt {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() const {
+ using lim = std::numeric_limits<T>;
+ TEST_CONSTEXPR_CXX23 T max = lim::max();
+ TEST_CONSTEXPR_CXX23 T low = lim::lowest();
+
+ assert(std::fmin(T(0), T(1)) == T(0));
+ assert(std::fmin(T(1), T(0)) == T(0));
+ assert(std::fmin(low, max) == low);
+
+ if (std::is_signed<T>::value) {
+ assert(std::fmin(T(-1), T(0)) == T(-1));
+ assert(std::fmin(low, T(0)) == T(low));
+ }
+ }
+};
+
+TEST_CONSTEXPR_CXX23 bool test() {
+ types::for_each(types::floating_point_types(), TestFloat());
+ types::for_each(types::integral_types(), TestInt());
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 23
+ static_assert(test());
+#endif
+ return 0;
+}
>From c4a2eebc23006e831f3bf9812b95cba8091f7736 Mon Sep 17 00:00:00 2001
From: atharva-potdar <atharvapotdar07 at gmail.com>
Date: Fri, 11 Sep 2026 21:37:15 +0530
Subject: [PATCH 2/3] fix: add defensive checks for assert, include; remove
s_nan, low/high from tests
---
libcxx/include/__math/min_max.h | 22 ++++++++++++-------
.../c.math/constexpr-cxx23-clang.pass.cpp | 14 ++++++++++++
libcxx/test/std/numerics/c.math/fmax.pass.cpp | 6 -----
libcxx/test/std/numerics/c.math/fmin.pass.cpp | 6 -----
4 files changed, 28 insertions(+), 20 deletions(-)
diff --git a/libcxx/include/__math/min_max.h b/libcxx/include/__math/min_max.h
index c4257fea5dcc3..eba7c4b76b951 100644
--- a/libcxx/include/__math/min_max.h
+++ b/libcxx/include/__math/min_max.h
@@ -9,6 +9,12 @@
#ifndef _LIBCPP___MATH_MIN_MAX_H
#define _LIBCPP___MATH_MIN_MAX_H
+#if __has_constexpr_builtin(__builtin_fmax) || defined(_LIBCPP_COMPILER_GCC)
+# define _LIBCPP_CONSTEXPR_FMAX_FMIN _LIBCPP_CONSTEXPR_SINCE_CXX23
+#else
+# define _LIBCPP_CONSTEXPR_FMAX_FMIN
+#endif
+
#include <__config>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_arithmetic.h>
@@ -25,21 +31,21 @@ namespace __math {
// fmax
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 float fmax(float __x, float __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_FMAX_FMIN float fmax(float __x, float __y) _NOEXCEPT {
return __builtin_fmaxf(__x, __y);
}
template <class = int>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 double fmax(double __x, double __y) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_FMAX_FMIN double fmax(double __x, double __y) _NOEXCEPT {
return __builtin_fmax(__x, __y);
}
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 long double fmax(long double __x, long double __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_FMAX_FMIN long double fmax(long double __x, long double __y) _NOEXCEPT {
return __builtin_fmaxl(__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 _LIBCPP_CONSTEXPR_SINCE_CXX23 __promote_t<_A1, _A2> fmax(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_FMAX_FMIN __promote_t<_A1, _A2> fmax(_A1 __x, _A2 __y) _NOEXCEPT {
using __result_type = __promote_t<_A1, _A2>;
static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), "");
return __math::fmax((__result_type)__x, (__result_type)__y);
@@ -47,21 +53,21 @@ template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_ar
// fmin
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 float fmin(float __x, float __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_FMAX_FMIN float fmin(float __x, float __y) _NOEXCEPT {
return __builtin_fminf(__x, __y);
}
template <class = int>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 double fmin(double __x, double __y) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_FMAX_FMIN double fmin(double __x, double __y) _NOEXCEPT {
return __builtin_fmin(__x, __y);
}
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 long double fmin(long double __x, long double __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_FMAX_FMIN long double fmin(long double __x, long double __y) _NOEXCEPT {
return __builtin_fminl(__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 _LIBCPP_CONSTEXPR_SINCE_CXX23 __promote_t<_A1, _A2> fmin(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_FMAX_FMIN __promote_t<_A1, _A2> fmin(_A1 __x, _A2 __y) _NOEXCEPT {
using __result_type = __promote_t<_A1, _A2>;
static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), "");
return __math::fmin((__result_type)__x, (__result_type)__y);
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 95c21eb144bf4..924ef8f4a0678 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
@@ -185,6 +185,7 @@ int main(int, char**) {
ASSERT_NOT_CONSTEXPR_CXX23(std::fdimf(1.0f, 0.0f) == 1.0f);
ASSERT_NOT_CONSTEXPR_CXX23(std::fdiml(1.0L, 0.0L) == 1.0L);
+#if __has_constexpr_builtin(__builtin_fmax)
ASSERT_CONSTEXPR_CXX23(std::fmax(1.0f, 0.0f) == 1.0f);
ASSERT_CONSTEXPR_CXX23(std::fmax(1.0, 0.0) == 1.0);
ASSERT_CONSTEXPR_CXX23(std::fmax(1.0L, 0.0L) == 1.0L);
@@ -196,6 +197,19 @@ int main(int, char**) {
ASSERT_CONSTEXPR_CXX23(std::fmin(1.0L, 0.0L) == 0.0L);
ASSERT_CONSTEXPR_CXX23(std::fminf(1.0f, 0.0f) == 0.0f);
ASSERT_CONSTEXPR_CXX23(std::fminl(1.0L, 0.0L) == 0.0L);
+#else
+ ASSERT_NOT_CONSTEXPR_CXX23(std::fmax(1.0f, 0.0f) == 1.0f);
+ ASSERT_NOT_CONSTEXPR_CXX23(std::fmax(1.0, 0.0) == 1.0);
+ ASSERT_NOT_CONSTEXPR_CXX23(std::fmax(1.0L, 0.0L) == 1.0L);
+ ASSERT_NOT_CONSTEXPR_CXX23(std::fmaxf(1.0f, 0.0f) == 1.0f);
+ ASSERT_NOT_CONSTEXPR_CXX23(std::fmaxl(1.0L, 0.0L) == 1.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX23(std::fmin(1.0f, 0.0f) == 0.0f);
+ ASSERT_NOT_CONSTEXPR_CXX23(std::fmin(1.0, 0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX23(std::fmin(1.0L, 0.0L) == 0.0L);
+ ASSERT_NOT_CONSTEXPR_CXX23(std::fminf(1.0f, 0.0f) == 0.0f);
+ ASSERT_NOT_CONSTEXPR_CXX23(std::fminl(1.0L, 0.0L) == 0.0L);
+#endif
ASSERT_NOT_CONSTEXPR_CXX23(std::fma(1.0f, 1.0f, 1.0f) == 2.0f);
ASSERT_NOT_CONSTEXPR_CXX23(std::fma(1.0, 1.0, 1.0) == 2.0);
diff --git a/libcxx/test/std/numerics/c.math/fmax.pass.cpp b/libcxx/test/std/numerics/c.math/fmax.pass.cpp
index 590e40f448e69..69b6cf4c6ed49 100644
--- a/libcxx/test/std/numerics/c.math/fmax.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/fmax.pass.cpp
@@ -22,7 +22,6 @@ struct TestFloat {
using lim = std::numeric_limits<T>;
TEST_CONSTEXPR_CXX23 T inf = lim::infinity();
TEST_CONSTEXPR_CXX23 T nan = lim::quiet_NaN();
- TEST_CONSTEXPR_CXX23 T s_nan = lim::signaling_NaN();
assert(std::fmax(T(1), T(2)) == T(2));
assert(std::fmax(T(2), T(1)) == T(2));
@@ -35,7 +34,6 @@ struct TestFloat {
assert(std::fmax(nan, T(1)) == T(1));
assert(std::fmax(T(1), nan) == T(1));
- assert(std::fmax(s_nan, T(1)) == T(1));
assert(std::isnan(std::fmax(nan, nan)));
}
@@ -45,16 +43,12 @@ struct TestInt {
template <class T>
TEST_CONSTEXPR_CXX23 void operator()() const {
using lim = std::numeric_limits<T>;
- TEST_CONSTEXPR_CXX23 T max = lim::max();
- TEST_CONSTEXPR_CXX23 T low = lim::lowest();
assert(std::fmax(T(0), T(1)) == T(1));
assert(std::fmax(T(1), T(0)) == T(1));
- assert(std::fmax(low, max) == max);
if (std::is_signed<T>::value) {
assert(std::fmax(T(-1), T(0)) == T(0));
- assert(std::fmax(low, T(0)) == T(0));
}
}
};
diff --git a/libcxx/test/std/numerics/c.math/fmin.pass.cpp b/libcxx/test/std/numerics/c.math/fmin.pass.cpp
index a2c41bfa94021..5ffcc479d6d15 100644
--- a/libcxx/test/std/numerics/c.math/fmin.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/fmin.pass.cpp
@@ -22,7 +22,6 @@ struct TestFloat {
using lim = std::numeric_limits<T>;
TEST_CONSTEXPR_CXX23 T inf = lim::infinity();
TEST_CONSTEXPR_CXX23 T nan = lim::quiet_NaN();
- TEST_CONSTEXPR_CXX23 T s_nan = lim::signaling_NaN();
assert(std::fmin(T(1), T(2)) == T(1));
assert(std::fmin(T(2), T(1)) == T(1));
@@ -35,7 +34,6 @@ struct TestFloat {
assert(std::fmin(nan, T(1)) == T(1));
assert(std::fmin(T(1), nan) == T(1));
- assert(std::fmin(s_nan, T(1)) == T(1));
assert(std::isnan(std::fmin(nan, nan)));
}
@@ -45,16 +43,12 @@ struct TestInt {
template <class T>
TEST_CONSTEXPR_CXX23 void operator()() const {
using lim = std::numeric_limits<T>;
- TEST_CONSTEXPR_CXX23 T max = lim::max();
- TEST_CONSTEXPR_CXX23 T low = lim::lowest();
assert(std::fmin(T(0), T(1)) == T(0));
assert(std::fmin(T(1), T(0)) == T(0));
- assert(std::fmin(low, max) == low);
if (std::is_signed<T>::value) {
assert(std::fmin(T(-1), T(0)) == T(-1));
- assert(std::fmin(low, T(0)) == T(low));
}
}
};
>From 7a8a6870c3c137f142af01f2eb3e2938b704f592 Mon Sep 17 00:00:00 2001
From: atharva-potdar <atharvapotdar07 at gmail.com>
Date: Tue, 22 Sep 2026 20:10:17 +0530
Subject: [PATCH 3/3] revert the conditional macros for constexpr on clang
---
libcxx/include/__math/min_max.h | 22 +++++++------------
.../c.math/constexpr-cxx23-clang.pass.cpp | 14 ------------
2 files changed, 8 insertions(+), 28 deletions(-)
diff --git a/libcxx/include/__math/min_max.h b/libcxx/include/__math/min_max.h
index eba7c4b76b951..c4257fea5dcc3 100644
--- a/libcxx/include/__math/min_max.h
+++ b/libcxx/include/__math/min_max.h
@@ -9,12 +9,6 @@
#ifndef _LIBCPP___MATH_MIN_MAX_H
#define _LIBCPP___MATH_MIN_MAX_H
-#if __has_constexpr_builtin(__builtin_fmax) || defined(_LIBCPP_COMPILER_GCC)
-# define _LIBCPP_CONSTEXPR_FMAX_FMIN _LIBCPP_CONSTEXPR_SINCE_CXX23
-#else
-# define _LIBCPP_CONSTEXPR_FMAX_FMIN
-#endif
-
#include <__config>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_arithmetic.h>
@@ -31,21 +25,21 @@ namespace __math {
// fmax
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_FMAX_FMIN float fmax(float __x, float __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 float fmax(float __x, float __y) _NOEXCEPT {
return __builtin_fmaxf(__x, __y);
}
template <class = int>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_FMAX_FMIN double fmax(double __x, double __y) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 double fmax(double __x, double __y) _NOEXCEPT {
return __builtin_fmax(__x, __y);
}
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_FMAX_FMIN long double fmax(long double __x, long double __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 long double fmax(long double __x, long double __y) _NOEXCEPT {
return __builtin_fmaxl(__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 _LIBCPP_CONSTEXPR_FMAX_FMIN __promote_t<_A1, _A2> fmax(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 __promote_t<_A1, _A2> fmax(_A1 __x, _A2 __y) _NOEXCEPT {
using __result_type = __promote_t<_A1, _A2>;
static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), "");
return __math::fmax((__result_type)__x, (__result_type)__y);
@@ -53,21 +47,21 @@ template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_ar
// fmin
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_FMAX_FMIN float fmin(float __x, float __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 float fmin(float __x, float __y) _NOEXCEPT {
return __builtin_fminf(__x, __y);
}
template <class = int>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_FMAX_FMIN double fmin(double __x, double __y) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 double fmin(double __x, double __y) _NOEXCEPT {
return __builtin_fmin(__x, __y);
}
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_FMAX_FMIN long double fmin(long double __x, long double __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 long double fmin(long double __x, long double __y) _NOEXCEPT {
return __builtin_fminl(__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 _LIBCPP_CONSTEXPR_FMAX_FMIN __promote_t<_A1, _A2> fmin(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 __promote_t<_A1, _A2> fmin(_A1 __x, _A2 __y) _NOEXCEPT {
using __result_type = __promote_t<_A1, _A2>;
static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), "");
return __math::fmin((__result_type)__x, (__result_type)__y);
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 924ef8f4a0678..95c21eb144bf4 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
@@ -185,7 +185,6 @@ int main(int, char**) {
ASSERT_NOT_CONSTEXPR_CXX23(std::fdimf(1.0f, 0.0f) == 1.0f);
ASSERT_NOT_CONSTEXPR_CXX23(std::fdiml(1.0L, 0.0L) == 1.0L);
-#if __has_constexpr_builtin(__builtin_fmax)
ASSERT_CONSTEXPR_CXX23(std::fmax(1.0f, 0.0f) == 1.0f);
ASSERT_CONSTEXPR_CXX23(std::fmax(1.0, 0.0) == 1.0);
ASSERT_CONSTEXPR_CXX23(std::fmax(1.0L, 0.0L) == 1.0L);
@@ -197,19 +196,6 @@ int main(int, char**) {
ASSERT_CONSTEXPR_CXX23(std::fmin(1.0L, 0.0L) == 0.0L);
ASSERT_CONSTEXPR_CXX23(std::fminf(1.0f, 0.0f) == 0.0f);
ASSERT_CONSTEXPR_CXX23(std::fminl(1.0L, 0.0L) == 0.0L);
-#else
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmax(1.0f, 0.0f) == 1.0f);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmax(1.0, 0.0) == 1.0);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmax(1.0L, 0.0L) == 1.0L);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmaxf(1.0f, 0.0f) == 1.0f);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmaxl(1.0L, 0.0L) == 1.0L);
-
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmin(1.0f, 0.0f) == 0.0f);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmin(1.0, 0.0) == 0.0);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fmin(1.0L, 0.0L) == 0.0L);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fminf(1.0f, 0.0f) == 0.0f);
- ASSERT_NOT_CONSTEXPR_CXX23(std::fminl(1.0L, 0.0L) == 0.0L);
-#endif
ASSERT_NOT_CONSTEXPR_CXX23(std::fma(1.0f, 1.0f, 1.0f) == 2.0f);
ASSERT_NOT_CONSTEXPR_CXX23(std::fma(1.0, 1.0, 1.0) == 2.0);
More information about the libcxx-commits
mailing list