diff options
| author | Peter Klausler <pklausler@nvidia.com> | 2022-10-13 17:14:20 -0700 |
|---|---|---|
| committer | Peter Klausler <pklausler@nvidia.com> | 2022-10-30 11:03:18 -0700 |
| commit | a280d3000b58d94161c92a688e820c0d59e889e4 (patch) | |
| tree | 84e525e70181ad5583b4617f5fed9f7af0154b35 | |
| parent | 35a1161c241f39e82de1bc23d43c5faffd9f24b4 (diff) | |
| download | llvm-a280d3000b58d94161c92a688e820c0d59e889e4.tar.gz | |
[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
| -rw-r--r-- | flang/lib/Evaluate/fold-integer.cpp | 75 | ||||
| -rw-r--r-- | 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 9bb31a016582..3ef3b957e850 100644 --- a/flang/lib/Evaluate/fold-integer.cpp +++ b/flang/lib/Evaluate/fold-integer.cpp @@ -246,12 +246,21 @@ static Expr<T> FoldCount(FoldingContext &context, FunctionRef<T> &&ref) { : Folder<LogicalResult>{context}.Folding(arg[0])}) { std::optional<int> dim; if (CheckReductionDIM(dim, context, arg, 1, mask->Rank())) { - auto accumulator{[&](Scalar<T> &element, const ConstantSubscripts &at) { - if (mask->At(at).IsTrue()) { - element = element.AddSigned(Scalar<T>{1}).value; - } - }}; - return Expr<T>{DoReduction<T>(*mask, dim, Scalar<T>{}, accumulator)}; + bool overflow{false}; + auto accumulator{ + [&mask, &overflow](Scalar<T> &element, const ConstantSubscripts &at) { + if (mask->At(at).IsTrue()) { + auto incremented{element.AddSigned(Scalar<T>{1})}; + overflow |= incremented.overflow; + element = incremented.value; + } + }}; + Constant<T> result{DoReduction<T>(*mask, dim, Scalar<T>{}, accumulator)}; + if (overflow) { + context.messages().Say( + "Result of intrinsic function COUNT overflows its result type"_warn_en_US); + } + return Expr<T>{std::move(result)}; } } return Expr<T>{std::move(ref)}; @@ -494,6 +503,15 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction( auto *intrinsic{std::get_if<SpecificIntrinsic>(&funcRef.proc().u)}; CHECK(intrinsic); std::string name{intrinsic->name}; + auto FromInt64{[&name, &context](std::int64_t n) { + Scalar<T> 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<T, T>(context, std::move(funcRef), ScalarFunc<T, T>([&context](const Scalar<T> &i) -> Scalar<T> { @@ -592,12 +610,13 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction( name); } else { return common::visit( - [&funcRef, &context](const auto &str) -> Expr<T> { + [&funcRef, &name, &context, &FromInt64]( + const auto &str) -> Expr<T> { using Char = typename std::decay_t<decltype(str)>::Result; return FoldElementalIntrinsic<T, Char>(context, std::move(funcRef), - ScalarFunc<T, Char>([](const Scalar<Char> &c) { - return Scalar<T>{CharacterUtils<Char::kind>::ICHAR(c)}; + ScalarFunc<T, Char>([&FromInt64](const Scalar<Char> &c) { + return FromInt64(CharacterUtils<Char::kind>::ICHAR(c)); })); }, someChar->u); @@ -676,27 +695,29 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction( return FoldElementalIntrinsic<T, TC, TC, LogicalResult>(context, std::move(funcRef), ScalarFunc<T, TC, TC, LogicalResult>{ - [&name](const Scalar<TC> &str, const Scalar<TC> &other, - const Scalar<LogicalResult> &back) -> Scalar<T> { - return name == "index" - ? CharacterUtils<TC::kind>::INDEX( - str, other, back.IsTrue()) - : name == "scan" ? CharacterUtils<TC::kind>::SCAN( - str, other, back.IsTrue()) - : CharacterUtils<TC::kind>::VERIFY( - str, other, back.IsTrue()); + [&name, &FromInt64](const Scalar<TC> &str, + const Scalar<TC> &other, + const Scalar<LogicalResult> &back) { + return FromInt64(name == "index" + ? CharacterUtils<TC::kind>::INDEX( + str, other, back.IsTrue()) + : name == "scan" + ? CharacterUtils<TC::kind>::SCAN( + str, other, back.IsTrue()) + : CharacterUtils<TC::kind>::VERIFY( + str, other, back.IsTrue())); }}); } else { return FoldElementalIntrinsic<T, TC, TC>(context, std::move(funcRef), ScalarFunc<T, TC, TC>{ - [&name](const Scalar<TC> &str, - const Scalar<TC> &other) -> Scalar<T> { - return name == "index" - ? CharacterUtils<TC::kind>::INDEX(str, other) - : name == "scan" - ? CharacterUtils<TC::kind>::SCAN(str, other) - : CharacterUtils<TC::kind>::VERIFY(str, other); + [&name, &FromInt64]( + const Scalar<TC> &str, const Scalar<TC> &other) { + return FromInt64(name == "index" + ? CharacterUtils<TC::kind>::INDEX(str, other) + : name == "scan" + ? CharacterUtils<TC::kind>::SCAN(str, other) + : CharacterUtils<TC::kind>::VERIFY(str, other)); }}); } }, @@ -835,8 +856,8 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction( [&](const auto &kch) -> Expr<T> { using TC = typename std::decay_t<decltype(kch)>::Result; return FoldElementalIntrinsic<T, TC>(context, std::move(funcRef), - ScalarFunc<T, TC>{[](const Scalar<TC> &str) -> Scalar<T> { - return CharacterUtils<TC::kind>::LEN_TRIM(str); + ScalarFunc<T, TC>{[&FromInt64](const Scalar<TC> &str) { + return FromInt64(CharacterUtils<TC::kind>::LEN_TRIM(str)); }}); }, charExpr->u); diff --git a/flang/test/Evaluate/folding05.f90 b/flang/test/Evaluate/folding05.f90 Binary files differindex 3be3904ccab5..f876a56691b8 100644 --- a/flang/test/Evaluate/folding05.f90 +++ b/flang/test/Evaluate/folding05.f90 |
