[libcxx-commits] [libcxx] [libc++][math] Fix testing `constexpr` at compile time (PR #105984)
via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Aug 27 02:03:28 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Robin Caloudis (robincaloudis)
<details>
<summary>Changes</summary>
## Why
Tests make use of `assert()`, which gets evaluated at runtime. As a result, the cmath functions that are `constexpr` functions since C++23 do not get tested at compile time. Note that the tests make use of `static_assert`, but test only the constexpr function `test()` whose return value is computable at compile time and not the actual cmath functions.
## What
Add condition that provides either a runtime (for std <= c++20) or compile time (for std >= c++23) assert.
---
Full diff: https://github.com/llvm/llvm-project/pull/105984.diff
4 Files Affected:
- (modified) libcxx/test/std/numerics/c.math/isfinite.pass.cpp (+26-30)
- (modified) libcxx/test/std/numerics/c.math/isinf.pass.cpp (+26-30)
- (modified) libcxx/test/std/numerics/c.math/isnan.pass.cpp (+26-30)
- (modified) libcxx/test/std/numerics/c.math/isnormal.pass.cpp (+22-26)
``````````diff
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
}
};
``````````
</details>
https://github.com/llvm/llvm-project/pull/105984
More information about the libcxx-commits
mailing list