[clang] [llvm] [APFloat] Signal overflow when rounding delivers the largest finite value (PR #220020)
Jack Royer via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 16 01:10:48 PDT 2026
https://github.com/Garfield1002 updated https://github.com/llvm/llvm-project/pull/220020
>From 118c1cae5afe9dafd4a9d2f1a0ecbbcfda161f2e Mon Sep 17 00:00:00 2001
From: Jack Royer <jack.royer.23 at gmail.com>
Date: Mon, 31 Aug 2026 17:57:18 +0200
Subject: [PATCH 1/2] [APFloat] Signal overflow when rounding delivers the
largest finite value
---
llvm/lib/Support/APFloat.cpp | 9 ++++++++-
llvm/unittests/ADT/APFloatTest.cpp | 18 +++++++++---------
2 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index 59a6ba3867d40..f93b2ae1e2f32 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -1590,7 +1590,14 @@ APFloat::opStatus IEEEFloat::handleOverflow(roundingMode rounding_mode) {
semantics->nanEncoding == fltNanEncoding::AllOnes)
APInt::tcClearBit(significandParts(), 0);
- return opInexact;
+ /* The overflow is still signaled.
+ IEEE 754-2019 7.4 raises it if the largest finite number is exceeded in
+ magnitude by what would have been the result, even if we rounded away from
+ infinity it does not make the overflow disappear.
+ Formats without a non-finite encoding are left alone. */
+ if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::FiniteOnly)
+ return opInexact;
+ return static_cast<opStatus>(opOverflow | opInexact);
}
/* Returns TRUE if, when truncating the current number, with BIT the
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index e161071e63af4..fd3131a6a8bb5 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -3973,9 +3973,9 @@ TEST(APFloatTest, multiply) {
{MaxQuad, MaxQuad, "inf", OverflowStatus, APFloat::fcInfinity,
APFloat::rmTowardPositive},
{MaxQuad, MaxQuad, "0x1.ffffffffffffffffffffffffffffp+16383",
- APFloat::opInexact, APFloat::fcNormal, APFloat::rmTowardNegative},
+ OverflowStatus, APFloat::fcNormal, APFloat::rmTowardNegative},
{MaxQuad, MaxQuad, "0x1.ffffffffffffffffffffffffffffp+16383",
- APFloat::opInexact, APFloat::fcNormal, APFloat::rmTowardZero},
+ OverflowStatus, APFloat::fcNormal, APFloat::rmTowardZero},
{MaxQuad, MaxQuad, "inf", OverflowStatus, APFloat::fcInfinity,
APFloat::rmNearestTiesToAway},
@@ -4253,11 +4253,11 @@ TEST(APFloatTest, divide) {
{MaxQuad, NMinQuad, "-inf", OverflowStatus, APFloat::fcInfinity,
APFloat::rmNearestTiesToEven},
{MaxQuad, NMinQuad, "-0x1.ffffffffffffffffffffffffffffp+16383",
- APFloat::opInexact, APFloat::fcNormal, APFloat::rmTowardPositive},
+ OverflowStatus, APFloat::fcNormal, APFloat::rmTowardPositive},
{MaxQuad, NMinQuad, "-inf", OverflowStatus, APFloat::fcInfinity,
APFloat::rmTowardNegative},
{MaxQuad, NMinQuad, "-0x1.ffffffffffffffffffffffffffffp+16383",
- APFloat::opInexact, APFloat::fcNormal, APFloat::rmTowardZero},
+ OverflowStatus, APFloat::fcNormal, APFloat::rmTowardZero},
{MaxQuad, NMinQuad, "-inf", OverflowStatus, APFloat::fcInfinity,
APFloat::rmNearestTiesToAway},
@@ -8361,9 +8361,9 @@ TEST(APFloatTest, Float8E4M3FNAdd) {
{QNaN, FromStr("-448"), "NaN", APFloat::opOK, APFloat::fcNaN},
{FromStr("448"), FromStr("-32"), "416", APFloat::opOK, APFloat::fcNormal},
{FromStr("448"), FromStr("0"), "448", APFloat::opOK, APFloat::fcNormal},
- {FromStr("448"), FromStr("32"), "448", APFloat::opInexact,
+ {FromStr("448"), FromStr("32"), "448", APFloat::opOverflow | APFloat::opInexact,
APFloat::fcNormal, APFloat::rmTowardZero},
- {FromStr("448"), FromStr("448"), "448", APFloat::opInexact,
+ {FromStr("448"), FromStr("448"), "448", APFloat::opOverflow | APFloat::opInexact,
APFloat::fcNormal, APFloat::rmTowardZero},
};
@@ -8706,7 +8706,7 @@ TEST(APFloatTest, Float8E5M2FNUZAdd) {
APFloat::fcNormal},
{FromStr("57344"), FromStr("4096"), "57344", APFloat::opInexact,
APFloat::fcNormal, APFloat::rmTowardZero},
- {FromStr("57344"), FromStr("57344"), "57344", APFloat::opInexact,
+ {FromStr("57344"), FromStr("57344"), "57344", APFloat::opOverflow | APFloat::opInexact,
APFloat::fcNormal, APFloat::rmTowardZero},
};
@@ -8902,9 +8902,9 @@ TEST(APFloatTest, Float8E4M3FNUZAdd) {
{QNaN, FromStr("-240"), "NaN", APFloat::opOK, APFloat::fcNaN},
{FromStr("240"), FromStr("-16"), "224", APFloat::opOK, APFloat::fcNormal},
{FromStr("240"), FromStr("0"), "240", APFloat::opOK, APFloat::fcNormal},
- {FromStr("240"), FromStr("32"), "240", APFloat::opInexact,
+ {FromStr("240"), FromStr("32"), "240", APFloat::opOverflow | APFloat::opInexact,
APFloat::fcNormal, APFloat::rmTowardZero},
- {FromStr("240"), FromStr("240"), "240", APFloat::opInexact,
+ {FromStr("240"), FromStr("240"), "240", APFloat::opOverflow | APFloat::opInexact,
APFloat::fcNormal, APFloat::rmTowardZero},
};
>From c3ade876dce8b05ba5fe1e9f2abc4912664bce00 Mon Sep 17 00:00:00 2001
From: Jack Royer <jack.royer.23 at gmail.com>
Date: Wed, 16 Sep 2026 10:10:17 +0200
Subject: [PATCH 2/2] address review
---
clang/test/Sema/warn-literal-range.c | 5 ++++-
llvm/lib/Support/APFloat.cpp | 6 ++----
llvm/unittests/ADT/APFloatTest.cpp | 27 ++++++++++++++++-----------
3 files changed, 22 insertions(+), 16 deletions(-)
diff --git a/clang/test/Sema/warn-literal-range.c b/clang/test/Sema/warn-literal-range.c
index 8014b058bd886..e7d8956e553e3 100644
--- a/clang/test/Sema/warn-literal-range.c
+++ b/clang/test/Sema/warn-literal-range.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c99 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c99 -fexperimental-strict-floating-point -verify %s
float f0 = 0.42f; // no-warning
@@ -35,3 +35,6 @@ long double ld3 = 0x0.42p42L; // no-warning
long double ld4 = 0x0.42p-42000L; // expected-warning {{magnitude of floating-point constant too small for type 'long double'; minimum is 3.64519953188247460253E-4951}}
long double ld5 = 0x0.42p+42000L; // expected-warning {{magnitude of floating-point constant too large for type 'long double'; maximum is 1.18973149535723176502E+4932}}
+
+#pragma STDC FENV_ROUND FE_TOWARDZERO // {{pragma STDC FENV_ROUND is not supported}}
+double d6 = 1e400; // expected-warning {{magnitude of floating-point constant too large for type 'double'; maximum is 1.7976931348623157E+308}}
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index f93b2ae1e2f32..139af3ba9e1ea 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -5581,10 +5581,8 @@ APFloat::opStatus DoubleAPFloat::handleOverflow(roundingMode RM) {
default:
llvm_unreachable("Invalid rounding mode found");
}
- opStatus S = opInexact;
- if (!getFirst().isFinite())
- S = static_cast<opStatus>(S | opOverflow);
- return S;
+
+ return static_cast<opStatus>(opInexact | opOverflow);
}
APFloat::opStatus DoubleAPFloat::convertFromUnsignedParts(
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index fd3131a6a8bb5..f290a870d04d0 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -7582,7 +7582,7 @@ TEST(APFloatTest, PPCDoubleDoubleConvertFromAPIntEnormous) {
EXPECT_EQ(ConvertFromStatus, APFloat::opInexact | APFloat::opOverflow);
} else {
EXPECT_EQ(F, Largest);
- EXPECT_EQ(ConvertFromStatus, APFloat::opInexact);
+ EXPECT_EQ(ConvertFromStatus, APFloat::opInexact | APFloat::opOverflow);
}
}
@@ -8361,10 +8361,12 @@ TEST(APFloatTest, Float8E4M3FNAdd) {
{QNaN, FromStr("-448"), "NaN", APFloat::opOK, APFloat::fcNaN},
{FromStr("448"), FromStr("-32"), "416", APFloat::opOK, APFloat::fcNormal},
{FromStr("448"), FromStr("0"), "448", APFloat::opOK, APFloat::fcNormal},
- {FromStr("448"), FromStr("32"), "448", APFloat::opOverflow | APFloat::opInexact,
- APFloat::fcNormal, APFloat::rmTowardZero},
- {FromStr("448"), FromStr("448"), "448", APFloat::opOverflow | APFloat::opInexact,
- APFloat::fcNormal, APFloat::rmTowardZero},
+ {FromStr("448"), FromStr("32"), "448",
+ APFloat::opOverflow | APFloat::opInexact, APFloat::fcNormal,
+ APFloat::rmTowardZero},
+ {FromStr("448"), FromStr("448"), "448",
+ APFloat::opOverflow | APFloat::opInexact, APFloat::fcNormal,
+ APFloat::rmTowardZero},
};
for (size_t i = 0; i < std::size(AdditionTests); ++i) {
@@ -8706,8 +8708,9 @@ TEST(APFloatTest, Float8E5M2FNUZAdd) {
APFloat::fcNormal},
{FromStr("57344"), FromStr("4096"), "57344", APFloat::opInexact,
APFloat::fcNormal, APFloat::rmTowardZero},
- {FromStr("57344"), FromStr("57344"), "57344", APFloat::opOverflow | APFloat::opInexact,
- APFloat::fcNormal, APFloat::rmTowardZero},
+ {FromStr("57344"), FromStr("57344"), "57344",
+ APFloat::opOverflow | APFloat::opInexact, APFloat::fcNormal,
+ APFloat::rmTowardZero},
};
for (size_t i = 0; i < std::size(AdditionTests); ++i) {
@@ -8902,10 +8905,12 @@ TEST(APFloatTest, Float8E4M3FNUZAdd) {
{QNaN, FromStr("-240"), "NaN", APFloat::opOK, APFloat::fcNaN},
{FromStr("240"), FromStr("-16"), "224", APFloat::opOK, APFloat::fcNormal},
{FromStr("240"), FromStr("0"), "240", APFloat::opOK, APFloat::fcNormal},
- {FromStr("240"), FromStr("32"), "240", APFloat::opOverflow | APFloat::opInexact,
- APFloat::fcNormal, APFloat::rmTowardZero},
- {FromStr("240"), FromStr("240"), "240", APFloat::opOverflow | APFloat::opInexact,
- APFloat::fcNormal, APFloat::rmTowardZero},
+ {FromStr("240"), FromStr("32"), "240",
+ APFloat::opOverflow | APFloat::opInexact, APFloat::fcNormal,
+ APFloat::rmTowardZero},
+ {FromStr("240"), FromStr("240"), "240",
+ APFloat::opOverflow | APFloat::opInexact, APFloat::fcNormal,
+ APFloat::rmTowardZero},
};
for (size_t i = 0; i < std::size(AdditionTests); ++i) {
More information about the cfe-commits
mailing list