[libcxx-commits] [libcxx] [libc++][math] Add constexpr for std::abs() (PR #146633)

Arjun Patel via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jul 2 12:21:16 PDT 2025


https://github.com/arjunUpatel updated https://github.com/llvm/llvm-project/pull/146633

>From 5c135a1b2f5ca89bfb6d1c43ef17cd95c892ea82 Mon Sep 17 00:00:00 2001
From: Arjun Patel <arjunpatel151002 at gmail.com>
Date: Wed, 2 Jul 2025 00:14:13 -0400
Subject: [PATCH 1/5] Update abs test

---
 libcxx/test/std/numerics/c.math/abs.pass.cpp | 30 +++++++++++++-------
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/libcxx/test/std/numerics/c.math/abs.pass.cpp b/libcxx/test/std/numerics/c.math/abs.pass.cpp
index 51aee6e986836..908620b2a3290 100644
--- a/libcxx/test/std/numerics/c.math/abs.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/abs.pass.cpp
@@ -20,21 +20,29 @@ struct correct_size_int {
 };
 
 template <class Source, class Result>
-void test_abs() {
-  Source neg_val = -5;
-  Source pos_val = 5;
-  Result res     = 5;
+TEST_CONSTEXPR_CXX23 void test_abs() {
+  TEST_CONSTEXPR_CXX23 Source neg_val = -5;
+  TEST_CONSTEXPR_CXX23 Source pos_val = 5;
+  TEST_CONSTEXPR_CXX23 Result res     = 5;
 
   ASSERT_SAME_TYPE(decltype(std::abs(neg_val)), Result);
-
-  assert(std::abs(neg_val) == res);
-  assert(std::abs(pos_val) == res);
+  #if TEST_STD_VER >= 23
+    static_assert(std::abs(neg_val) == res);
+    static_assert(std::abs(pos_val) == res);
+  #else 
+    assert(std::abs(neg_val) == res);
+    assert(std::abs(pos_val) == res);
+  #endif
 }
 
-void test_big() {
-  long long int big_value          = std::numeric_limits<long long int>::max(); // a value too big for ints to store
-  long long int negative_big_value = -big_value;
-  assert(std::abs(negative_big_value) == big_value); // make sure it doesn't get casted to a smaller type
+TEST_CONSTEXPR_CXX23 void test_big() {
+  TEST_CONSTEXPR_CXX23 long long int big_value          = std::numeric_limits<long long int>::max(); // a value too big for ints to store
+  TEST_CONSTEXPR_CXX23 long long int negative_big_value = -big_value;
+  #if TEST_STD_VER >= 23
+    static_assert(std::abs(negative_big_value) == big_value); // make sure it doesn't get casted to a smaller type
+  #else
+    assert(std::abs(negative_big_value) == big_value); // make sure it doesn't get casted to a smaller type
+  #endif
 }
 
 // The following is helpful to keep in mind:

>From 32d133a20a41cfc936e8f8dae9f05b951692c3c9 Mon Sep 17 00:00:00 2001
From: Arjun Patel <arjunpatel151002 at gmail.com>
Date: Wed, 2 Jul 2025 00:27:59 -0400
Subject: [PATCH 2/5] Make abs traits constexpr

---
 libcxx/include/__math/abs.h | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/libcxx/include/__math/abs.h b/libcxx/include/__math/abs.h
index b780159f11ebf..a1d5854ac8878 100644
--- a/libcxx/include/__math/abs.h
+++ b/libcxx/include/__math/abs.h
@@ -41,25 +41,25 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
 
 // abs
 
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline float abs(float __x) _NOEXCEPT { return __builtin_fabsf(__x); }
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline double abs(double __x) _NOEXCEPT { return __builtin_fabs(__x); }
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline float abs(float __x) _NOEXCEPT { return __builtin_fabsf(__x); }
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline double abs(double __x) _NOEXCEPT { return __builtin_fabs(__x); }
 
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline long double abs(long double __x) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline long double abs(long double __x) _NOEXCEPT {
   return __builtin_fabsl(__x);
 }
 
 template <class = int>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline int abs(int __x) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline int abs(int __x) _NOEXCEPT {
   return __builtin_abs(__x);
 }
 
 template <class = int>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline long abs(long __x) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline long abs(long __x) _NOEXCEPT {
   return __builtin_labs(__x);
 }
 
 template <class = int>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline long long abs(long long __x) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline long long abs(long long __x) _NOEXCEPT {
   return __builtin_llabs(__x);
 }
 

>From c8434670860850b14a47b64e13b6680b85554b7e Mon Sep 17 00:00:00 2001
From: Arjun Patel <arjunpatel151002 at gmail.com>
Date: Wed, 2 Jul 2025 00:29:49 -0400
Subject: [PATCH 3/5] Update clang cpp23 constexpr tests

---
 .../numerics/c.math/constexpr-cxx23-clang.pass.cpp   | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

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 3f17f21e8c108..64164240c8564 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
@@ -40,12 +40,12 @@ int main(int, char**) {
   double DummyDouble;
   long double DummyLongDouble;
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1L) == 1L);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1LL) == 1LL);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0f) == 1.0f);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0) == 1.0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0L) == 1.0L);
+  ASSERT_CONSTEXPR_CXX23(std::abs(-1) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::abs(-1L) == 1L);
+  ASSERT_CONSTEXPR_CXX23(std::abs(-1LL) == 1LL);
+  ASSERT_CONSTEXPR_CXX23(std::abs(-1.0f) == 1.0f);
+  ASSERT_CONSTEXPR_CXX23(std::abs(-1.0) == 1.0);
+  ASSERT_CONSTEXPR_CXX23(std::abs(-1.0L) == 1.0L);
 
   ASSERT_NOT_CONSTEXPR_CXX23(std::labs(-1L) == 1L);
   ASSERT_NOT_CONSTEXPR_CXX23(std::llabs(-1LL) == 1LL);

>From 4f49c871162f8e95d0867dbcbccd5b870f6a657a Mon Sep 17 00:00:00 2001
From: Arjun Patel <arjunpatel151002 at gmail.com>
Date: Wed, 2 Jul 2025 14:56:07 -0400
Subject: [PATCH 4/5] Update gcc cpp23 constexpr tests

---
 .../numerics/c.math/constexpr-cxx23-gcc.pass.cpp       | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

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..a4dcd3eb0fac7 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
@@ -38,11 +38,11 @@ int main(int, char**) {
   long double DummyLongDouble;
 
   ASSERT_CONSTEXPR_CXX23(std::abs(-1) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1L) == 1L);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1LL) == 1LL);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0f) == 1.0f);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0) == 1.0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0L) == 1.0L);
+  ASSERT_CONSTEXPR_CXX23(std::abs(-1L) == 1L);
+  ASSERT_CONSTEXPR_CXX23(std::abs(-1LL) == 1LL);
+  ASSERT_CONSTEXPR_CXX23(std::abs(-1.0f) == 1.0f);
+  ASSERT_CONSTEXPR_CXX23(std::abs(-1.0) == 1.0);
+  ASSERT_CONSTEXPR_CXX23(std::abs(-1.0L) == 1.0L);
 
   ASSERT_CONSTEXPR_CXX23(std::labs(-1L) == 1L);
   ASSERT_CONSTEXPR_CXX23(std::llabs(-1LL) == 1LL);

>From c07b0d8f7c8abe9f00f1e423f995b263c8e5f551 Mon Sep 17 00:00:00 2001
From: Arjun Patel <arjunpatel151002 at gmail.com>
Date: Wed, 2 Jul 2025 15:20:55 -0400
Subject: [PATCH 5/5] Check constexpr builtins for clang

---
 .../c.math/constexpr-cxx23-clang.pass.cpp     | 37 ++++++++++++++++---
 1 file changed, 31 insertions(+), 6 deletions(-)

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 64164240c8564..675270264ce7c 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
@@ -40,12 +40,37 @@ int main(int, char**) {
   double DummyDouble;
   long double DummyLongDouble;
 
-  ASSERT_CONSTEXPR_CXX23(std::abs(-1) == 1);
-  ASSERT_CONSTEXPR_CXX23(std::abs(-1L) == 1L);
-  ASSERT_CONSTEXPR_CXX23(std::abs(-1LL) == 1LL);
-  ASSERT_CONSTEXPR_CXX23(std::abs(-1.0f) == 1.0f);
-  ASSERT_CONSTEXPR_CXX23(std::abs(-1.0) == 1.0);
-  ASSERT_CONSTEXPR_CXX23(std::abs(-1.0L) == 1.0L);
+  // TODO(LLVM 22): Remove `__has_constexpr_builtin` conditional once support for Clang 19 is dropped.
+  #if __has_constexpr_builtin(__builtin_abs)
+    ASSERT_CONSTEXPR_CXX23(std::abs(-1) == 1);
+  #else
+    ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1) == 1);
+  #endif
+  #if __has_constexpr_builtin(__builtin_labs)
+    ASSERT_CONSTEXPR_CXX23(std::abs(-1L) == 1L);
+  #else
+    ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1L) == 1L);
+  #endif
+  #if __has_constexpr_builtin(__builtin_llabs)
+    ASSERT_CONSTEXPR_CXX23(std::abs(-1LL) == 1LL);
+  #else
+    ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1LL) == 1LL);
+  #endif
+  #if __has_constexpr_builtin(__builtin_fabsf)
+    ASSERT_CONSTEXPR_CXX23(std::abs(-1.0f) == 1.0f);
+  #else
+    ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0f) == 1.0f);
+  #endif
+  #if __has_constexpr_builtin(__builtin_fabs)
+    ASSERT_CONSTEXPR_CXX23(std::abs(-1.0) == 1.0);
+  #else
+    ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0) == 1.0);
+  #endif
+  #if __has_constexpr_builtin(__builtin_fabsl)
+    ASSERT_CONSTEXPR_CXX23(std::abs(-1.0L) == 1.0L);
+  #else
+    ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0L) == 1.0L);
+  #endif
 
   ASSERT_NOT_CONSTEXPR_CXX23(std::labs(-1L) == 1L);
   ASSERT_NOT_CONSTEXPR_CXX23(std::llabs(-1LL) == 1LL);



More information about the libcxx-commits mailing list