[flang-commits] [flang] [flang] Better folding warning due to hidden conversion (PR #165430)
via flang-commits
flang-commits at lists.llvm.org
Tue Oct 28 09:27:08 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: Peter Klausler (klausler)
<details>
<summary>Changes</summary>
When folding intrinsic function calls for types like REAL(2) that don't have host math library support, we convert them to a type that has greater range and precision, call a host math library routine that does exist, and convert the result back to the original result type. The folding of this second conversion can elicit floating-point warnings (usually overflow) that are somewhat unclear to the user. Add support for adding contextual information to these warnings.
---
Full diff: https://github.com/llvm/llvm-project/pull/165430.diff
7 Files Affected:
- (modified) flang/include/flang/Evaluate/common.h (+7-1)
- (modified) flang/lib/Evaluate/common.cpp (+11-7)
- (modified) flang/lib/Evaluate/fold-implementation.h (+7-7)
- (modified) flang/lib/Evaluate/host.cpp (+2-2)
- (modified) flang/lib/Evaluate/intrinsics-library.cpp (+3-1)
- (modified) flang/lib/Semantics/expression.cpp (+1-1)
- (added) flang/test/Evaluate/folding33.f90 (+4)
``````````diff
diff --git a/flang/include/flang/Evaluate/common.h b/flang/include/flang/Evaluate/common.h
index 0263f15d4215e..3d220afa71718 100644
--- a/flang/include/flang/Evaluate/common.h
+++ b/flang/include/flang/Evaluate/common.h
@@ -303,10 +303,16 @@ class FoldingContext {
return common::ScopedSet(analyzingPDTComponentKindSelector_, true);
}
+ common::Restorer<std::string> SetRealFlagWarningContext(std::string str) {
+ return common::ScopedSet(realFlagWarningContext_, str);
+ }
+
parser::CharBlock SaveTempName(std::string &&name) {
return {*tempNames_.emplace(std::move(name)).first};
}
+ void RealFlagWarnings(const RealFlags &, const char *op);
+
private:
parser::ContextualMessages messages_;
const common::IntrinsicTypeDefaultKinds &defaults_;
@@ -318,8 +324,8 @@ class FoldingContext {
std::map<parser::CharBlock, ConstantSubscript> impliedDos_;
const common::LanguageFeatureControl &languageFeatures_;
std::set<std::string> &tempNames_;
+ std::string realFlagWarningContext_;
};
-void RealFlagWarnings(FoldingContext &, const RealFlags &, const char *op);
} // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_COMMON_H_
diff --git a/flang/lib/Evaluate/common.cpp b/flang/lib/Evaluate/common.cpp
index 46c75a5c2ee44..ed6a0ef93b0db 100644
--- a/flang/lib/Evaluate/common.cpp
+++ b/flang/lib/Evaluate/common.cpp
@@ -13,24 +13,28 @@ using namespace Fortran::parser::literals;
namespace Fortran::evaluate {
-void RealFlagWarnings(
- FoldingContext &context, const RealFlags &flags, const char *operation) {
+void FoldingContext::RealFlagWarnings(
+ const RealFlags &flags, const char *operation) {
static constexpr auto warning{common::UsageWarning::FoldingException};
if (flags.test(RealFlag::Overflow)) {
- context.Warn(warning, "overflow on %s"_warn_en_US, operation);
+ Warn(warning, "overflow on %s%s"_warn_en_US, operation,
+ realFlagWarningContext_);
}
if (flags.test(RealFlag::DivideByZero)) {
if (std::strcmp(operation, "division") == 0) {
- context.Warn(warning, "division by zero"_warn_en_US);
+ Warn(warning, "division by zero%s"_warn_en_US, realFlagWarningContext_);
} else {
- context.Warn(warning, "division by zero on %s"_warn_en_US, operation);
+ Warn(warning, "division by zero on %s%s"_warn_en_US, operation,
+ realFlagWarningContext_);
}
}
if (flags.test(RealFlag::InvalidArgument)) {
- context.Warn(warning, "invalid argument on %s"_warn_en_US, operation);
+ Warn(warning, "invalid argument on %s%s"_warn_en_US, operation,
+ realFlagWarningContext_);
}
if (flags.test(RealFlag::Underflow)) {
- context.Warn(warning, "underflow on %s"_warn_en_US, operation);
+ Warn(warning, "underflow on %s%s"_warn_en_US, operation,
+ realFlagWarningContext_);
}
}
diff --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h
index 3fdf3a6f38848..52ea627d0bbe4 100644
--- a/flang/lib/Evaluate/fold-implementation.h
+++ b/flang/lib/Evaluate/fold-implementation.h
@@ -1862,7 +1862,7 @@ Expr<TO> FoldOperation(
std::snprintf(buffer, sizeof buffer,
"INTEGER(%d) to REAL(%d) conversion", Operand::kind,
TO::kind);
- RealFlagWarnings(ctx, converted.flags, buffer);
+ ctx.RealFlagWarnings(converted.flags, buffer);
}
return ScalarConstantToExpr(std::move(converted.value));
} else if constexpr (FromCat == TypeCategory::Real) {
@@ -1871,7 +1871,7 @@ Expr<TO> FoldOperation(
if (!converted.flags.empty()) {
std::snprintf(buffer, sizeof buffer,
"REAL(%d) to REAL(%d) conversion", Operand::kind, TO::kind);
- RealFlagWarnings(ctx, converted.flags, buffer);
+ ctx.RealFlagWarnings(converted.flags, buffer);
}
if (ctx.targetCharacteristics().areSubnormalsFlushedToZero()) {
converted.value = converted.value.FlushSubnormalToZero();
@@ -2012,7 +2012,7 @@ Expr<T> FoldOperation(FoldingContext &context, Add<T> &&x) {
} else {
auto sum{folded->first.Add(
folded->second, context.targetCharacteristics().roundingMode())};
- RealFlagWarnings(context, sum.flags, "addition");
+ context.RealFlagWarnings(sum.flags, "addition");
if (context.targetCharacteristics().areSubnormalsFlushedToZero()) {
sum.value = sum.value.FlushSubnormalToZero();
}
@@ -2041,7 +2041,7 @@ Expr<T> FoldOperation(FoldingContext &context, Subtract<T> &&x) {
} else {
auto difference{folded->first.Subtract(
folded->second, context.targetCharacteristics().roundingMode())};
- RealFlagWarnings(context, difference.flags, "subtraction");
+ context.RealFlagWarnings(difference.flags, "subtraction");
if (context.targetCharacteristics().areSubnormalsFlushedToZero()) {
difference.value = difference.value.FlushSubnormalToZero();
}
@@ -2070,7 +2070,7 @@ Expr<T> FoldOperation(FoldingContext &context, Multiply<T> &&x) {
} else {
auto product{folded->first.Multiply(
folded->second, context.targetCharacteristics().roundingMode())};
- RealFlagWarnings(context, product.flags, "multiplication");
+ context.RealFlagWarnings(product.flags, "multiplication");
if (context.targetCharacteristics().areSubnormalsFlushedToZero()) {
product.value = product.value.FlushSubnormalToZero();
}
@@ -2141,7 +2141,7 @@ Expr<T> FoldOperation(FoldingContext &context, Divide<T> &&x) {
}
}
if (!isCanonicalNaNOrInf) {
- RealFlagWarnings(context, quotient.flags, "division");
+ context.RealFlagWarnings(quotient.flags, "division");
}
if (context.targetCharacteristics().areSubnormalsFlushedToZero()) {
quotient.value = quotient.value.FlushSubnormalToZero();
@@ -2201,7 +2201,7 @@ Expr<T> FoldOperation(FoldingContext &context, RealToIntPower<T> &&x) {
[&](auto &y) -> Expr<T> {
if (auto folded{OperandsAreConstants(x.left(), y)}) {
auto power{evaluate::IntPower(folded->first, folded->second)};
- RealFlagWarnings(context, power.flags, "power with INTEGER exponent");
+ context.RealFlagWarnings(power.flags, "power with INTEGER exponent");
if (context.targetCharacteristics().areSubnormalsFlushedToZero()) {
power.value = power.value.FlushSubnormalToZero();
}
diff --git a/flang/lib/Evaluate/host.cpp b/flang/lib/Evaluate/host.cpp
index 25409ac3418b8..bf0249647162a 100644
--- a/flang/lib/Evaluate/host.cpp
+++ b/flang/lib/Evaluate/host.cpp
@@ -140,8 +140,8 @@ void HostFloatingPointEnvironment::CheckAndRestoreFloatingPointEnvironment(
}
if (!flags_.empty()) {
- RealFlagWarnings(
- context, flags_, "evaluation of intrinsic function or operation");
+ context.RealFlagWarnings(
+ flags_, "evaluation of intrinsic function or operation");
}
errno = 0;
if (fesetenv(&originalFenv_) != 0) {
diff --git a/flang/lib/Evaluate/intrinsics-library.cpp b/flang/lib/Evaluate/intrinsics-library.cpp
index 9820aa3d2ea3d..d8af5246fabdd 100644
--- a/flang/lib/Evaluate/intrinsics-library.cpp
+++ b/flang/lib/Evaluate/intrinsics-library.cpp
@@ -1043,7 +1043,7 @@ std::optional<HostRuntimeWrapper> GetHostRuntimeWrapper(const std::string &name,
if (const auto *hostFunction{
SearchHostRuntime(name, biggerResultType, biggerArgTypes)}) {
auto hostFolderWithChecks{AddArgumentVerifierIfAny(name, *hostFunction)};
- return [hostFunction, resultType, hostFolderWithChecks](
+ return [hostFunction, resultType, hostFolderWithChecks, name](
FoldingContext &context, std::vector<Expr<SomeType>> &&args) {
auto nArgs{args.size()};
for (size_t i{0}; i < nArgs; ++i) {
@@ -1051,6 +1051,8 @@ std::optional<HostRuntimeWrapper> GetHostRuntimeWrapper(const std::string &name,
ConvertToType(hostFunction->argumentTypes[i], std::move(args[i]))
.value());
}
+ auto restorer{context.SetRealFlagWarningContext(
+ " after folding a call to '"s + name + "'"s)};
return Fold(context,
ConvertToType(
resultType, hostFolderWithChecks(context, std::move(args)))
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 32aa6b1e0aa1d..c8167fd34f666 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -834,7 +834,7 @@ Constant<TYPE> ReadRealLiteral(
auto valWithFlags{
Scalar<TYPE>::Read(p, context.targetCharacteristics().roundingMode())};
CHECK(p == source.end());
- RealFlagWarnings(context, valWithFlags.flags, "conversion of REAL literal");
+ context.RealFlagWarnings(valWithFlags.flags, "conversion of REAL literal");
auto value{valWithFlags.value};
if (context.targetCharacteristics().areSubnormalsFlushedToZero()) {
value = value.FlushSubnormalToZero();
diff --git a/flang/test/Evaluate/folding33.f90 b/flang/test/Evaluate/folding33.f90
new file mode 100644
index 0000000000000..fb5a23cf1f209
--- /dev/null
+++ b/flang/test/Evaluate/folding33.f90
@@ -0,0 +1,4 @@
+!RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s
+!CHECK: warning: overflow on REAL(4) to REAL(2) conversion after folding a call to 'exp' [-Wfolding-exception]
+print *, exp((11.265625_2,1._2))
+end
``````````
</details>
https://github.com/llvm/llvm-project/pull/165430
More information about the flang-commits
mailing list