[libcxx-commits] [libcxx] [libc++][math] Fix testing `constexpr` at compile time (PR #105984)

Robin Caloudis via libcxx-commits libcxx-commits at lists.llvm.org
Sun Aug 25 05:48:45 PDT 2024


https://github.com/robincaloudis created https://github.com/llvm/llvm-project/pull/105984

None

>From eceb3158c36a5e3f8009aa01257df5dfa6f07260 Mon Sep 17 00:00:00 2001
From: Robin Caloudis <robin.caloudis at gmx.de>
Date: Sun, 25 Aug 2024 14:45:05 +0200
Subject: [PATCH] Test constexpr at compile time

---
 .../std/numerics/c.math/isfinite.pass.cpp     | 56 +++++++++----------
 .../test/std/numerics/c.math/isinf.pass.cpp   | 56 +++++++++----------
 .../test/std/numerics/c.math/isnan.pass.cpp   | 56 +++++++++----------
 .../std/numerics/c.math/isnormal.pass.cpp     | 48 ++++++++--------
 4 files changed, 100 insertions(+), 116 deletions(-)

diff --git a/libcxx/test/std/numerics/c.math/isfinite.pass.cpp b/libcxx/test/std/numerics/c.math/isfinite.pass.cpp
index 3d5be616343343..e6d6af52ed3e94 100644
--- a/libcxx/test/std/numerics/c.math/isfinite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isfinite.pass.cpp
@@ -18,53 +18,49 @@
 #include "test_macros.h"
 #include "type_algorithms.h"
 
+#if TEST_STD_VER >= 23
+#  define COMPILE_OR_RUNTIME_ASSERT(expr) static_assert(expr)
+#else
+#  define COMPILE_OR_RUNTIME_ASSERT(expr) assert(expr)
+#endif
+
 struct TestFloat {
   template <class T>
-  static TEST_CONSTEXPR_CXX23 bool test() {
-    assert(std::isfinite(std::numeric_limits<T>::max()));
-    assert(!std::isfinite(std::numeric_limits<T>::infinity()));
-    assert(std::isfinite(std::numeric_limits<T>::min()));
-    assert(std::isfinite(std::numeric_limits<T>::denorm_min()));
-    assert(std::isfinite(std::numeric_limits<T>::lowest()));
-    assert(!std::isfinite(-std::numeric_limits<T>::infinity()));
-    assert(std::isfinite(T(0)));
-    assert(!std::isfinite(std::numeric_limits<T>::quiet_NaN()));
-    assert(!std::isfinite(std::numeric_limits<T>::signaling_NaN()));
-
-    return true;
+  static void test() {
+    COMPILE_OR_RUNTIME_ASSERT(std::isfinite(std::numeric_limits<T>::max()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isfinite(std::numeric_limits<T>::infinity()));
+    COMPILE_OR_RUNTIME_ASSERT(std::isfinite(std::numeric_limits<T>::min()));
+    COMPILE_OR_RUNTIME_ASSERT(std::isfinite(std::numeric_limits<T>::denorm_min()));
+    COMPILE_OR_RUNTIME_ASSERT(std::isfinite(std::numeric_limits<T>::lowest()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isfinite(-std::numeric_limits<T>::infinity()));
+    COMPILE_OR_RUNTIME_ASSERT(std::isfinite(T(0)));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isfinite(std::numeric_limits<T>::quiet_NaN()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isfinite(std::numeric_limits<T>::signaling_NaN()));
   }
 
   template <class T>
-  TEST_CONSTEXPR_CXX23 void operator()() {
+  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::isfinite(std::numeric_limits<T>::max()));
-    assert(std::isfinite(std::numeric_limits<T>::lowest()));
-    assert(std::isfinite(T(0)));
-
-    return true;
+  static void test() {
+    COMPILE_OR_RUNTIME_ASSERT(std::isfinite(std::numeric_limits<T>::max()));
+    COMPILE_OR_RUNTIME_ASSERT(std::isfinite(std::numeric_limits<T>::lowest()));
+    COMPILE_OR_RUNTIME_ASSERT(std::isfinite(T(0)));
   }
 
   template <class T>
-  TEST_CONSTEXPR_CXX23 void operator()() {
+  void operator()() {
     test<T>();
-#if TEST_STD_VER >= 23
-    static_assert(test<T>());
-#endif
   }
 };
 
 template <typename T>
 struct ConvertibleTo {
-  operator T() const { return T(); }
+  TEST_CONSTEXPR_CXX23 operator T() const { return T(); }
 };
 
 int main(int, char**) {
@@ -73,9 +69,9 @@ int main(int, char**) {
 
   // Make sure we can call `std::isfinite` with convertible types
   {
-    assert(std::isfinite(ConvertibleTo<float>()));
-    assert(std::isfinite(ConvertibleTo<double>()));
-    assert(std::isfinite(ConvertibleTo<long double>()));
+    COMPILE_OR_RUNTIME_ASSERT(std::isfinite(ConvertibleTo<float>()));
+    COMPILE_OR_RUNTIME_ASSERT(std::isfinite(ConvertibleTo<double>()));
+    COMPILE_OR_RUNTIME_ASSERT(std::isfinite(ConvertibleTo<long double>()));
   }
 
   return 0;
diff --git a/libcxx/test/std/numerics/c.math/isinf.pass.cpp b/libcxx/test/std/numerics/c.math/isinf.pass.cpp
index e5169e8056c2ea..b77162f1b254de 100644
--- a/libcxx/test/std/numerics/c.math/isinf.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isinf.pass.cpp
@@ -18,53 +18,49 @@
 #include "test_macros.h"
 #include "type_algorithms.h"
 
+#if TEST_STD_VER >= 23
+#  define COMPILE_OR_RUNTIME_ASSERT(expr) static_assert(expr)
+#else
+#  define COMPILE_OR_RUNTIME_ASSERT(expr) assert(expr)
+#endif
+
 struct TestFloat {
   template <class T>
-  static TEST_CONSTEXPR_CXX23 bool test() {
-    assert(!std::isinf(std::numeric_limits<T>::max()));
-    assert(std::isinf(std::numeric_limits<T>::infinity()));
-    assert(!std::isinf(std::numeric_limits<T>::min()));
-    assert(!std::isinf(std::numeric_limits<T>::denorm_min()));
-    assert(!std::isinf(std::numeric_limits<T>::lowest()));
-    assert(std::isinf(-std::numeric_limits<T>::infinity()));
-    assert(!std::isinf(T(0)));
-    assert(!std::isinf(std::numeric_limits<T>::quiet_NaN()));
-    assert(!std::isinf(std::numeric_limits<T>::signaling_NaN()));
-
-    return true;
+  static void test() {
+    COMPILE_OR_RUNTIME_ASSERT(!std::isinf(std::numeric_limits<T>::max()));
+    COMPILE_OR_RUNTIME_ASSERT(std::isinf(std::numeric_limits<T>::infinity()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isinf(std::numeric_limits<T>::min()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isinf(std::numeric_limits<T>::denorm_min()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isinf(std::numeric_limits<T>::lowest()));
+    COMPILE_OR_RUNTIME_ASSERT(std::isinf(-std::numeric_limits<T>::infinity()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isinf(T(0)));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isinf(std::numeric_limits<T>::quiet_NaN()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isinf(std::numeric_limits<T>::signaling_NaN()));
   }
 
   template <class T>
-  TEST_CONSTEXPR_CXX23 void operator()() {
+  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::isinf(std::numeric_limits<T>::max()));
-    assert(!std::isinf(std::numeric_limits<T>::lowest()));
-    assert(!std::isinf(T(0)));
-
-    return true;
+  static void test() {
+    COMPILE_OR_RUNTIME_ASSERT(!std::isinf(std::numeric_limits<T>::max()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isinf(std::numeric_limits<T>::lowest()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isinf(T(0)));
   }
 
   template <class T>
-  TEST_CONSTEXPR_CXX23 void operator()() {
+  void operator()() {
     test<T>();
-#if TEST_STD_VER >= 23
-    static_assert(test<T>());
-#endif
   }
 };
 
 template <typename T>
 struct ConvertibleTo {
-  operator T() const { return T(); }
+  TEST_CONSTEXPR_CXX23 operator T() const { return T(); }
 };
 
 int main(int, char**) {
@@ -73,9 +69,9 @@ int main(int, char**) {
 
   // Make sure we can call `std::isinf` with convertible types
   {
-    assert(!std::isinf(ConvertibleTo<float>()));
-    assert(!std::isinf(ConvertibleTo<double>()));
-    assert(!std::isinf(ConvertibleTo<long double>()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isinf(ConvertibleTo<float>()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isinf(ConvertibleTo<double>()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isinf(ConvertibleTo<long double>()));
   }
 
   return 0;
diff --git a/libcxx/test/std/numerics/c.math/isnan.pass.cpp b/libcxx/test/std/numerics/c.math/isnan.pass.cpp
index e4ccab1243e567..1eb8a2d3c50797 100644
--- a/libcxx/test/std/numerics/c.math/isnan.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isnan.pass.cpp
@@ -18,53 +18,49 @@
 #include "test_macros.h"
 #include "type_algorithms.h"
 
+#if TEST_STD_VER >= 23
+#  define COMPILE_OR_RUNTIME_ASSERT(expr) static_assert(expr)
+#else
+#  define COMPILE_OR_RUNTIME_ASSERT(expr) assert(expr)
+#endif
+
 struct TestFloat {
   template <class T>
-  static TEST_CONSTEXPR_CXX23 bool test() {
-    assert(!std::isnan(std::numeric_limits<T>::max()));
-    assert(!std::isnan(std::numeric_limits<T>::infinity()));
-    assert(!std::isnan(std::numeric_limits<T>::min()));
-    assert(!std::isnan(std::numeric_limits<T>::denorm_min()));
-    assert(!std::isnan(std::numeric_limits<T>::lowest()));
-    assert(!std::isnan(-std::numeric_limits<T>::infinity()));
-    assert(!std::isnan(T(0)));
-    assert(std::isnan(std::numeric_limits<T>::quiet_NaN()));
-    assert(std::isnan(std::numeric_limits<T>::signaling_NaN()));
-
-    return true;
+  static void test() {
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnan(std::numeric_limits<T>::max()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnan(std::numeric_limits<T>::infinity()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnan(std::numeric_limits<T>::min()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnan(std::numeric_limits<T>::denorm_min()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnan(std::numeric_limits<T>::lowest()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnan(-std::numeric_limits<T>::infinity()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnan(T(0)));
+    COMPILE_OR_RUNTIME_ASSERT(std::isnan(std::numeric_limits<T>::quiet_NaN()));
+    COMPILE_OR_RUNTIME_ASSERT(std::isnan(std::numeric_limits<T>::signaling_NaN()));
   }
 
   template <class T>
-  TEST_CONSTEXPR_CXX23 void operator()() {
+  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::isnan(std::numeric_limits<T>::max()));
-    assert(!std::isnan(std::numeric_limits<T>::lowest()));
-    assert(!std::isnan(T(0)));
-
-    return true;
+  static void test() {
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnan(std::numeric_limits<T>::max()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnan(std::numeric_limits<T>::lowest()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnan(T(0)));
   }
 
   template <class T>
-  TEST_CONSTEXPR_CXX23 void operator()() {
+  void operator()() {
     test<T>();
-#if TEST_STD_VER >= 23
-    static_assert(test<T>());
-#endif
   }
 };
 
 template <typename T>
 struct ConvertibleTo {
-  operator T() const { return T(); }
+  TEST_CONSTEXPR_CXX23 operator T() const { return T(); }
 };
 
 int main(int, char**) {
@@ -73,9 +69,9 @@ int main(int, char**) {
 
   // Make sure we can call `std::isnan` with convertible types
   {
-    assert(!std::isnan(ConvertibleTo<float>()));
-    assert(!std::isnan(ConvertibleTo<double>()));
-    assert(!std::isnan(ConvertibleTo<long double>()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnan(ConvertibleTo<float>()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnan(ConvertibleTo<double>()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnan(ConvertibleTo<long double>()));
   }
 
   return 0;
diff --git a/libcxx/test/std/numerics/c.math/isnormal.pass.cpp b/libcxx/test/std/numerics/c.math/isnormal.pass.cpp
index c3b8f31359f988..884e0fd6e09f7b 100644
--- a/libcxx/test/std/numerics/c.math/isnormal.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isnormal.pass.cpp
@@ -18,47 +18,43 @@
 #include "test_macros.h"
 #include "type_algorithms.h"
 
+#if TEST_STD_VER >= 23
+#  define COMPILE_OR_RUNTIME_ASSERT(expr) static_assert(expr)
+#else
+#  define COMPILE_OR_RUNTIME_ASSERT(expr) assert(expr)
+#endif
+
 struct TestFloat {
   template <class T>
-  static TEST_CONSTEXPR_CXX23 bool test() {
-    assert(std::isnormal(std::numeric_limits<T>::max()));
-    assert(!std::isnormal(std::numeric_limits<T>::infinity()));
-    assert(std::isnormal(std::numeric_limits<T>::min()));
-    assert(!std::isnormal(std::numeric_limits<T>::denorm_min()));
-    assert(std::isnormal(std::numeric_limits<T>::lowest()));
-    assert(!std::isnormal(-std::numeric_limits<T>::infinity()));
-    assert(!std::isnormal(T(0)));
-    assert(!std::isnormal(std::numeric_limits<T>::quiet_NaN()));
-    assert(!std::isnormal(std::numeric_limits<T>::signaling_NaN()));
-
-    return true;
+  static void test() {
+    COMPILE_OR_RUNTIME_ASSERT(std::isnormal(std::numeric_limits<T>::max()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnormal(std::numeric_limits<T>::infinity()));
+    COMPILE_OR_RUNTIME_ASSERT(std::isnormal(std::numeric_limits<T>::min()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnormal(std::numeric_limits<T>::denorm_min()));
+    COMPILE_OR_RUNTIME_ASSERT(std::isnormal(std::numeric_limits<T>::lowest()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnormal(-std::numeric_limits<T>::infinity()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnormal(T(0)));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnormal(std::numeric_limits<T>::quiet_NaN()));
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnormal(std::numeric_limits<T>::signaling_NaN()));
   }
 
   template <class T>
-  TEST_CONSTEXPR_CXX23 void operator()() {
+  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::isnormal(std::numeric_limits<T>::max()));
-    assert(std::isnormal(std::numeric_limits<T>::lowest()) == std::is_signed<T>::value);
-    assert(!std::isnormal(T(0)));
-
-    return true;
+  static void test() {
+    COMPILE_OR_RUNTIME_ASSERT(std::isnormal(std::numeric_limits<T>::max()));
+    COMPILE_OR_RUNTIME_ASSERT(std::isnormal(std::numeric_limits<T>::lowest()) == std::is_signed<T>::value);
+    COMPILE_OR_RUNTIME_ASSERT(!std::isnormal(T(0)));
   }
 
   template <class T>
-  TEST_CONSTEXPR_CXX23 void operator()() {
+  void operator()() {
     test<T>();
-#if TEST_STD_VER >= 23
-    static_assert(test<T>());
-#endif
   }
 };
 



More information about the libcxx-commits mailing list