[libcxx-commits] [libcxx] WIP [libc++][math] Add `constexpr` to `std::isgreater()` (PR #210075)

Lucas Mellone via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jul 16 14:58:10 PDT 2026


https://github.com/lknknm updated https://github.com/llvm/llvm-project/pull/210075

>From 1fc2d6029a58ceaed872953980ae0f9b2bc9e178 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Thu, 16 Jul 2026 16:47:35 +0200
Subject: [PATCH 1/4] add: constexpr to isgreater

---
 libcxx/include/__math/traits.h                        | 11 +++++------
 .../numerics/c.math/constexpr-cxx23-clang.pass.cpp    |  6 +++---
 .../numerics/c.math/constexpr-cxx23-gcc.pass.cpp      |  6 +++---
 3 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h
index ff22cee7305d7..28269eef46743 100644
--- a/libcxx/include/__math/traits.h
+++ b/libcxx/include/__math/traits.h
@@ -82,8 +82,7 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
 #ifdef _LIBCPP_PREFERRED_OVERLOAD
 _LIBCPP_PREFERRED_OVERLOAD
 #endif
-    bool
-    isinf(double __x) _NOEXCEPT {
+    bool isinf(double __x) _NOEXCEPT {
   return __builtin_isinf(__x);
 }
 
@@ -106,8 +105,7 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
 #ifdef _LIBCPP_PREFERRED_OVERLOAD
 _LIBCPP_PREFERRED_OVERLOAD
 #endif
-    bool
-    isnan(double __x) _NOEXCEPT {
+    bool isnan(double __x) _NOEXCEPT {
   return __builtin_isnan(__x);
 }
 
@@ -137,7 +135,8 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
 // isgreater
 
 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool
+isgreater(_A1 __x, _A2 __y) _NOEXCEPT {
   using type = __promote_t<_A1, _A2>;
   return __builtin_isgreater((type)__x, (type)__y);
 }
@@ -216,7 +215,7 @@ template <class _A1>
 
 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 {
+[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) noexcept {
   using type = __promote_t<_A1, _A2>;
   return __builtin_isgreater((type)__x, (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 93865afc5e68b..642806ffbd960 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
@@ -227,9 +227,9 @@ int main(int, char**) {
   ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0) == 1);
   ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0L) == 1);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0f, 0.0f) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0, 0.0) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0L, 0.0L) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreater(-1.0f, 0.0f) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreater(-1.0, 0.0) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreater(-1.0L, 0.0L) == 0);
 
   ASSERT_NOT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0f, 0.0f) == 0);
   ASSERT_NOT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0, 0.0) == 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 d8779706bcee2..34513b459a056 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
@@ -221,9 +221,9 @@ int main(int, char**) {
   ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0) == 1);
   ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0L) == 1);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0f, 0.0f) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0, 0.0) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0L, 0.0L) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreater(-1.0f, 0.0f) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreater(-1.0, 0.0) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreater(-1.0L, 0.0L) == 0);
 
   ASSERT_NOT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0f, 0.0f) == 0);
   ASSERT_NOT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0, 0.0) == 0);

>From f6f5b24db9910930a4f63731ebc408653c43b530 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Thu, 16 Jul 2026 16:51:44 +0200
Subject: [PATCH 2/4] revert: clang-format mistake

---
 libcxx/include/__math/traits.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h
index 28269eef46743..48a68f31c2101 100644
--- a/libcxx/include/__math/traits.h
+++ b/libcxx/include/__math/traits.h
@@ -82,7 +82,8 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
 #ifdef _LIBCPP_PREFERRED_OVERLOAD
 _LIBCPP_PREFERRED_OVERLOAD
 #endif
-    bool isinf(double __x) _NOEXCEPT {
+    bool
+    isinf(double __x) _NOEXCEPT {
   return __builtin_isinf(__x);
 }
 
@@ -105,7 +106,8 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
 #ifdef _LIBCPP_PREFERRED_OVERLOAD
 _LIBCPP_PREFERRED_OVERLOAD
 #endif
-    bool isnan(double __x) _NOEXCEPT {
+    bool
+    isnan(double __x) _NOEXCEPT {
   return __builtin_isnan(__x);
 }
 

>From 9cfce54da2a26d9654a04d41c577bd5dacabe942 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Thu, 16 Jul 2026 23:44:41 +0200
Subject: [PATCH 3/4] add: isgreater.pass.cpp

---
 .../std/numerics/c.math/isgreater.pass.cpp    | 71 +++++++++++++++++++
 1 file changed, 71 insertions(+)
 create mode 100644 libcxx/test/std/numerics/c.math/isgreater.pass.cpp

diff --git a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
new file mode 100644
index 0000000000000..7b119df05f791
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
@@ -0,0 +1,71 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// bool isgreater(floating-point-type x, floating-point-type y); // constexpr since C++23
+
+// We don't control the implementation on windows
+// UNSUPPORTED: windows
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(std::isgreater(std::numeric_limits<T>::max(), T(0)));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+struct TestInt {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(std::isgreater(std::numeric_limits<T>::max(), T(0)));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+template <typename T>
+struct ConvertibleTo {
+  operator T() const { return T(1); }
+};
+
+template <typename T>
+struct ZeroConvertibleTo {
+  operator T() const { return T(0); }
+};
+
+int main(int, char**) {
+  types::for_each(types::floating_point_types(), TestFloat());
+  types::for_each(types::integral_types(), TestInt());
+
+  return 0;
+}

>From 184002328c9527189365872f28e6e5b7d1548ed6 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Thu, 16 Jul 2026 23:53:01 +0200
Subject: [PATCH 4/4] add: mixed-type promotion tests

---
 .../test/std/numerics/c.math/isgreater.pass.cpp | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
index 7b119df05f791..780b61e321cf1 100644
--- a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
@@ -23,6 +23,8 @@ struct TestFloat {
   template <class T>
   static TEST_CONSTEXPR_CXX23 bool test() {
     assert(std::isgreater(std::numeric_limits<T>::max(), T(0)));
+    assert(!std::isgreater(T(0), std::numeric_limits<T>::max()));
+    assert(!std::isgreater(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()));
 
     return true;
   }
@@ -40,6 +42,8 @@ struct TestInt {
   template <class T>
   static TEST_CONSTEXPR_CXX23 bool test() {
     assert(std::isgreater(std::numeric_limits<T>::max(), T(0)));
+    assert(!std::isgreater(T(0), std::numeric_limits<T>::max()));
+    assert(!std::isgreater(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()));
 
     return true;
   }
@@ -58,14 +62,17 @@ struct ConvertibleTo {
   operator T() const { return T(1); }
 };
 
-template <typename T>
-struct ZeroConvertibleTo {
-  operator T() const { return T(0); }
-};
-
 int main(int, char**) {
   types::for_each(types::floating_point_types(), TestFloat());
   types::for_each(types::integral_types(), TestInt());
 
+  // Make sure we can call `std::isgreater` with mixed-type promotions with __promote_t<_A1, _A2>.
+  {
+    assert(std::isgreater(2.0, 1));     // double vs int
+    assert(!std::isgreater(1, 2.0f));   // int vs float
+    assert(std::isgreater(2.0L, 1.0f)); // long double vs float
+    assert(!std::isgreater(std::numeric_limits<double>::quiet_NaN(), 0));
+  }
+
   return 0;
 }



More information about the libcxx-commits mailing list