From a280d3000b58d94161c92a688e820c0d59e889e4 Mon Sep 17 00:00:00 2001 From: Peter Klausler Date: Thu, 13 Oct 2022 17:14:20 -0700 Subject: [PATCH] [flang] Emit warnings when results of folding some integer intrinsics overflow When the compile-time result value of a reference to an integer-valued intrinsic function COUNT, ICHAR, IACHAR, INDEX, SCAN, or VERIFY cannot be represented in the selected result kind, emit a warning. Differential Revision: https://reviews.llvm.org/D136974 --- flang/lib/Evaluate/fold-integer.cpp | 75 +++++++++++++++++++++++------------- flang/test/Evaluate/folding05.f90 | Bin 10212 -> 10393 bytes 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/flang/lib/Evaluate/fold-integer.cpp b/flang/lib/Evaluate/fold-integer.cpp index 9bb31a0..3ef3b95 100644 --- a/flang/lib/Evaluate/fold-integer.cpp +++ b/flang/lib/Evaluate/fold-integer.cpp @@ -246,12 +246,21 @@ static Expr FoldCount(FoldingContext &context, FunctionRef &&ref) { : Folder{context}.Folding(arg[0])}) { std::optional dim; if (CheckReductionDIM(dim, context, arg, 1, mask->Rank())) { - auto accumulator{[&](Scalar &element, const ConstantSubscripts &at) { - if (mask->At(at).IsTrue()) { - element = element.AddSigned(Scalar{1}).value; - } - }}; - return Expr{DoReduction(*mask, dim, Scalar{}, accumulator)}; + bool overflow{false}; + auto accumulator{ + [&mask, &overflow](Scalar &element, const ConstantSubscripts &at) { + if (mask->At(at).IsTrue()) { + auto incremented{element.AddSigned(Scalar{1})}; + overflow |= incremented.overflow; + element = incremented.value; + } + }}; + Constant result{DoReduction(*mask, dim, Scalar{}, accumulator)}; + if (overflow) { + context.messages().Say( + "Result of intrinsic function COUNT overflows its result type"_warn_en_US); + } + return Expr{std::move(result)}; } } return Expr{std::move(ref)}; @@ -494,6 +503,15 @@ Expr> FoldIntrinsicFunction( auto *intrinsic{std::get_if(&funcRef.proc().u)}; CHECK(intrinsic); std::string name{intrinsic->name}; + auto FromInt64{[&name, &context](std::int64_t n) { + Scalar result{n}; + if (result.ToInt64() != n) { + context.messages().Say( + "Result of intrinsic function '%s' (%jd) overflows its result type"_warn_en_US, + name, std::intmax_t{n}); + } + return result; + }}; if (name == "abs") { // incl. babs, iiabs, jiaabs, & kiabs return FoldElementalIntrinsic(context, std::move(funcRef), ScalarFunc([&context](const Scalar &i) -> Scalar { @@ -592,12 +610,13 @@ Expr> FoldIntrinsicFunction( name); } else { return common::visit( - [&funcRef, &context](const auto &str) -> Expr { + [&funcRef, &name, &context, &FromInt64]( + const auto &str) -> Expr { using Char = typename std::decay_t::Result; return FoldElementalIntrinsic(context, std::move(funcRef), - ScalarFunc([](const Scalar &c) { - return Scalar{CharacterUtils::ICHAR(c)}; + ScalarFunc([&FromInt64](const Scalar &c) { + return FromInt64(CharacterUtils::ICHAR(c)); })); }, someChar->u); @@ -676,27 +695,29 @@ Expr> FoldIntrinsicFunction( return FoldElementalIntrinsic(context, std::move(funcRef), ScalarFunc{ - [&name](const Scalar &str, const Scalar &other, - const Scalar &back) -> Scalar { - return name == "index" - ? CharacterUtils::INDEX( - str, other, back.IsTrue()) - : name == "scan" ? CharacterUtils::SCAN( - str, other, back.IsTrue()) - : CharacterUtils::VERIFY( - str, other, back.IsTrue()); + [&name, &FromInt64](const Scalar &str, + const Scalar &other, + const Scalar &back) { + return FromInt64(name == "index" + ? CharacterUtils::INDEX( + str, other, back.IsTrue()) + : name == "scan" + ? CharacterUtils::SCAN( + str, other, back.IsTrue()) + : CharacterUtils::VERIFY( + str, other, back.IsTrue())); }}); } else { return FoldElementalIntrinsic(context, std::move(funcRef), ScalarFunc{ - [&name](const Scalar &str, - const Scalar &other) -> Scalar { - return name == "index" - ? CharacterUtils::INDEX(str, other) - : name == "scan" - ? CharacterUtils::SCAN(str, other) - : CharacterUtils::VERIFY(str, other); + [&name, &FromInt64]( + const Scalar &str, const Scalar &other) { + return FromInt64(name == "index" + ? CharacterUtils::INDEX(str, other) + : name == "scan" + ? CharacterUtils::SCAN(str, other) + : CharacterUtils::VERIFY(str, other)); }}); } }, @@ -835,8 +856,8 @@ Expr> FoldIntrinsicFunction( [&](const auto &kch) -> Expr { using TC = typename std::decay_t::Result; return FoldElementalIntrinsic(context, std::move(funcRef), - ScalarFunc{[](const Scalar &str) -> Scalar { - return CharacterUtils::LEN_TRIM(str); + ScalarFunc{[&FromInt64](const Scalar &str) { + return FromInt64(CharacterUtils::LEN_TRIM(str)); }}); }, charExpr->u); diff --git a/flang/test/Evaluate/folding05.f90 b/flang/test/Evaluate/folding05.f90 index 3be3904ccab5159aa04ab45f136913df95192186..f876a56691b83f50f89da658ed80926d7f84755c 100644 GIT binary patch delta 170 zcmaFjKQnN{E;dQUaK|7&D~0mJqP)z!bSs6R)Z)^d5{3MY2$IiACxP8b+q3 znhN=4sYPiy`Q^n5nI**vMG%E0l?ADjCo;=zzRI?c5wB@_2-6Hr%uOte%}gu_89I?8 GSRMd;UpcP; delta 29 kcmbOk_{4w1F1E=b>