Skip to content

Commit 5354681

Browse files
authored
[flang] Better folding warning due to hidden conversion (#165430)
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.
1 parent 82ecbeb commit 5354681

File tree

7 files changed

+35
-19
lines changed

7 files changed

+35
-19
lines changed

flang/include/flang/Evaluate/common.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,10 +303,16 @@ class FoldingContext {
303303
return common::ScopedSet(analyzingPDTComponentKindSelector_, true);
304304
}
305305

306+
common::Restorer<std::string> SetRealFlagWarningContext(std::string str) {
307+
return common::ScopedSet(realFlagWarningContext_, str);
308+
}
309+
306310
parser::CharBlock SaveTempName(std::string &&name) {
307311
return {*tempNames_.emplace(std::move(name)).first};
308312
}
309313

314+
void RealFlagWarnings(const RealFlags &, const char *op);
315+
310316
private:
311317
parser::ContextualMessages messages_;
312318
const common::IntrinsicTypeDefaultKinds &defaults_;
@@ -318,8 +324,8 @@ class FoldingContext {
318324
std::map<parser::CharBlock, ConstantSubscript> impliedDos_;
319325
const common::LanguageFeatureControl &languageFeatures_;
320326
std::set<std::string> &tempNames_;
327+
std::string realFlagWarningContext_;
321328
};
322329

323-
void RealFlagWarnings(FoldingContext &, const RealFlags &, const char *op);
324330
} // namespace Fortran::evaluate
325331
#endif // FORTRAN_EVALUATE_COMMON_H_

flang/lib/Evaluate/common.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,28 @@ using namespace Fortran::parser::literals;
1313

1414
namespace Fortran::evaluate {
1515

16-
void RealFlagWarnings(
17-
FoldingContext &context, const RealFlags &flags, const char *operation) {
16+
void FoldingContext::RealFlagWarnings(
17+
const RealFlags &flags, const char *operation) {
1818
static constexpr auto warning{common::UsageWarning::FoldingException};
1919
if (flags.test(RealFlag::Overflow)) {
20-
context.Warn(warning, "overflow on %s"_warn_en_US, operation);
20+
Warn(warning, "overflow on %s%s"_warn_en_US, operation,
21+
realFlagWarningContext_);
2122
}
2223
if (flags.test(RealFlag::DivideByZero)) {
2324
if (std::strcmp(operation, "division") == 0) {
24-
context.Warn(warning, "division by zero"_warn_en_US);
25+
Warn(warning, "division by zero%s"_warn_en_US, realFlagWarningContext_);
2526
} else {
26-
context.Warn(warning, "division by zero on %s"_warn_en_US, operation);
27+
Warn(warning, "division by zero on %s%s"_warn_en_US, operation,
28+
realFlagWarningContext_);
2729
}
2830
}
2931
if (flags.test(RealFlag::InvalidArgument)) {
30-
context.Warn(warning, "invalid argument on %s"_warn_en_US, operation);
32+
Warn(warning, "invalid argument on %s%s"_warn_en_US, operation,
33+
realFlagWarningContext_);
3134
}
3235
if (flags.test(RealFlag::Underflow)) {
33-
context.Warn(warning, "underflow on %s"_warn_en_US, operation);
36+
Warn(warning, "underflow on %s%s"_warn_en_US, operation,
37+
realFlagWarningContext_);
3438
}
3539
}
3640

flang/lib/Evaluate/fold-implementation.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1862,7 +1862,7 @@ Expr<TO> FoldOperation(
18621862
std::snprintf(buffer, sizeof buffer,
18631863
"INTEGER(%d) to REAL(%d) conversion", Operand::kind,
18641864
TO::kind);
1865-
RealFlagWarnings(ctx, converted.flags, buffer);
1865+
ctx.RealFlagWarnings(converted.flags, buffer);
18661866
}
18671867
return ScalarConstantToExpr(std::move(converted.value));
18681868
} else if constexpr (FromCat == TypeCategory::Real) {
@@ -1871,7 +1871,7 @@ Expr<TO> FoldOperation(
18711871
if (!converted.flags.empty()) {
18721872
std::snprintf(buffer, sizeof buffer,
18731873
"REAL(%d) to REAL(%d) conversion", Operand::kind, TO::kind);
1874-
RealFlagWarnings(ctx, converted.flags, buffer);
1874+
ctx.RealFlagWarnings(converted.flags, buffer);
18751875
}
18761876
if (ctx.targetCharacteristics().areSubnormalsFlushedToZero()) {
18771877
converted.value = converted.value.FlushSubnormalToZero();
@@ -2012,7 +2012,7 @@ Expr<T> FoldOperation(FoldingContext &context, Add<T> &&x) {
20122012
} else {
20132013
auto sum{folded->first.Add(
20142014
folded->second, context.targetCharacteristics().roundingMode())};
2015-
RealFlagWarnings(context, sum.flags, "addition");
2015+
context.RealFlagWarnings(sum.flags, "addition");
20162016
if (context.targetCharacteristics().areSubnormalsFlushedToZero()) {
20172017
sum.value = sum.value.FlushSubnormalToZero();
20182018
}
@@ -2041,7 +2041,7 @@ Expr<T> FoldOperation(FoldingContext &context, Subtract<T> &&x) {
20412041
} else {
20422042
auto difference{folded->first.Subtract(
20432043
folded->second, context.targetCharacteristics().roundingMode())};
2044-
RealFlagWarnings(context, difference.flags, "subtraction");
2044+
context.RealFlagWarnings(difference.flags, "subtraction");
20452045
if (context.targetCharacteristics().areSubnormalsFlushedToZero()) {
20462046
difference.value = difference.value.FlushSubnormalToZero();
20472047
}
@@ -2070,7 +2070,7 @@ Expr<T> FoldOperation(FoldingContext &context, Multiply<T> &&x) {
20702070
} else {
20712071
auto product{folded->first.Multiply(
20722072
folded->second, context.targetCharacteristics().roundingMode())};
2073-
RealFlagWarnings(context, product.flags, "multiplication");
2073+
context.RealFlagWarnings(product.flags, "multiplication");
20742074
if (context.targetCharacteristics().areSubnormalsFlushedToZero()) {
20752075
product.value = product.value.FlushSubnormalToZero();
20762076
}
@@ -2141,7 +2141,7 @@ Expr<T> FoldOperation(FoldingContext &context, Divide<T> &&x) {
21412141
}
21422142
}
21432143
if (!isCanonicalNaNOrInf) {
2144-
RealFlagWarnings(context, quotient.flags, "division");
2144+
context.RealFlagWarnings(quotient.flags, "division");
21452145
}
21462146
if (context.targetCharacteristics().areSubnormalsFlushedToZero()) {
21472147
quotient.value = quotient.value.FlushSubnormalToZero();
@@ -2201,7 +2201,7 @@ Expr<T> FoldOperation(FoldingContext &context, RealToIntPower<T> &&x) {
22012201
[&](auto &y) -> Expr<T> {
22022202
if (auto folded{OperandsAreConstants(x.left(), y)}) {
22032203
auto power{evaluate::IntPower(folded->first, folded->second)};
2204-
RealFlagWarnings(context, power.flags, "power with INTEGER exponent");
2204+
context.RealFlagWarnings(power.flags, "power with INTEGER exponent");
22052205
if (context.targetCharacteristics().areSubnormalsFlushedToZero()) {
22062206
power.value = power.value.FlushSubnormalToZero();
22072207
}

flang/lib/Evaluate/host.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ void HostFloatingPointEnvironment::CheckAndRestoreFloatingPointEnvironment(
140140
}
141141

142142
if (!flags_.empty()) {
143-
RealFlagWarnings(
144-
context, flags_, "evaluation of intrinsic function or operation");
143+
context.RealFlagWarnings(
144+
flags_, "evaluation of intrinsic function or operation");
145145
}
146146
errno = 0;
147147
if (fesetenv(&originalFenv_) != 0) {

flang/lib/Evaluate/intrinsics-library.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1043,14 +1043,16 @@ std::optional<HostRuntimeWrapper> GetHostRuntimeWrapper(const std::string &name,
10431043
if (const auto *hostFunction{
10441044
SearchHostRuntime(name, biggerResultType, biggerArgTypes)}) {
10451045
auto hostFolderWithChecks{AddArgumentVerifierIfAny(name, *hostFunction)};
1046-
return [hostFunction, resultType, hostFolderWithChecks](
1046+
return [hostFunction, resultType, hostFolderWithChecks, name](
10471047
FoldingContext &context, std::vector<Expr<SomeType>> &&args) {
10481048
auto nArgs{args.size()};
10491049
for (size_t i{0}; i < nArgs; ++i) {
10501050
args[i] = Fold(context,
10511051
ConvertToType(hostFunction->argumentTypes[i], std::move(args[i]))
10521052
.value());
10531053
}
1054+
auto restorer{context.SetRealFlagWarningContext(
1055+
" after folding a call to '"s + name + "'"s)};
10541056
return Fold(context,
10551057
ConvertToType(
10561058
resultType, hostFolderWithChecks(context, std::move(args)))

flang/lib/Semantics/expression.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -834,7 +834,7 @@ Constant<TYPE> ReadRealLiteral(
834834
auto valWithFlags{
835835
Scalar<TYPE>::Read(p, context.targetCharacteristics().roundingMode())};
836836
CHECK(p == source.end());
837-
RealFlagWarnings(context, valWithFlags.flags, "conversion of REAL literal");
837+
context.RealFlagWarnings(valWithFlags.flags, "conversion of REAL literal");
838838
auto value{valWithFlags.value};
839839
if (context.targetCharacteristics().areSubnormalsFlushedToZero()) {
840840
value = value.FlushSubnormalToZero();

flang/test/Evaluate/folding33.f90

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
!RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s
2+
!CHECK: warning: overflow on REAL(4) to REAL(2) conversion after folding a call to 'exp' [-Wfolding-exception]
3+
print *, exp((11.265625_2,1._2))
4+
end

0 commit comments

Comments
 (0)