[libc-commits] [libc] [libc][math] Add gcc-7 to 9 compatibility for shared math. (PR #197868)
via libc-commits
libc-commits at lists.llvm.org
Thu May 21 06:54:57 PDT 2026
https://github.com/lntue updated https://github.com/llvm/llvm-project/pull/197868
>From 43e3a82521d8c1fd4b2788d7a17d6a1f68d85161 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Thu, 21 May 2026 04:51:41 +0000
Subject: [PATCH 1/7] [libc] Support building shared tests with gcc-7, 8, 9.
- Add more fine-grained constexpr annotations.
---
libc/src/__support/macros/attributes.h | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/libc/src/__support/macros/attributes.h b/libc/src/__support/macros/attributes.h
index b3e1e12889511..cffcabcd29bd3 100644
--- a/libc/src/__support/macros/attributes.h
+++ b/libc/src/__support/macros/attributes.h
@@ -48,19 +48,41 @@
#endif // has_builtin(__builtin_bit_cast)
#endif // LIBC_HAS_BUILTIN_BIT_CAST
+#if LIBC_HAS_BUILTIN_BIT_CAST
+#define LIBC_BIT_CAST_CONSTEXPR constexpr
+#define LIBC_BIT_CAST_CONSTEXPR_VAR constexpr
+#else
+#define LIBC_BIT_CAST_CONSTEXPR
+#define LIBC_BIT_CAST_CONSTEXPR_VAR const
+#endif // LIBC_HAS_BUILTIN_BIT_CAST
+
#ifndef LIBC_HAS_CONSTANT_EVALUATION
#define LIBC_HAS_CONSTANT_EVALUATION \
(LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED && LIBC_HAS_BUILTIN_BIT_CAST)
#endif // LIBC_HAS_CONSTANT_EVALUATION
+#if LIBC_HAS_CONSTANT_EVALUATION
+#define LIBC_CONSTEXPR_DEFAULT constexpr
+#define LIBC_CONSTEXPR_VAR_DEFAULT constexpr
+#else
+#define LIBC_CONSTEXPR_DEFAULT
+#define LIBC_CONSTEXPR_VAR_DEFAULT const
+#endif // LIBC_HAS_CONSTANT_EVALUATION
+
// TODO: Remove the macro once Clang/LLVM bump their minimum compilers' version.
// The reason for indirection is GCC is known to fail with constexpr qualified
// functions that doesn't produce constant expression.
+// Also, there are some circular dependency in the generic functions without
+// __builtin_func for the following functions:
+// fputil::fma
+// fputil::sqrt
#if LIBC_ENABLE_CONSTEXPR && LIBC_HAS_CONSTANT_EVALUATION
#define LIBC_USE_CONSTEXPR
#define LIBC_CONSTEXPR constexpr
+#define LIBC_CONSTEXPR_VAR constexpr
#else
#define LIBC_CONSTEXPR
+#define LIBC_CONSTEXPR_VAR const
#endif // LIBC_USE_CONSTEXPR
#ifndef LIBC_HAS_BUILTIN_IS_ASSIGNABLE
>From b3002ac664ac9c8ceaf38eadb496fce8d4fbd3dc Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Thu, 21 May 2026 04:54:06 +0000
Subject: [PATCH 2/7] Update LIBC_LOOP_(NO)UNROLL annotation compatibility.
---
libc/src/__support/macros/optimization.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/libc/src/__support/macros/optimization.h b/libc/src/__support/macros/optimization.h
index dbefd20a5cd16..a1e5766393190 100644
--- a/libc/src/__support/macros/optimization.h
+++ b/libc/src/__support/macros/optimization.h
@@ -32,8 +32,13 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
#define LIBC_LOOP_NOUNROLL _Pragma("nounroll")
#define LIBC_LOOP_UNROLL _Pragma("unroll")
#elif defined(LIBC_COMPILER_IS_GCC)
+#if LIBC_COMPILER_GCC_VER >= 800
#define LIBC_LOOP_NOUNROLL _Pragma("GCC unroll 0")
#define LIBC_LOOP_UNROLL _Pragma("GCC unroll 2048")
+#else
+#define LIBC_LOOP_NOUNROLL
+#define LIBC_LOOP_UNROLL
+#endif
#elif defined(LIBC_COMPILER_IS_MSVC)
#define LIBC_LOOP_NOUNROLL
#define LIBC_LOOP_UNROLL
>From 52df4aabbb0d21755372dfc52ffbb1faee47b8a9 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Thu, 21 May 2026 04:56:10 +0000
Subject: [PATCH 3/7] Apply fine-grained constexpr annotations to
src/__support/FPUtil folder.
---
libc/src/__support/FPUtil/FEnvImpl.h | 8 +--
libc/src/__support/FPUtil/FPBits.h | 25 ++++----
libc/src/__support/FPUtil/NormalFloat.h | 5 +-
libc/src/__support/FPUtil/bfloat16.h | 2 +-
libc/src/__support/FPUtil/dyadic_float.h | 14 ++---
.../src/__support/FPUtil/except_value_utils.h | 61 +++++++++++++------
libc/src/__support/FPUtil/generic/FMA.h | 2 +-
libc/src/__support/FPUtil/generic/sqrt.h | 14 +++--
.../FPUtil/generic/sqrt_80_bit_long_double.h | 10 +--
libc/src/__support/FPUtil/rounding_mode.h | 10 +--
.../FPUtil/x86_64/NextAfterLongDouble.h | 3 +-
.../FPUtil/x86_64/NextUpDownLongDouble.h | 2 +-
12 files changed, 91 insertions(+), 65 deletions(-)
diff --git a/libc/src/__support/FPUtil/FEnvImpl.h b/libc/src/__support/FPUtil/FEnvImpl.h
index a21f511bd72b8..89188d20297e6 100644
--- a/libc/src/__support/FPUtil/FEnvImpl.h
+++ b/libc/src/__support/FPUtil/FEnvImpl.h
@@ -123,7 +123,7 @@ LIBC_INLINE int set_env(const fenv_t *) { return 0; }
namespace LIBC_NAMESPACE_DECL {
namespace fputil {
-LIBC_INLINE static constexpr int
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT int
clear_except_if_required([[maybe_unused]] int excepts) {
if (cpp::is_constant_evaluated()) {
return 0;
@@ -136,7 +136,7 @@ clear_except_if_required([[maybe_unused]] int excepts) {
}
}
-LIBC_INLINE static constexpr int
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT int
set_except_if_required([[maybe_unused]] int excepts) {
if (cpp::is_constant_evaluated()) {
return 0;
@@ -149,7 +149,7 @@ set_except_if_required([[maybe_unused]] int excepts) {
}
}
-LIBC_INLINE static constexpr int
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT int
raise_except_if_required([[maybe_unused]] int excepts) {
if (cpp::is_constant_evaluated()) {
return 0;
@@ -162,7 +162,7 @@ raise_except_if_required([[maybe_unused]] int excepts) {
}
}
-LIBC_INLINE static constexpr void
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT void
set_errno_if_required([[maybe_unused]] int err) {
if (!cpp::is_constant_evaluated()) {
#ifndef LIBC_MATH_HAS_NO_ERRNO
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 7028fd4f38950..c52699e17e225 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -835,21 +835,22 @@ struct FPBits final : public internal::FPRepImpl<get_fp_type<T>(), FPBits<T>> {
// Constructors.
LIBC_INLINE constexpr FPBits() = default;
- template <typename XType> LIBC_INLINE constexpr explicit FPBits(XType x) {
- using Unqual = typename cpp::remove_cv_t<XType>;
- if constexpr (cpp::is_same_v<Unqual, T>) {
- UP::bits = cpp::bit_cast<StorageType>(x);
- } else if constexpr (cpp::is_same_v<Unqual, StorageType>) {
- UP::bits = x;
- } else {
- // We don't want accidental type promotions/conversions, so we require
- // exact type match.
- static_assert(cpp::always_false<XType>);
- }
+ template <
+ typename XType,
+ cpp::enable_if_t<cpp::is_same_v<cpp::remove_cv_t<XType>, T>, int> = 0>
+ LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR explicit FPBits(XType x) {
+ UP::bits = cpp::bit_cast<StorageType>(x);
}
+ template <typename XType,
+ cpp::enable_if_t<
+ cpp::is_same_v<cpp::remove_cv_t<XType>, StorageType>, int> = 0>
+ LIBC_INLINE constexpr explicit FPBits(XType x) : UP(x) {}
+
// Floating-point conversions.
- LIBC_INLINE constexpr T get_val() const { return cpp::bit_cast<T>(UP::bits); }
+ LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR T get_val() const {
+ return cpp::bit_cast<T>(UP::bits);
+ }
};
} // namespace fputil
diff --git a/libc/src/__support/FPUtil/NormalFloat.h b/libc/src/__support/FPUtil/NormalFloat.h
index 5123a3e217f72..2da317a356405 100644
--- a/libc/src/__support/FPUtil/NormalFloat.h
+++ b/libc/src/__support/FPUtil/NormalFloat.h
@@ -95,7 +95,7 @@ template <typename T> struct NormalFloat {
return result;
}
- LIBC_INLINE constexpr operator T() const {
+ LIBC_INLINE operator T() const {
int biased_exponent = exponent + FPBits<T>::EXP_BIAS;
// Max exponent is of the form 0xFF...E. That is why -2 and not -1.
constexpr int MAX_EXPONENT_VALUE = (1 << FPBits<T>::EXP_LEN) - 2;
@@ -216,8 +216,7 @@ NormalFloat<long double>::init_from_bits(FPBits<long double> bits) {
}
}
-template <>
-LIBC_INLINE constexpr NormalFloat<long double>::operator long double() const {
+template <> LIBC_INLINE NormalFloat<long double>::operator long double() const {
using LDBits = FPBits<long double>;
int biased_exponent = exponent + LDBits::EXP_BIAS;
// Max exponent is of the form 0xFF...E. That is why -2 and not -1.
diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
index 5c8f3b7e6c77a..638500d94cef2 100644
--- a/libc/src/__support/FPUtil/bfloat16.h
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -92,7 +92,7 @@ struct BFloat16 {
return fputil::greater_than_or_equals(*this, other);
}
- LIBC_INLINE constexpr BFloat16 operator-() const {
+ LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR BFloat16 operator-() const {
fputil::FPBits<bfloat16> result(*this);
result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
return result.get_val();
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 8ce041247716b..7e4ea2f1a81be 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -39,7 +39,7 @@ namespace fputil {
// Return value is +1 if the value should be rounded up; -1 if it should be
// rounded down; 0 if it's exact and needs no rounding.
template <size_t Bits>
-LIBC_INLINE constexpr int
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT int
rounding_direction(const LIBC_NAMESPACE::UInt<Bits> &value, size_t rshift,
Sign logical_sign) {
if (rshift == 0 || (rshift < Bits && (value << (Bits - rshift)) == 0) ||
@@ -95,7 +95,7 @@ template <size_t Bits> struct DyadicFloat {
LIBC_INLINE constexpr DyadicFloat() = default;
template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
- LIBC_INLINE constexpr DyadicFloat(T x) {
+ LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR DyadicFloat(T x) {
static_assert(FPBits<T>::FRACTION_LEN < Bits);
FPBits<T> x_bits(x);
sign = x_bits.sign();
@@ -152,7 +152,7 @@ template <size_t Bits> struct DyadicFloat {
// Produce a correctly rounded DyadicFloat from a too-large mantissa,
// by shifting it down and rounding if necessary.
template <size_t MantissaBits>
- LIBC_INLINE constexpr static DyadicFloat<Bits>
+ LIBC_INLINE LIBC_CONSTEXPR_DEFAULT static DyadicFloat<Bits>
round(Sign result_sign, int result_exponent,
const LIBC_NAMESPACE::UInt<MantissaBits> &input_mantissa,
size_t rshift) {
@@ -171,7 +171,7 @@ template <size_t Bits> struct DyadicFloat {
}
template <typename T, bool ShouldSignalExceptions>
- LIBC_INLINE constexpr cpp::enable_if_t<
+ LIBC_INLINE LIBC_CONSTEXPR_DEFAULT cpp::enable_if_t<
cpp::is_floating_point_v<T> && (FPBits<T>::FRACTION_LEN < Bits), T>
generic_as() const {
using FPBits = FPBits<T>;
@@ -284,7 +284,7 @@ template <size_t Bits> struct DyadicFloat {
typename = cpp::enable_if_t<cpp::is_floating_point_v<T> &&
(FPBits<T>::FRACTION_LEN < Bits),
void>>
- LIBC_INLINE constexpr T fast_as() const {
+ LIBC_INLINE LIBC_CONSTEXPR_DEFAULT T fast_as() const {
if (LIBC_UNLIKELY(mantissa.is_zero()))
return FPBits<T>::zero(sign).get_val();
@@ -411,7 +411,7 @@ template <size_t Bits> struct DyadicFloat {
typename = cpp::enable_if_t<cpp::is_floating_point_v<T> &&
(FPBits<T>::FRACTION_LEN < Bits),
void>>
- LIBC_INLINE constexpr T as() const {
+ LIBC_INLINE LIBC_CONSTEXPR_DEFAULT T as() const {
if constexpr (cpp::is_same_v<T, bfloat16>
#if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION)
|| cpp::is_same_v<T, float16>
@@ -453,7 +453,7 @@ template <size_t Bits> struct DyadicFloat {
return new_mant;
}
- LIBC_INLINE constexpr MantissaType
+ LIBC_INLINE LIBC_CONSTEXPR_DEFAULT MantissaType
as_mantissa_type_rounded(int *round_dir_out = nullptr) const {
int round_dir = 0;
MantissaType new_mant;
diff --git a/libc/src/__support/FPUtil/except_value_utils.h b/libc/src/__support/FPUtil/except_value_utils.h
index 5f767769974d2..37ecc52784c16 100644
--- a/libc/src/__support/FPUtil/except_value_utils.h
+++ b/libc/src/__support/FPUtil/except_value_utils.h
@@ -53,7 +53,8 @@ template <typename T, size_t N> struct ExceptValues {
Mapping values[N];
- LIBC_INLINE constexpr cpp::optional<T> lookup(StorageType x_bits) const {
+ LIBC_INLINE LIBC_CONSTEXPR_DEFAULT cpp::optional<T>
+ lookup(StorageType x_bits) const {
for (size_t i = 0; i < N; ++i) {
if (LIBC_UNLIKELY(x_bits == values[i].input)) {
StorageType out_bits = values[i].rnd_towardzero_result;
@@ -74,8 +75,8 @@ template <typename T, size_t N> struct ExceptValues {
return cpp::nullopt;
}
- LIBC_INLINE constexpr cpp::optional<T> lookup_odd(StorageType x_abs,
- bool sign) const {
+ LIBC_INLINE LIBC_CONSTEXPR_DEFAULT cpp::optional<T>
+ lookup_odd(StorageType x_abs, bool sign) const {
for (size_t i = 0; i < N; ++i) {
if (LIBC_UNLIKELY(x_abs == values[i].input)) {
StorageType out_bits = values[i].rnd_towardzero_result;
@@ -111,30 +112,52 @@ template <typename T, size_t N> struct ExceptValues {
};
// Helper functions to set results for exceptional cases.
-template <typename T> LIBC_INLINE T round_result_slightly_down(T value_rn) {
- volatile T tmp = value_rn;
- tmp -= FPBits<T>::min_normal().get_val();
- return tmp;
+template <typename T>
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT T round_result_slightly_down(T value_rn) {
+ if (cpp::is_constant_evaluated()) {
+ return value_rn;
+ } else {
+ volatile T tmp = value_rn;
+ tmp -= FPBits<T>::min_normal().get_val();
+ return tmp;
+ }
}
-template <typename T> LIBC_INLINE T round_result_slightly_up(T value_rn) {
- volatile T tmp = value_rn;
- tmp += FPBits<T>::min_normal().get_val();
- return tmp;
+template <typename T>
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT T round_result_slightly_up(T value_rn) {
+ if (cpp::is_constant_evaluated()) {
+ return value_rn;
+ } else {
+ volatile T tmp = value_rn;
+ tmp += FPBits<T>::min_normal().get_val();
+ return tmp;
+ }
}
#if defined(LIBC_TYPES_HAS_FLOAT16) && \
!defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS)
-template <> LIBC_INLINE float16 round_result_slightly_down(float16 value_rn) {
- volatile float tmp = value_rn;
- tmp -= FPBits<float16>::min_normal().get_val();
- return cast<float16>(tmp);
+template <>
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT float16
+round_result_slightly_down(float16 value_rn) {
+ if (cpp::is_constant_evaluated()) {
+ return value_rn;
+ } else {
+ volatile float tmp = value_rn;
+ tmp -= FPBits<float16>::min_normal().get_val();
+ return cast<float16>(tmp);
+ }
}
-template <> LIBC_INLINE float16 round_result_slightly_up(float16 value_rn) {
- volatile float tmp = value_rn;
- tmp += FPBits<float16>::min_normal().get_val();
- return cast<float16>(tmp);
+template <>
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT float16
+round_result_slightly_up(float16 value_rn) {
+ if (cpp::is_constant_evaluated()) {
+ return value_rn;
+ } else {
+ volatile float tmp = value_rn;
+ tmp += FPBits<float16>::min_normal().get_val();
+ return cast<float16>(tmp);
+ }
}
#endif
diff --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h
index 7b46978d0c8af..0de4f98969b72 100644
--- a/libc/src/__support/FPUtil/generic/FMA.h
+++ b/libc/src/__support/FPUtil/generic/FMA.h
@@ -168,7 +168,7 @@ fma(InType x, InType y, InType z) {
constexpr InStorageType IMPLICIT_MASK =
InFPBits::SIG_MASK - InFPBits::FRACTION_MASK;
- constexpr InType DENORMAL_SCALING =
+ LIBC_BIT_CAST_CONSTEXPR_VAR InType DENORMAL_SCALING =
InFPBits::create_value(
Sign::POS, InFPBits::FRACTION_LEN + InFPBits::EXP_BIAS, IMPLICIT_MASK)
.get_val();
diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h
index 4e452a87050b1..69087bd93f083 100644
--- a/libc/src/__support/FPUtil/generic/sqrt.h
+++ b/libc/src/__support/FPUtil/generic/sqrt.h
@@ -41,8 +41,8 @@ template <> struct SpecialLongDouble<long double> {
#endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
template <typename T>
-LIBC_INLINE void normalize(int &exponent,
- typename FPBits<T>::StorageType &mantissa) {
+LIBC_INLINE constexpr void
+normalize(int &exponent, typename FPBits<T>::StorageType &mantissa) {
const int shift =
cpp::countl_zero(mantissa) -
(8 * static_cast<int>(sizeof(mantissa)) - 1 - FPBits<T>::FRACTION_LEN);
@@ -52,12 +52,14 @@ LIBC_INLINE void normalize(int &exponent,
#ifdef LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64
template <>
-LIBC_INLINE void normalize<long double>(int &exponent, uint64_t &mantissa) {
+LIBC_INLINE constexpr void normalize<long double>(int &exponent,
+ uint64_t &mantissa) {
normalize<double>(exponent, mantissa);
}
#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
template <>
-LIBC_INLINE void normalize<long double>(int &exponent, UInt128 &mantissa) {
+LIBC_INLINE constexpr void normalize<long double>(int &exponent,
+ UInt128 &mantissa) {
const uint64_t hi_bits = static_cast<uint64_t>(mantissa >> 64);
const int shift =
hi_bits ? (cpp::countl_zero(hi_bits) - 15)
@@ -72,7 +74,7 @@ LIBC_INLINE void normalize<long double>(int &exponent, UInt128 &mantissa) {
// Correctly rounded IEEE 754 SQRT for all rounding modes.
// Shift-and-add algorithm.
template <typename OutType, typename InType>
-LIBC_INLINE static constexpr cpp::enable_if_t<
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT static cpp::enable_if_t<
cpp::is_floating_point_v<OutType> && cpp::is_floating_point_v<InType> &&
sizeof(OutType) <= sizeof(InType),
OutType>
@@ -92,7 +94,7 @@ sqrt(InType x) {
DyadicFloat<cpp::bit_ceil(static_cast<size_t>(InFPBits::STORAGE_LEN))>;
constexpr InStorageType ONE = InStorageType(1) << InFPBits::FRACTION_LEN;
- constexpr auto FLT_NAN = OutFPBits::quiet_nan().get_val();
+ LIBC_BIT_CAST_CONSTEXPR_VAR auto FLT_NAN = OutFPBits::quiet_nan().get_val();
InFPBits bits(x);
diff --git a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
index 0ba836d17a085..cc692d0fc4c26 100644
--- a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
+++ b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
@@ -21,8 +21,8 @@ namespace LIBC_NAMESPACE_DECL {
namespace fputil {
namespace x86 {
-LIBC_INLINE void normalize(int &exponent,
- FPBits<long double>::StorageType &mantissa) {
+LIBC_INLINE constexpr void
+normalize(int &exponent, FPBits<long double>::StorageType &mantissa) {
const unsigned int shift = static_cast<unsigned int>(
static_cast<size_t>(cpp::countl_zero(static_cast<uint64_t>(mantissa))) -
(8 * sizeof(uint64_t) - 1 - FPBits<long double>::FRACTION_LEN));
@@ -32,16 +32,16 @@ LIBC_INLINE void normalize(int &exponent,
// if constexpr statement in sqrt.h still requires x86::sqrt to be declared
// even when it's not used.
-LIBC_INLINE long double sqrt(long double x);
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT long double sqrt(long double x);
// Correctly rounded SQRT for all rounding modes.
// Shift-and-add algorithm.
#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
-LIBC_INLINE long double sqrt(long double x) {
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT long double sqrt(long double x) {
using LDBits = FPBits<long double>;
using StorageType = typename LDBits::StorageType;
constexpr StorageType ONE = StorageType(1) << int(LDBits::FRACTION_LEN);
- constexpr auto LDNAN = LDBits::quiet_nan().get_val();
+ LIBC_BIT_CAST_CONSTEXPR_VAR auto LDNAN = LDBits::quiet_nan().get_val();
LDBits bits(x);
diff --git a/libc/src/__support/FPUtil/rounding_mode.h b/libc/src/__support/FPUtil/rounding_mode.h
index 92061ea13e203..6ce693d41da50 100644
--- a/libc/src/__support/FPUtil/rounding_mode.h
+++ b/libc/src/__support/FPUtil/rounding_mode.h
@@ -80,7 +80,7 @@ LIBC_INLINE int quick_get_round() {
} // namespace generic
-LIBC_INLINE constexpr bool fenv_is_round_up() {
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT bool fenv_is_round_up() {
if (cpp::is_constant_evaluated()) {
return false;
} else {
@@ -88,7 +88,7 @@ LIBC_INLINE constexpr bool fenv_is_round_up() {
}
}
-LIBC_INLINE constexpr bool fenv_is_round_down() {
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT bool fenv_is_round_down() {
if (cpp::is_constant_evaluated()) {
return false;
} else {
@@ -96,7 +96,7 @@ LIBC_INLINE constexpr bool fenv_is_round_down() {
}
}
-LIBC_INLINE constexpr bool fenv_is_round_to_nearest() {
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT bool fenv_is_round_to_nearest() {
if (cpp::is_constant_evaluated()) {
return true;
} else {
@@ -104,7 +104,7 @@ LIBC_INLINE constexpr bool fenv_is_round_to_nearest() {
}
}
-LIBC_INLINE constexpr bool fenv_is_round_to_zero() {
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT bool fenv_is_round_to_zero() {
if (cpp::is_constant_evaluated()) {
return false;
} else {
@@ -113,7 +113,7 @@ LIBC_INLINE constexpr bool fenv_is_round_to_zero() {
}
// Quick free standing get rounding mode based on the above observations.
-LIBC_INLINE constexpr int quick_get_round() {
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT int quick_get_round() {
if (cpp::is_constant_evaluated()) {
return FE_TONEAREST;
} else {
diff --git a/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h b/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
index aa9f4a5e39c2d..2ea36666c9a46 100644
--- a/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
+++ b/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
@@ -24,7 +24,8 @@
namespace LIBC_NAMESPACE_DECL {
namespace fputil {
-LIBC_INLINE constexpr long double nextafter(long double from, long double to) {
+LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR long double nextafter(long double from,
+ long double to) {
using FPBits = FPBits<long double>;
FPBits from_bits(from);
if (from_bits.is_nan())
diff --git a/libc/src/__support/FPUtil/x86_64/NextUpDownLongDouble.h b/libc/src/__support/FPUtil/x86_64/NextUpDownLongDouble.h
index 31869975ac5ad..589328ae2a425 100644
--- a/libc/src/__support/FPUtil/x86_64/NextUpDownLongDouble.h
+++ b/libc/src/__support/FPUtil/x86_64/NextUpDownLongDouble.h
@@ -22,7 +22,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace fputil {
template <bool IsDown>
-LIBC_INLINE constexpr long double nextupdown(long double x) {
+LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR long double nextupdown(long double x) {
constexpr Sign sign = IsDown ? Sign::NEG : Sign::POS;
using FPBits_t = FPBits<long double>;
>From 660d9767fa29a132a6e2cd9c2158b096045199b3 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Thu, 21 May 2026 04:56:41 +0000
Subject: [PATCH 4/7] Apply fine-grained constexpr annotations to src/__support
folder.
---
libc/src/__support/big_int.h | 26 ++++++++++++++------------
libc/src/__support/complex_basic_ops.h | 4 ++--
2 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/libc/src/__support/big_int.h b/libc/src/__support/big_int.h
index a6dcff27ca167..0e5c038ec356e 100644
--- a/libc/src/__support/big_int.h
+++ b/libc/src/__support/big_int.h
@@ -242,10 +242,9 @@ LIBC_INLINE constexpr void quick_mul_hi(cpp::array<word, N> &dst,
template <typename word, size_t N>
LIBC_INLINE constexpr bool is_negative(const cpp::array<word, N> &array) {
- using signed_word = cpp::make_signed_t<word>;
- return cpp::bit_cast<signed_word>(array.back()) < 0;
+ constexpr size_t WORD_BITS = cpp::numeric_limits<word>::digits;
+ return (array.back() >> (WORD_BITS - 1)) != 0;
}
-
// An enum for the shift function below.
enum Direction { LEFT, RIGHT };
@@ -257,6 +256,7 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array,
size_t offset) {
static_assert(direction == LEFT || direction == RIGHT);
constexpr size_t WORD_BITS = cpp::numeric_limits<word>::digits;
+#if LIBC_HAS_BUILTIN_BIT_CAST
#ifdef LIBC_TYPES_HAS_INT128
constexpr size_t TOTAL_BITS = N * WORD_BITS;
if constexpr (TOTAL_BITS == 128 &&
@@ -270,6 +270,8 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array,
return cpp::bit_cast<cpp::array<word, N>>(tmp);
}
#endif
+#endif // LIBC_HAS_BUILTIN_BIT_CAST
+
if (LIBC_UNLIKELY(offset == 0))
return array;
const bool is_neg = is_signed && is_negative(array);
@@ -366,7 +368,7 @@ struct BigInt {
LIBC_INLINE constexpr BigInt(
const BigInt<OtherBits, OtherSigned, OtherWordType> &other) {
using BigIntOther = BigInt<OtherBits, OtherSigned, OtherWordType>;
- const bool should_sign_extend = Signed && other.is_neg();
+ [[maybe_unused]] const bool should_sign_extend = Signed && other.is_neg();
static_assert(!(Bits == OtherBits && WORD_SIZE != BigIntOther::WORD_SIZE) &&
"This is currently untested for casting between bigints with "
@@ -1184,7 +1186,7 @@ namespace cpp {
// Specialization of cpp::bit_cast ('bit.h') from T to BigInt.
template <typename To, typename From>
-LIBC_INLINE constexpr cpp::enable_if_t<
+LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR cpp::enable_if_t<
(sizeof(To) == sizeof(From)) && cpp::is_trivially_copyable<To>::value &&
cpp::is_trivially_copyable<From>::value && is_big_int<To>::value,
To>
@@ -1197,13 +1199,13 @@ bit_cast(const From &from) {
// Specialization of cpp::bit_cast ('bit.h') from BigInt to T.
template <typename To, size_t Bits>
-LIBC_INLINE constexpr cpp::enable_if_t<
- sizeof(To) == sizeof(UInt<Bits>) &&
- cpp::is_trivially_constructible<To>::value &&
- cpp::is_trivially_copyable<To>::value &&
- cpp::is_trivially_copyable<UInt<Bits>>::value,
- To>
-bit_cast(const UInt<Bits> &from) {
+LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR
+ cpp::enable_if_t<sizeof(To) == sizeof(UInt<Bits>) &&
+ cpp::is_trivially_constructible<To>::value &&
+ cpp::is_trivially_copyable<To>::value &&
+ cpp::is_trivially_copyable<UInt<Bits>>::value,
+ To>
+ bit_cast(const UInt<Bits> &from) {
return cpp::bit_cast<To>(from.val);
}
diff --git a/libc/src/__support/complex_basic_ops.h b/libc/src/__support/complex_basic_ops.h
index 5992ebec0786c..bf488730d1c72 100644
--- a/libc/src/__support/complex_basic_ops.h
+++ b/libc/src/__support/complex_basic_ops.h
@@ -15,13 +15,13 @@
namespace LIBC_NAMESPACE_DECL {
-template <typename T> LIBC_INLINE constexpr T conjugate(T c) {
+template <typename T> LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR T conjugate(T c) {
Complex<make_real_t<T>> c_c = cpp::bit_cast<Complex<make_real_t<T>>>(c);
c_c.imag = -c_c.imag;
return cpp::bit_cast<T>(c_c);
}
-template <typename T> LIBC_INLINE constexpr T project(T c) {
+template <typename T> LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR T project(T c) {
using real_t = make_real_t<T>;
Complex<real_t> c_c = cpp::bit_cast<Complex<real_t>>(c);
if (fputil::FPBits<real_t>(c_c.real).is_inf() ||
>From 51bd08ae08d43dc8c74875258524157a3e3432ad Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Thu, 21 May 2026 04:57:40 +0000
Subject: [PATCH 5/7] Remove or update constexpr annotations for functions in
src/__support/math folder.
---
libc/src/__support/math/acos.h | 2 +-
libc/src/__support/math/acosf.h | 2 +-
libc/src/__support/math/acoshf.h | 2 +-
libc/src/__support/math/asinf.h | 2 +-
libc/src/__support/math/asinhf.h | 2 +-
libc/src/__support/math/atan.h | 2 +-
libc/src/__support/math/atan2.h | 2 +-
libc/src/__support/math/atan2f.h | 2 +-
libc/src/__support/math/atan2f128.h | 2 +-
libc/src/__support/math/atanf.h | 2 +-
libc/src/__support/math/atanhf.h | 2 +-
libc/src/__support/math/cbrt.h | 2 +-
libc/src/__support/math/cbrtf.h | 2 +-
libc/src/__support/math/cos.h | 2 +-
libc/src/__support/math/cosf.h | 4 ++--
libc/src/__support/math/coshf.h | 2 +-
libc/src/__support/math/cospif.h | 2 +-
libc/src/__support/math/dsqrtf128.h | 2 +-
libc/src/__support/math/dsqrtl.h | 2 +-
libc/src/__support/math/erff.h | 2 +-
libc/src/__support/math/exp10.h | 9 ++++-----
libc/src/__support/math/exp10f.h | 2 +-
libc/src/__support/math/exp10m1f.h | 2 +-
libc/src/__support/math/exp2.h | 10 +++++-----
libc/src/__support/math/exp2f.h | 2 +-
libc/src/__support/math/exp2m1f.h | 2 +-
libc/src/__support/math/expf.h | 2 +-
libc/src/__support/math/expm1.h | 9 ++++-----
libc/src/__support/math/expm1f.h | 2 +-
libc/src/__support/math/fsqrt.h | 4 +++-
libc/src/__support/math/fsqrtf128.h | 2 +-
libc/src/__support/math/fsqrtl.h | 2 +-
libc/src/__support/math/log.h | 2 +-
libc/src/__support/math/nextafterl.h | 2 +-
libc/src/__support/math/nextdownl.h | 2 +-
libc/src/__support/math/nextupl.h | 2 +-
libc/src/__support/math/pow.h | 4 ++--
libc/src/__support/math/powf.h | 6 +++---
libc/src/__support/math/rsqrtf.h | 2 +-
libc/src/__support/math/sin.h | 2 +-
libc/src/__support/math/sinhf.h | 2 +-
libc/src/__support/math/tan.h | 2 +-
42 files changed, 58 insertions(+), 58 deletions(-)
diff --git a/libc/src/__support/math/acos.h b/libc/src/__support/math/acos.h
index 6b419449176fd..2ee7974358b18 100644
--- a/libc/src/__support/math/acos.h
+++ b/libc/src/__support/math/acos.h
@@ -24,7 +24,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr double acos(double x) {
+LIBC_INLINE double acos(double x) {
using DoubleDouble = fputil::DoubleDouble;
using namespace asin_internal;
using FPBits = fputil::FPBits<double>;
diff --git a/libc/src/__support/math/acosf.h b/libc/src/__support/math/acosf.h
index ae93abe7e716a..abfc8ce14c8b0 100644
--- a/libc/src/__support/math/acosf.h
+++ b/libc/src/__support/math/acosf.h
@@ -46,7 +46,7 @@ LIBC_INLINE_VAR constexpr fputil::ExceptValues<float, N_EXCEPTS> ACOSF_EXCEPTS =
} // namespace acosf_internal
-LIBC_INLINE constexpr float acosf(float x) {
+LIBC_INLINE float acosf(float x) {
using namespace acosf_internal;
using namespace inv_trigf_utils_internal;
using FPBits = typename fputil::FPBits<float>;
diff --git a/libc/src/__support/math/acoshf.h b/libc/src/__support/math/acoshf.h
index b111a21c07b70..02b2a3d5a513d 100644
--- a/libc/src/__support/math/acoshf.h
+++ b/libc/src/__support/math/acoshf.h
@@ -22,7 +22,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float acoshf(float x) {
+LIBC_INLINE float acoshf(float x) {
using namespace acoshf_internal;
using FPBits_t = typename fputil::FPBits<float>;
FPBits_t xbits(x);
diff --git a/libc/src/__support/math/asinf.h b/libc/src/__support/math/asinf.h
index 08cfb192754e4..8bafce5d8ba3d 100644
--- a/libc/src/__support/math/asinf.h
+++ b/libc/src/__support/math/asinf.h
@@ -23,7 +23,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float asinf(float x) {
+LIBC_INLINE float asinf(float x) {
using namespace inv_trigf_utils_internal;
using FPBits = typename fputil::FPBits<float>;
diff --git a/libc/src/__support/math/asinhf.h b/libc/src/__support/math/asinhf.h
index e420eae221c3e..ac77eb2085853 100644
--- a/libc/src/__support/math/asinhf.h
+++ b/libc/src/__support/math/asinhf.h
@@ -21,7 +21,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float asinhf(float x) {
+LIBC_INLINE float asinhf(float x) {
using namespace acoshf_internal;
using FPBits_t = typename fputil::FPBits<float>;
FPBits_t xbits(x);
diff --git a/libc/src/__support/math/atan.h b/libc/src/__support/math/atan.h
index db60311bd746d..8a11167a6268e 100644
--- a/libc/src/__support/math/atan.h
+++ b/libc/src/__support/math/atan.h
@@ -52,7 +52,7 @@ namespace math {
// So we can return:
// atan(x) = sign(x) * (pi/2 - epsilon)
-LIBC_INLINE constexpr double atan(double x) {
+LIBC_INLINE double atan(double x) {
using namespace atan_internal;
using FPBits = fputil::FPBits<double>;
diff --git a/libc/src/__support/math/atan2.h b/libc/src/__support/math/atan2.h
index f59d92b6dc19c..a009af39354a1 100644
--- a/libc/src/__support/math/atan2.h
+++ b/libc/src/__support/math/atan2.h
@@ -75,7 +75,7 @@ namespace math {
// and relative errors bounded by:
// |(atan(u) - P(u)) / P(u)| < u^10 / 11 < 2^-73.
-LIBC_INLINE constexpr double atan2(double y, double x) {
+LIBC_INLINE double atan2(double y, double x) {
using namespace atan_internal;
using FPBits = fputil::FPBits<double>;
diff --git a/libc/src/__support/math/atan2f.h b/libc/src/__support/math/atan2f.h
index 15d1fce2b707c..3a56291a832d3 100644
--- a/libc/src/__support/math/atan2f.h
+++ b/libc/src/__support/math/atan2f.h
@@ -239,7 +239,7 @@ LIBC_INLINE float atan2f_double_double(double num_d, double den_d, double q_d,
// 0x1.aec6f...p-100
// which is about rounding errors of double-double (2^-104).
-LIBC_INLINE constexpr float atan2f(float y, float x) {
+LIBC_INLINE float atan2f(float y, float x) {
using namespace atan2f_internal;
using namespace inv_trigf_utils_internal;
using FPBits = typename fputil::FPBits<float>;
diff --git a/libc/src/__support/math/atan2f128.h b/libc/src/__support/math/atan2f128.h
index d04cf6f49d4ea..e72499ec5af20 100644
--- a/libc/src/__support/math/atan2f128.h
+++ b/libc/src/__support/math/atan2f128.h
@@ -81,7 +81,7 @@ namespace math {
// and relative errors bounded by:
// |(atan(u) - P(u)) / P(u)| < 2^-114.
-LIBC_INLINE constexpr float128 atan2f128(float128 y, float128 x) {
+LIBC_INLINE float128 atan2f128(float128 y, float128 x) {
using Float128 = fputil::DyadicFloat<128>;
constexpr Float128 ZERO = {Sign::POS, 0, 0_u128};
diff --git a/libc/src/__support/math/atanf.h b/libc/src/__support/math/atanf.h
index d583572ea4727..78b8b25b8b2c6 100644
--- a/libc/src/__support/math/atanf.h
+++ b/libc/src/__support/math/atanf.h
@@ -30,7 +30,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float atanf(float x) {
+LIBC_INLINE float atanf(float x) {
using namespace inv_trigf_utils_internal;
using FPBits = typename fputil::FPBits<float>;
diff --git a/libc/src/__support/math/atanhf.h b/libc/src/__support/math/atanhf.h
index 16d46994e2705..684b74a46d353 100644
--- a/libc/src/__support/math/atanhf.h
+++ b/libc/src/__support/math/atanhf.h
@@ -19,7 +19,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float atanhf(float x) {
+LIBC_INLINE float atanhf(float x) {
using namespace acoshf_internal;
using FPBits = typename fputil::FPBits<float>;
diff --git a/libc/src/__support/math/cbrt.h b/libc/src/__support/math/cbrt.h
index a781ed36238b8..1998731aeb4f8 100644
--- a/libc/src/__support/math/cbrt.h
+++ b/libc/src/__support/math/cbrt.h
@@ -144,7 +144,7 @@ LIBC_INLINE constexpr double get_error(const DoubleDouble &x_3,
// exceptional handling, similar to what was done in the CORE-MATH project:
// https://gitlab.inria.fr/core-math/core-math/-/blob/master/src/binary64/cbrt/cbrt.c
-LIBC_INLINE constexpr double cbrt(double x) {
+LIBC_INLINE double cbrt(double x) {
using DoubleDouble = fputil::DoubleDouble;
using namespace cbrt_internal;
using FPBits = fputil::FPBits<double>;
diff --git a/libc/src/__support/math/cbrtf.h b/libc/src/__support/math/cbrtf.h
index 35e60562a39c0..5f0c413088a36 100644
--- a/libc/src/__support/math/cbrtf.h
+++ b/libc/src/__support/math/cbrtf.h
@@ -19,7 +19,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float cbrtf(float x) {
+LIBC_INLINE float cbrtf(float x) {
// Look up table for 2^(i/3) for i = 0, 1, 2.
constexpr double CBRT2[3] = {1.0, 0x1.428a2f98d728bp0, 0x1.965fea53d6e3dp0};
diff --git a/libc/src/__support/math/cos.h b/libc/src/__support/math/cos.h
index e6a37c132cd80..93ca20ed41e03 100644
--- a/libc/src/__support/math/cos.h
+++ b/libc/src/__support/math/cos.h
@@ -30,7 +30,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr double cos(double x) {
+LIBC_INLINE double cos(double x) {
using namespace range_reduction_double_internal;
using FPBits = typename fputil::FPBits<double>;
FPBits xbits(x);
diff --git a/libc/src/__support/math/cosf.h b/libc/src/__support/math/cosf.h
index f6ead968ac26e..affff7117562a 100644
--- a/libc/src/__support/math/cosf.h
+++ b/libc/src/__support/math/cosf.h
@@ -26,7 +26,7 @@
namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float cosf(float x) {
+LIBC_INLINE float cosf(float x) {
return sincosf_float_eval::sincosf_eval</*IS_SIN*/ false>(x);
}
@@ -41,7 +41,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float cosf(float x) {
+LIBC_INLINE float cosf(float x) {
using namespace sincosf_utils_internal;
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
diff --git a/libc/src/__support/math/coshf.h b/libc/src/__support/math/coshf.h
index aa0988f9711f1..d80d86af301ab 100644
--- a/libc/src/__support/math/coshf.h
+++ b/libc/src/__support/math/coshf.h
@@ -20,7 +20,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float coshf(float x) {
+LIBC_INLINE float coshf(float x) {
using namespace sinhfcoshf_internal;
using FPBits = typename fputil::FPBits<float>;
diff --git a/libc/src/__support/math/cospif.h b/libc/src/__support/math/cospif.h
index 3d0a335408722..49100feba3230 100644
--- a/libc/src/__support/math/cospif.h
+++ b/libc/src/__support/math/cospif.h
@@ -22,7 +22,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float cospif(float x) {
+LIBC_INLINE float cospif(float x) {
using namespace sincosf_utils_internal;
using FPBits = typename fputil::FPBits<float>;
diff --git a/libc/src/__support/math/dsqrtf128.h b/libc/src/__support/math/dsqrtf128.h
index 241e1b437982a..6b0521410dc43 100644
--- a/libc/src/__support/math/dsqrtf128.h
+++ b/libc/src/__support/math/dsqrtf128.h
@@ -19,7 +19,7 @@
namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr double dsqrtf128(float128 x) {
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT double dsqrtf128(float128 x) {
return fputil::sqrt<double>(x);
}
diff --git a/libc/src/__support/math/dsqrtl.h b/libc/src/__support/math/dsqrtl.h
index 14decf8c6ed77..110f8aff92f56 100644
--- a/libc/src/__support/math/dsqrtl.h
+++ b/libc/src/__support/math/dsqrtl.h
@@ -15,7 +15,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr double dsqrtl(long double x) {
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT double dsqrtl(long double x) {
return fputil::sqrt<double>(x);
}
diff --git a/libc/src/__support/math/erff.h b/libc/src/__support/math/erff.h
index a40b927c60a26..63919734cf744 100644
--- a/libc/src/__support/math/erff.h
+++ b/libc/src/__support/math/erff.h
@@ -19,7 +19,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float erff(float x) {
+LIBC_INLINE float erff(float x) {
// Polynomials approximating erf(x)/x on ( k/8, (k + 1)/8 ) generated by
// Sollya with: > P = fpminimax(erf(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14|],
diff --git a/libc/src/__support/math/exp10.h b/libc/src/__support/math/exp10.h
index c2ca627d20db9..17dc70f7a2fd2 100644
--- a/libc/src/__support/math/exp10.h
+++ b/libc/src/__support/math/exp10.h
@@ -83,8 +83,7 @@ LIBC_INLINE double exp10_poly_approx_d(double dx) {
// > P = fpminimax((10^x - 1)/x, 5, [|DD...|], [-2^-14, 2^-14]);
// Error bounds:
// | output - 10^(dx) | < 2^-101
-LIBC_INLINE constexpr DoubleDouble
-exp10_poly_approx_dd(const DoubleDouble &dx) {
+LIBC_INLINE DoubleDouble exp10_poly_approx_dd(const DoubleDouble &dx) {
// Taylor polynomial.
constexpr DoubleDouble COEFFS[] = {
{0, 0x1p0},
@@ -106,7 +105,7 @@ exp10_poly_approx_dd(const DoubleDouble &dx) {
// Return exp(dx) ~ 1 + a0 * dx + a1 * dx^2 + ... + a6 * dx^7
// For |dx| < 2^-14:
// | output - 10^dx | < 1.5 * 2^-124.
-LIBC_INLINE constexpr Float128 exp10_poly_approx_f128(const Float128 &dx) {
+LIBC_INLINE Float128 exp10_poly_approx_f128(const Float128 &dx) {
constexpr Float128 COEFFS_128[]{
{Sign::POS, -127, 0x80000000'00000000'00000000'00000000_u128}, // 1.0
{Sign::POS, -126, 0x935d8ddd'aaa8ac16'ea56d62b'82d30a2d_u128},
@@ -235,7 +234,7 @@ LIBC_INLINE double exp10_denorm(double x) {
// * x >= log10(2^1024)
// * x <= log10(2^-1022)
// * x is inf or nan
-LIBC_INLINE constexpr double exp10_set_exceptional(double x) {
+LIBC_INLINE double exp10_set_exceptional(double x) {
using FPBits = typename fputil::FPBits<double>;
FPBits xbits(x);
@@ -286,7 +285,7 @@ LIBC_INLINE constexpr double exp10_set_exceptional(double x) {
namespace math {
-LIBC_INLINE constexpr double exp10(double x) {
+LIBC_INLINE double exp10(double x) {
using FPBits = typename fputil::FPBits<double>;
FPBits xbits(x);
diff --git a/libc/src/__support/math/exp10f.h b/libc/src/__support/math/exp10f.h
index 31d3492d56a5e..41f9a73a09935 100644
--- a/libc/src/__support/math/exp10f.h
+++ b/libc/src/__support/math/exp10f.h
@@ -20,7 +20,7 @@
namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float exp10f(float x) {
+LIBC_INLINE float exp10f(float x) {
using FPBits = typename fputil::FPBits<float>;
FPBits xbits(x);
diff --git a/libc/src/__support/math/exp10m1f.h b/libc/src/__support/math/exp10m1f.h
index 25cfa13789ebd..c45d3752d6f6c 100644
--- a/libc/src/__support/math/exp10m1f.h
+++ b/libc/src/__support/math/exp10m1f.h
@@ -104,7 +104,7 @@ LIBC_INLINE_VAR constexpr fputil::ExceptValues<float, N_EXCEPTS_HI>
} // namespace exp10m1f_internal
-LIBC_INLINE constexpr float exp10m1f(float x) {
+LIBC_INLINE float exp10m1f(float x) {
using namespace exp10m1f_internal;
using FPBits = fputil::FPBits<float>;
FPBits xbits(x);
diff --git a/libc/src/__support/math/exp2.h b/libc/src/__support/math/exp2.h
index 9a3e9c6f19dec..1f12347c7103d 100644
--- a/libc/src/__support/math/exp2.h
+++ b/libc/src/__support/math/exp2.h
@@ -77,7 +77,7 @@ LIBC_INLINE double poly_approx_d(double dx) {
// > P = fpminimax((2^x - 1)/x, 5, [|DD...|], [-2^-13 - 2^-30, 2^-13 + 2^-30]);
// Error bounds:
// | output - 2^(dx) | < 2^-101
-LIBC_INLINE constexpr DoubleDouble poly_approx_dd(const DoubleDouble &dx) {
+LIBC_INLINE DoubleDouble poly_approx_dd(const DoubleDouble &dx) {
// Taylor polynomial.
constexpr DoubleDouble COEFFS[] = {
{0, 0x1p0},
@@ -98,7 +98,7 @@ LIBC_INLINE constexpr DoubleDouble poly_approx_dd(const DoubleDouble &dx) {
// Return exp(dx) ~ 1 + a0 * dx + a1 * dx^2 + ... + a6 * dx^7
// For |dx| < 2^-13 + 2^-30:
// | output - exp(dx) | < 2^-126.
-LIBC_INLINE constexpr Float128 poly_approx_f128(const Float128 &dx) {
+LIBC_INLINE Float128 poly_approx_f128(const Float128 &dx) {
constexpr Float128 COEFFS_128[]{
{Sign::POS, -127, 0x80000000'00000000'00000000'00000000_u128}, // 1.0
{Sign::POS, -128, 0xb17217f7'd1cf79ab'c9e3b398'03f2f6af_u128},
@@ -119,7 +119,7 @@ LIBC_INLINE constexpr Float128 poly_approx_f128(const Float128 &dx) {
// Compute 2^(x) using 128-bit precision.
// TODO(lntue): investigate triple-double precision implementation for this
// step.
-LIBC_INLINE constexpr Float128 exp2_f128(double x, int hi, int idx1, int idx2) {
+LIBC_INLINE Float128 exp2_f128(double x, int hi, int idx1, int idx2) {
Float128 dx = Float128(x);
// TODO: Skip recalculating exp_mid1 and exp_mid2.
@@ -213,7 +213,7 @@ LIBC_INLINE double exp2_denorm(double x) {
// * x >= 1024
// * x <= -1022
// * x is inf or nan
-LIBC_INLINE constexpr double set_exceptional(double x) {
+LIBC_INLINE double set_exceptional(double x) {
using FPBits = typename fputil::FPBits<double>;
FPBits xbits(x);
@@ -264,7 +264,7 @@ LIBC_INLINE constexpr double set_exceptional(double x) {
} // namespace exp2_internal
-LIBC_INLINE constexpr double exp2(double x) {
+LIBC_INLINE double exp2(double x) {
using namespace exp2_internal;
using FPBits = typename fputil::FPBits<double>;
FPBits xbits(x);
diff --git a/libc/src/__support/math/exp2f.h b/libc/src/__support/math/exp2f.h
index a231fcedda034..439c752969b4d 100644
--- a/libc/src/__support/math/exp2f.h
+++ b/libc/src/__support/math/exp2f.h
@@ -26,7 +26,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float exp2f(float x) {
+LIBC_INLINE float exp2f(float x) {
using FPBits = typename fputil::FPBits<float>;
FPBits xbits(x);
diff --git a/libc/src/__support/math/exp2m1f.h b/libc/src/__support/math/exp2m1f.h
index f1acde27ac0e1..49cd4589ace85 100644
--- a/libc/src/__support/math/exp2m1f.h
+++ b/libc/src/__support/math/exp2m1f.h
@@ -26,7 +26,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float exp2m1f(float x) {
+LIBC_INLINE float exp2m1f(float x) {
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
constexpr size_t N_EXCEPTS_LO = 8;
diff --git a/libc/src/__support/math/expf.h b/libc/src/__support/math/expf.h
index 5fcf0ffa97d5c..a635c01d22772 100644
--- a/libc/src/__support/math/expf.h
+++ b/libc/src/__support/math/expf.h
@@ -24,7 +24,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float expf(float x) {
+LIBC_INLINE float expf(float x) {
using FPBits = typename fputil::FPBits<float>;
FPBits xbits(x);
diff --git a/libc/src/__support/math/expm1.h b/libc/src/__support/math/expm1.h
index 2e07e10883547..0e581ea29fcd7 100644
--- a/libc/src/__support/math/expm1.h
+++ b/libc/src/__support/math/expm1.h
@@ -87,7 +87,7 @@ LIBC_INLINE double poly_approx_d(double dx) {
// Return expm1(dx) / dx ~ 1 + dx / 2 + dx^2 / 6 + ... + dx^6 / 5040
// For |dx| < 2^-13 + 2^-30:
// | output - expm1(dx) | < 2^-101
-LIBC_INLINE constexpr DoubleDouble poly_approx_dd(const DoubleDouble &dx) {
+LIBC_INLINE DoubleDouble poly_approx_dd(const DoubleDouble &dx) {
// Taylor polynomial.
constexpr DoubleDouble COEFFS[] = {
{0, 0x1p0}, // 1
@@ -108,8 +108,7 @@ LIBC_INLINE constexpr DoubleDouble poly_approx_dd(const DoubleDouble &dx) {
// Return (exp(dx) - 1)/dx ~ 1 + dx / 2 + dx^2 / 6 + ... + dx^6 / 5040
// For |dx| < 2^-13 + 2^-30:
// | output - exp(dx) | < 2^-126.
-[[maybe_unused]] LIBC_INLINE constexpr Float128
-poly_approx_f128(const Float128 &dx) {
+[[maybe_unused]] LIBC_INLINE Float128 poly_approx_f128(const Float128 &dx) {
constexpr Float128 COEFFS_128[]{
{Sign::POS, -127, 0x80000000'00000000'00000000'00000000_u128}, // 1.0
{Sign::POS, -128, 0x80000000'00000000'00000000'00000000_u128}, // 0.5
@@ -225,7 +224,7 @@ LIBC_INLINE DoubleDouble exp_double_double(double x, double kd,
// Check for exceptional cases when
// |x| <= 2^-53 or x < log(2^-54) or x >= 0x1.6232bdd7abcd3p+9
-LIBC_INLINE constexpr double set_exceptional(double x) {
+LIBC_INLINE double set_exceptional(double x) {
using FPBits = typename fputil::FPBits<double>;
FPBits xbits(x);
@@ -279,7 +278,7 @@ LIBC_INLINE constexpr double set_exceptional(double x) {
} // namespace expm1_internal
-LIBC_INLINE constexpr double expm1(double x) {
+LIBC_INLINE double expm1(double x) {
using namespace expm1_internal;
using FPBits = typename fputil::FPBits<double>;
diff --git a/libc/src/__support/math/expm1f.h b/libc/src/__support/math/expm1f.h
index f581635f77c7b..60dd62bf7be8d 100644
--- a/libc/src/__support/math/expm1f.h
+++ b/libc/src/__support/math/expm1f.h
@@ -27,7 +27,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float expm1f(float x) {
+LIBC_INLINE float expm1f(float x) {
using namespace common_constants_internal;
using FPBits = typename fputil::FPBits<float>;
FPBits xbits(x);
diff --git a/libc/src/__support/math/fsqrt.h b/libc/src/__support/math/fsqrt.h
index d35f25b9a8111..30fb8f4f5a84b 100644
--- a/libc/src/__support/math/fsqrt.h
+++ b/libc/src/__support/math/fsqrt.h
@@ -15,7 +15,9 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float fsqrt(double x) { return fputil::sqrt<float>(x); }
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT float fsqrt(double x) {
+ return fputil::sqrt<float>(x);
+}
} // namespace math
diff --git a/libc/src/__support/math/fsqrtf128.h b/libc/src/__support/math/fsqrtf128.h
index 955e19a818c57..61353c8043dd3 100644
--- a/libc/src/__support/math/fsqrtf128.h
+++ b/libc/src/__support/math/fsqrtf128.h
@@ -21,7 +21,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float fsqrtf128(float128 x) {
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT float fsqrtf128(float128 x) {
return fputil::sqrt<float>(x);
}
diff --git a/libc/src/__support/math/fsqrtl.h b/libc/src/__support/math/fsqrtl.h
index 26c3b9e4c14c9..44b6609b713a4 100644
--- a/libc/src/__support/math/fsqrtl.h
+++ b/libc/src/__support/math/fsqrtl.h
@@ -15,7 +15,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float fsqrtl(long double x) {
+LIBC_INLINE LIBC_CONSTEXPR_DEFAULT float fsqrtl(long double x) {
return fputil::sqrt<float>(x);
}
diff --git a/libc/src/__support/math/log.h b/libc/src/__support/math/log.h
index 62bdf4e25431e..917d1cc51cbb1 100644
--- a/libc/src/__support/math/log.h
+++ b/libc/src/__support/math/log.h
@@ -721,7 +721,7 @@ LIBC_INLINE_VAR constexpr Float128 BIG_COEFFS[3]{
// Reuse the output of the fast pass range reduction.
// -2^-8 <= m_x < 2^-7
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-LIBC_INLINE constexpr double log_accurate(int e_x, int index, double m_x) {
+LIBC_INLINE double log_accurate(int e_x, int index, double m_x) {
Float128 e_x_f128(static_cast<float>(e_x));
Float128 sum = fputil::quick_mul(LOG_2, e_x_f128);
sum = fputil::quick_add(sum, LOG_TABLE.step_1[index]);
diff --git a/libc/src/__support/math/nextafterl.h b/libc/src/__support/math/nextafterl.h
index a173ccfaa4c73..cf2c2e6da5fb4 100644
--- a/libc/src/__support/math/nextafterl.h
+++ b/libc/src/__support/math/nextafterl.h
@@ -16,7 +16,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr long double nextafterl(long double x, long double y) {
+LIBC_INLINE long double nextafterl(long double x, long double y) {
return fputil::nextafter(x, y);
}
diff --git a/libc/src/__support/math/nextdownl.h b/libc/src/__support/math/nextdownl.h
index 235186d0b2d43..d0a71fe55fb7d 100644
--- a/libc/src/__support/math/nextdownl.h
+++ b/libc/src/__support/math/nextdownl.h
@@ -16,7 +16,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr long double nextdownl(long double x) {
+LIBC_INLINE long double nextdownl(long double x) {
return fputil::nextupdown</*IsDown=*/true>(x);
}
diff --git a/libc/src/__support/math/nextupl.h b/libc/src/__support/math/nextupl.h
index 2d0e43a3d9f5a..5e2ff41bc8c89 100644
--- a/libc/src/__support/math/nextupl.h
+++ b/libc/src/__support/math/nextupl.h
@@ -16,7 +16,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr long double nextupl(long double x) {
+LIBC_INLINE long double nextupl(long double x) {
return fputil::nextupdown</*IsDown=*/false>(x);
}
diff --git a/libc/src/__support/math/pow.h b/libc/src/__support/math/pow.h
index 27e382435ecb3..c03e6be271d05 100644
--- a/libc/src/__support/math/pow.h
+++ b/libc/src/__support/math/pow.h
@@ -177,7 +177,7 @@ LIBC_INLINE_VAR constexpr DoubleDouble LOG2_R_DD[128] = {
{0.0, 1.0},
};
-LIBC_INLINE constexpr bool is_odd_integer(double x) {
+LIBC_INLINE bool is_odd_integer(double x) {
using FPBits = fputil::FPBits<double>;
FPBits xbits(x);
uint64_t x_u = xbits.uintval();
@@ -189,7 +189,7 @@ LIBC_INLINE constexpr bool is_odd_integer(double x) {
return (x_e + lsb == UNIT_EXPONENT);
}
-LIBC_INLINE constexpr bool is_integer(double x) {
+LIBC_INLINE bool is_integer(double x) {
using FPBits = fputil::FPBits<double>;
FPBits xbits(x);
uint64_t x_u = xbits.uintval();
diff --git a/libc/src/__support/math/powf.h b/libc/src/__support/math/powf.h
index 5762309794d27..7721d0d7f9534 100644
--- a/libc/src/__support/math/powf.h
+++ b/libc/src/__support/math/powf.h
@@ -533,7 +533,7 @@ LIBC_INLINE_VAR constexpr DoubleDouble LOG2_R2_DD[] = {
};
#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-LIBC_INLINE constexpr bool is_odd_integer(float x) {
+LIBC_INLINE bool is_odd_integer(float x) {
using FPBits = typename fputil::FPBits<float>;
uint32_t x_u = cpp::bit_cast<uint32_t>(x);
int32_t x_e =
@@ -544,7 +544,7 @@ LIBC_INLINE constexpr bool is_odd_integer(float x) {
return (x_e + lsb == UNIT_EXPONENT);
}
-LIBC_INLINE constexpr bool is_integer(float x) {
+LIBC_INLINE bool is_integer(float x) {
using FPBits = typename fputil::FPBits<float>;
uint32_t x_u = cpp::bit_cast<uint32_t>(x);
int32_t x_e =
@@ -556,7 +556,7 @@ LIBC_INLINE constexpr bool is_integer(float x) {
}
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-LIBC_INLINE constexpr bool larger_exponent(double a, double b) {
+LIBC_INLINE bool larger_exponent(double a, double b) {
using DoubleBits = typename fputil::FPBits<double>;
return DoubleBits(a).get_biased_exponent() >=
DoubleBits(b).get_biased_exponent();
diff --git a/libc/src/__support/math/rsqrtf.h b/libc/src/__support/math/rsqrtf.h
index 1e98a5dbb428f..78606be68cce1 100644
--- a/libc/src/__support/math/rsqrtf.h
+++ b/libc/src/__support/math/rsqrtf.h
@@ -20,7 +20,7 @@
namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float rsqrtf(float x) {
+LIBC_INLINE float rsqrtf(float x) {
using FPBits = fputil::FPBits<float>;
FPBits xbits(x);
diff --git a/libc/src/__support/math/sin.h b/libc/src/__support/math/sin.h
index 124df61b1dc80..7f2833e30f135 100644
--- a/libc/src/__support/math/sin.h
+++ b/libc/src/__support/math/sin.h
@@ -29,7 +29,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr double sin(double x) {
+LIBC_INLINE double sin(double x) {
using namespace math::range_reduction_double_internal;
using FPBits = typename fputil::FPBits<double>;
FPBits xbits(x);
diff --git a/libc/src/__support/math/sinhf.h b/libc/src/__support/math/sinhf.h
index 6af34412129fc..141d87ba72bd2 100644
--- a/libc/src/__support/math/sinhf.h
+++ b/libc/src/__support/math/sinhf.h
@@ -20,7 +20,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr float sinhf(float x) {
+LIBC_INLINE float sinhf(float x) {
using FPBits = typename fputil::FPBits<float>;
FPBits xbits(x);
uint32_t x_abs = xbits.abs().uintval();
diff --git a/libc/src/__support/math/tan.h b/libc/src/__support/math/tan.h
index 27cd4b7a044ab..7717f835dc94d 100644
--- a/libc/src/__support/math/tan.h
+++ b/libc/src/__support/math/tan.h
@@ -111,7 +111,7 @@ LIBC_INLINE double tan_eval(const DoubleDouble &u, DoubleDouble &result) {
[[maybe_unused]] Float128 newton_raphson_div(const Float128 &a, Float128 b,
double q) {
Float128 q0(q);
- constexpr Float128 TWO(2.0);
+ LIBC_BIT_CAST_CONSTEXPR_VAR Float128 TWO(2.0);
b.sign = (b.sign == Sign::POS) ? Sign::NEG : Sign::POS;
Float128 q1 =
fputil::quick_mul(q0, fputil::quick_add(TWO, fputil::quick_mul(b, q0)));
>From 7929f8ac8bdd0dfa7b4d24e249bbaef6e8acfb11 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Thu, 21 May 2026 04:58:54 +0000
Subject: [PATCH 6/7] Fix or ignore old gcc's warnings.
---
libc/cmake/modules/CheckCompilerFeatures.cmake | 5 ++++-
libc/cmake/modules/LLVMLibCCompileOptionRules.cmake | 11 +++++++++--
libc/cmake/modules/LLVMLibCTestRules.cmake | 7 ++++++-
libc/src/string/memory_utils/utils.h | 2 ++
libc/src/string/memory_utils/x86_64/inline_strlen.h | 13 ++++++-------
libc/test/shared/shared_math_constexpr_test.cpp | 2 +-
6 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/libc/cmake/modules/CheckCompilerFeatures.cmake b/libc/cmake/modules/CheckCompilerFeatures.cmake
index cbaa3213f1bf3..325b5efe3f805 100644
--- a/libc/cmake/modules/CheckCompilerFeatures.cmake
+++ b/libc/cmake/modules/CheckCompilerFeatures.cmake
@@ -154,4 +154,7 @@ check_cxx_compiler_flag("-nostdlib++" LIBC_CC_SUPPORTS_NOSTDLIBPP)
check_cxx_compiler_flag("-nostdlibinc" LIBC_CC_SUPPORTS_NOSTDLIBINC)
# clang-23+, post llvm.org/pr187860
-check_cxx_compiler_flag("-Werror -Wno-fenv-access" LIBC_CC_SUPPORTS_NO_FENV_ACCESS)
+check_cxx_compiler_flag("-Wfenv-access" LIBC_CC_SUPPORTS_NO_FENV_ACCESS)
+
+# clang-all, gcc-8+
+check_cxx_compiler_flag("-Wextra-semi" LIBC_CC_SUPPORTS_EXTRA_SEMI)
diff --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
index b8c4ee0801b9d..2ac20590c1819 100644
--- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
+++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
@@ -288,7 +288,12 @@ function(_get_common_compile_options output_var flags)
if(NOT LIBC_WNO_ERROR)
list(APPEND compile_options "-Werror")
endif()
- list(APPEND compile_options "-Wconversion")
+ if(NOT (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0.0"))
+ list(APPEND compile_options "-Wconversion")
+ else()
+ list(APPEND compile_options "-Wno-type-limits")
+ list(APPEND compile_options "-Wno-attributes")
+ endif()
list(APPEND compile_options "-Wno-sign-conversion")
list(APPEND compile_options "-Wdeprecated")
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
@@ -301,7 +306,9 @@ function(_get_common_compile_options output_var flags)
list(APPEND compile_options "-Wno-pedantic")
list(APPEND compile_options "-Wimplicit-fallthrough")
list(APPEND compile_options "-Wwrite-strings")
- list(APPEND compile_options "-Wextra-semi")
+ if(LIBC_CC_SUPPORTS_EXTRA_SEMI)
+ list(APPEND compile_options "-Wextra-semi")
+ endif()
if(NOT CMAKE_COMPILER_IS_GNUCXX)
list(APPEND compile_options "-Wnewline-eof")
list(APPEND compile_options "-Wnonportable-system-include-path")
diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index 9faf47f4d3297..39f227464402b 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -44,7 +44,12 @@ function(_get_common_test_compile_options output_var c_test flags)
if(NOT LIBC_WNO_ERROR)
# list(APPEND compile_options "-Werror")
endif()
- list(APPEND compile_options "-Wconversion")
+ if(NOT (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0.0"))
+ list(APPEND compile_options "-Wconversion")
+ else()
+ list(APPEND compile_options "-Wno-type-limits")
+ list(APPEND compile_options "-Wno-attributes")
+ endif()
# FIXME: convert to -Wsign-conversion
list(APPEND compile_options "-Wno-sign-conversion")
list(APPEND compile_options "-Wimplicit-fallthrough")
diff --git a/libc/src/string/memory_utils/utils.h b/libc/src/string/memory_utils/utils.h
index 6f6882b49223b..9824c4b058b3a 100644
--- a/libc/src/string/memory_utils/utils.h
+++ b/libc/src/string/memory_utils/utils.h
@@ -94,7 +94,9 @@ LIBC_INLINE void memcpy_inline(void *__restrict dst,
#ifndef LIBC_COMPILER_IS_MSVC
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
+#if defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 1100)
#pragma GCC diagnostic ignored "-Wstringop-overread"
+#endif // LIBC_COMPILER_IS_GCC && LIBC_COMPILER_GCC_VER >= 1100
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif // !LIBC_COMPILER_IS_MSVC
for (size_t i = 0; i < Size; ++i)
diff --git a/libc/src/string/memory_utils/x86_64/inline_strlen.h b/libc/src/string/memory_utils/x86_64/inline_strlen.h
index 74b6820a50ff1..0343e22f3e58e 100644
--- a/libc/src/string/memory_utils/x86_64/inline_strlen.h
+++ b/libc/src/string/memory_utils/x86_64/inline_strlen.h
@@ -24,20 +24,20 @@ LIBC_NO_SANITIZE_OOB_ACCESS LIBC_INLINE static Mask
compare_and_mask(const Vector *block_ptr, char c);
template <typename Vector, typename Mask,
- decltype(compare_and_mask<Vector, Mask>)>
+ Mask (*CompareAndMask)(const Vector *, char)>
LIBC_NO_SANITIZE_OOB_ACCESS LIBC_INLINE static size_t
string_length_vector(const char *src) {
uintptr_t misalign_bytes = reinterpret_cast<uintptr_t>(src) % sizeof(Vector);
const Vector *block_ptr =
reinterpret_cast<const Vector *>(src - misalign_bytes);
- auto cmp = compare_and_mask<Vector, Mask>(block_ptr, 0) >> misalign_bytes;
+ auto cmp = CompareAndMask(block_ptr, 0) >> misalign_bytes;
if (cmp)
return cpp::countr_zero(cmp);
while (true) {
block_ptr++;
- cmp = compare_and_mask<Vector, Mask>(block_ptr, 0);
+ cmp = CompareAndMask(block_ptr, 0);
if (cmp)
return static_cast<size_t>(reinterpret_cast<uintptr_t>(block_ptr) -
reinterpret_cast<uintptr_t>(src) +
@@ -56,15 +56,14 @@ calculate_find_first_character_return(const unsigned char *src, Mask c_mask,
}
template <typename Vector, typename Mask,
- decltype(compare_and_mask<Vector, Mask>)>
+ Mask (*CompareAndMask)(const Vector *, char)>
LIBC_NO_SANITIZE_OOB_ACCESS LIBC_INLINE static void *
find_first_character_vector(const unsigned char *s, unsigned char c, size_t n) {
uintptr_t misalign_bytes = reinterpret_cast<uintptr_t>(s) % sizeof(Vector);
const Vector *block_ptr =
reinterpret_cast<const Vector *>(s - misalign_bytes);
- auto cmp_bytes =
- compare_and_mask<Vector, Mask>(block_ptr, c) >> misalign_bytes;
+ auto cmp_bytes = CompareAndMask(block_ptr, c) >> misalign_bytes;
if (cmp_bytes)
return calculate_find_first_character_return<Mask>(
reinterpret_cast<const unsigned char *>(block_ptr) + misalign_bytes,
@@ -73,7 +72,7 @@ find_first_character_vector(const unsigned char *s, unsigned char c, size_t n) {
for (size_t bytes_checked = sizeof(Vector) - misalign_bytes;
bytes_checked < n; bytes_checked += sizeof(Vector)) {
block_ptr++;
- cmp_bytes = compare_and_mask<Vector, Mask>(block_ptr, c);
+ cmp_bytes = CompareAndMask(block_ptr, c);
if (cmp_bytes)
return calculate_find_first_character_return<Mask>(
reinterpret_cast<const unsigned char *>(block_ptr), cmp_bytes,
diff --git a/libc/test/shared/shared_math_constexpr_test.cpp b/libc/test/shared/shared_math_constexpr_test.cpp
index 1e7ccb623fc55..821042e1dab92 100644
--- a/libc/test/shared/shared_math_constexpr_test.cpp
+++ b/libc/test/shared/shared_math_constexpr_test.cpp
@@ -258,7 +258,7 @@ static_assert(0 == [] {
float16 setpayload_x = 0.0f16;
return LIBC_NAMESPACE::shared::setpayloadf16(&setpayload_x, 0.0f16);
}());
-static_assert(0LL == LIBC_NAMESPACE::shared::llrintf16(0.0));
+static_assert(0LL == LIBC_NAMESPACE::shared::llrintf16(0.0f16));
static_assert(0LL == LIBC_NAMESPACE::shared::llroundf16(0.0f16));
static_assert(0L == LIBC_NAMESPACE::shared::lrintf16(0.0f16));
static_assert(0L == LIBC_NAMESPACE::shared::lroundf16(0.0f16));
>From 5d27ec3bf1d2f63c871385a41b764f68d9d9cf63 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Thu, 21 May 2026 13:54:23 +0000
Subject: [PATCH 7/7] Update NormalFloat constexpr annotations.
---
libc/src/__support/FPUtil/NormalFloat.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/libc/src/__support/FPUtil/NormalFloat.h b/libc/src/__support/FPUtil/NormalFloat.h
index 2da317a356405..f7d32073c74a9 100644
--- a/libc/src/__support/FPUtil/NormalFloat.h
+++ b/libc/src/__support/FPUtil/NormalFloat.h
@@ -95,7 +95,7 @@ template <typename T> struct NormalFloat {
return result;
}
- LIBC_INLINE operator T() const {
+ LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR operator T() const {
int biased_exponent = exponent + FPBits<T>::EXP_BIAS;
// Max exponent is of the form 0xFF...E. That is why -2 and not -1.
constexpr int MAX_EXPONENT_VALUE = (1 << FPBits<T>::EXP_LEN) - 2;
@@ -216,7 +216,9 @@ NormalFloat<long double>::init_from_bits(FPBits<long double> bits) {
}
}
-template <> LIBC_INLINE NormalFloat<long double>::operator long double() const {
+template <>
+LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR NormalFloat<long double>::
+operator long double() const {
using LDBits = FPBits<long double>;
int biased_exponent = exponent + LDBits::EXP_BIAS;
// Max exponent is of the form 0xFF...E. That is why -2 and not -1.
More information about the libc-commits
mailing list