[libcxx-commits] [libcxx] [libc++][cmath] Add `constexpr` tests for P183R2 (PR #227200)
Hristo Hristov via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Sep 29 00:10:45 PDT 2026
https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/227200
>From e6d39a34ba9292c35d2fc8c0f74fab5f3f4f7830 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 29 Sep 2026 09:41:56 +0300
Subject: [PATCH] [libc++][cmath] Add `constexpr` tests for P183R2
This adds `constexpr` tests for https://wg21.link/P1383R2 similar to the tests for https://wg21.link/P0533R9.
`<complex>` depends on `<cmath>` so corresponding tests are not implemented.
---
.../c.math/constexpr-cxx26-clang.pass.cpp | 282 ++++++++++++++++++
.../c.math/constexpr-cxx26-gcc.pass.cpp | 67 +++++
2 files changed, 349 insertions(+)
create mode 100644 libcxx/test/libcxx/numerics/c.math/constexpr-cxx26-clang.pass.cpp
create mode 100644 libcxx/test/libcxx/numerics/c.math/constexpr-cxx26-gcc.pass.cpp
diff --git a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx26-clang.pass.cpp b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx26-clang.pass.cpp
new file mode 100644
index 0000000000000..b3b08b7aae0c9
--- /dev/null
+++ b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx26-clang.pass.cpp
@@ -0,0 +1,282 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+// REQUIRES: clang
+
+// We don't control the implementation of these functions on windows
+// UNSUPPORTED: windows
+
+// Missing some math functions.
+// XFAIL: LLVM-LIBC-FIXME
+
+// Check that Clang supports constexpr <cmath> and <cstdlib> functions
+// mentioned in the P1383R2 paper that is part of C++26
+// (https://wg21.link/P1383R2)
+//
+// Every function called in this test should become constexpr. Whenever some
+// of the desired function become constexpr, the programmer switches
+// `ASSERT_NOT_CONSTEXPR_CXX26` to `ASSERT_CONSTEXPR_CXX26` and eventually the
+// paper is implemented in Clang.
+// The test also works as a reference list of unimplemented functions.
+
+#include <cassert>
+#include <cmath>
+#include <cstdlib>
+
+int main(int, char**) {
+ bool ImplementedP1383R2 = true;
+
+#define ASSERT_CONSTEXPR_CXX26(Expr) static_assert(__builtin_constant_p(Expr) && (Expr))
+#define ASSERT_NOT_CONSTEXPR_CXX26(Expr) \
+ static_assert(!__builtin_constant_p(Expr)); \
+ assert(Expr); \
+ ImplementedP1383R2 = false
+
+ // acos()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::acos(1.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::acos(1.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::acos(1.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::acosf(1.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::acosl(1.0L) == 0.0L);
+
+ // asin()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::asin(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::asin(0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::asin(0.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::asinf(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::asinl(0.0L) == 0.0L);
+
+ // atan()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atan(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atan(0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atan(0.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atanf(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atanl(0.0L) == 0.0L);
+
+ // atan2()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atan2(0.f, 1.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atan2(0.0, 1.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atan2(0.0L, 1.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atan2f(0.f, 1.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atan2l(0.0L, 1.0L) == 0.0L);
+
+ // cos()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::cos(0.f) == 1.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::cos(0.0) == 1.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::cos(0.0L) == 1.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::cosf(0.f) == 1.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::cosl(0.0L) == 1.0L);
+
+ // sin()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::sin(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::sin(0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::sin(0.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::sinf(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::sinl(0.0L) == 0.0L);
+
+ // tan()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::tan(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::tan(0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::tan(0.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::tanf(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::tanl(0.0L) == 0.0L);
+
+ // acosh()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::acosh(1.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::acosh(1.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::acosh(1.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::acoshf(1.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::acoshl(1.0L) == 0.0L);
+
+ // asinh()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::asinh(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::asinh(0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::asinh(0.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::asinhf(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::asinhl(0.0L) == 0.0L);
+
+ // atanh()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atanh(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atanh(0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atanh(0.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atanhf(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atanhl(0.0L) == 0.0L);
+
+ // cosh()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::cosh(0.f) == 1.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::cosh(0.0) == 1.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::cosh(0.0L) == 1.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::coshf(0.f) == 1.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::coshl(0.0L) == 1.0L);
+
+ // sinh()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::sinh(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::sinh(0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::sinh(0.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::sinhf(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::sinhl(0.0L) == 0.0L);
+
+ // tanh()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::tanh(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::tanh(0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::tanh(0.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::tanhf(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::tanhl(0.0L) == 0.0L);
+
+ // exp()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::exp(0.f) == 1.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::exp(0.0) == 1.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::exp(0.0L) == 1.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::expf(0.f) == 1.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::expl(0.0L) == 1.0L);
+
+ // exp2()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::exp2(0.f) == 1.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::exp2(0.0) == 1.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::exp2(0.0L) == 1.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::exp2f(0.f) == 1.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::exp2l(0.0L) == 1.0L);
+
+ // expm1()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::expm1(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::expm1(0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::expm1(0.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::expm1f(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::expm1l(0.0L) == 0.0L);
+
+ // log()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log(1.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log(1.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log(1.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::logf(1.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::logl(1.0L) == 0.0L);
+
+ // log10()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log10(1.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log10(1.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log10(1.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log10f(1.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log10l(1.0L) == 0.0L);
+
+ // log1p()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log1p(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log1p(0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log1p(0.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log1pf(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log1pl(0.0L) == 0.0L);
+
+ // log2()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log2(1.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log2(1.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log2(1.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log2f(1.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::log2l(1.0L) == 0.0L);
+
+ // cbrt()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::cbrt(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::cbrt(0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::cbrt(0.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::cbrtf(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::cbrtl(0.0L) == 0.0L);
+
+ // [c.math.abs], absolute values
+
+ // hypot()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::hypot(0.f, 0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::hypot(0.0, 0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::hypot(0.0L, 0.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::hypotf(0.f, 0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::hypotl(0.0L, 0.0L) == 0.0L);
+
+ // [c.math.hypot3], three-dimensional hypotenuse
+
+ // hypot() - three arguments
+ ASSERT_NOT_CONSTEXPR_CXX26(std::hypot(0.f, 0.f, 0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::hypot(0.0, 0.0, 0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::hypot(0.0L, 0.0L, 0.0L) == 0.0L);
+
+ // pow()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::pow(0.f, 0.f) == 1.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::pow(0.0, 0.0) == 1.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::pow(0.0L, 0.0L) == 1.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::powf(0.f, 0.f) == 1.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::powl(0.0L, 0.0L) == 1.0L);
+
+ // sqrt()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::sqrt(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::sqrt(0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::sqrt(0.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::sqrtf(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::sqrtl(0.0L) == 0.0L);
+
+ // erf()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::erf(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::erf(0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::erf(0.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::erff(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::erfl(0.0L) == 0.0L);
+
+ // erfc()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::erfc(0.f) == 1.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::erfc(0.0) == 1.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::erfc(0.0L) == 1.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::erfcf(0.f) == 1.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::erfcl(0.0L) == 1.0L);
+
+ // lgamma()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::lgamma(1.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::lgamma(1.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::lgamma(1.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::lgammaf(1.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::lgammal(1.0L) == 0.0L);
+
+ // tgamma()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::tgamma(1.f) == 1.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::tgamma(1.0) == 1.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::tgamma(1.0L) == 1.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::tgammaf(1.f) == 1.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::tgammal(1.0L) == 1.0L);
+
+ assert(!ImplementedP1383R2 && R"(
+Congratulations! You just have implemented P1383R2 (https://wg21.link/P1383R2).
+Please go to `clang/www/cxx_status.html` and change the paper's implementation
+status. Also please delete this assert and refactor `ASSERT_CONSTEXPR_CXX26`
+and `ASSERT_NOT_CONSTEXPR_CXX26`.
+)");
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx26-gcc.pass.cpp b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx26-gcc.pass.cpp
new file mode 100644
index 0000000000000..a359da3241e90
--- /dev/null
+++ b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx26-gcc.pass.cpp
@@ -0,0 +1,67 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+// REQUIRES: gcc
+
+// Check that GCC supports constexpr <cmath> and <cstdlib> functions
+// mentioned in the P1383R2 paper that is part of C++26
+// (https://wg21.link/P1383R2)
+//
+// Every function called in this test should become constexpr. Whenever some
+// of the desired function become constexpr, the programmer switches
+// `ASSERT_NOT_CONSTEXPR_CXX26` to `ASSERT_CONSTEXPR_CXX26` and eventually the
+// paper is implemented in Clang.
+// The test also works as a reference list of unimplemented functions.
+
+#include <cassert>
+#include <cmath>
+#include <cstdlib>
+
+int main(int, char**) {
+ bool ImplementedP1383R2 = true;
+
+#define ASSERT_CONSTEXPR_CXX26(Expr) static_assert(__builtin_constant_p(Expr) && (Expr))
+#define ASSERT_NOT_CONSTEXPR_CXX26(Expr) \
+ static_assert(!__builtin_constant_p(Expr)); \
+ assert(Expr); \
+ ImplementedP1383R2 = false
+
+ // acos
+ ASSERT_NOT_CONSTEXPR_CXX26(std::acos(1.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::acos(1.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::acos(1.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::acosf(1.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::acosl(1.0L) == 0.0L);
+
+ // asin()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::asin(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::asin(0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::asin(0.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::asinf(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::asinl(0.0L) == 0.0L);
+
+ // atan()
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atan(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atan(0.0) == 0.0);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atan(0.0L) == 0.0L);
+
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atanf(0.f) == 0.f);
+ ASSERT_NOT_CONSTEXPR_CXX26(std::atanl(0.0L) == 0.0L);
+
+ assert(!ImplementedP1383R2 && R"(
+Congratulations! You just have implemented P1383R2 (https://wg21.link/P1383R2).
+Please go to `clang/www/cxx_status.html` and change the paper's implementation
+status. Also please delete this assert and refactor `ASSERT_CONSTEXPR_CXX26`
+and `ASSERT_NOT_CONSTEXPR_CXX26`.
+)");
+
+ return 0;
+}
More information about the libcxx-commits
mailing list