[flang-commits] [flang] a280d30 - [flang] Emit warnings when results of folding some integer intrinsics overflow

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Sun Oct 30 11:03:32 PDT 2022


Author: Peter Klausler
Date: 2022-10-30T11:03:18-07:00
New Revision: a280d3000b58d94161c92a688e820c0d59e889e4

URL: https://github.com/llvm/llvm-project/commit/a280d3000b58d94161c92a688e820c0d59e889e4
DIFF: https://github.com/llvm/llvm-project/commit/a280d3000b58d94161c92a688e820c0d59e889e4.diff

LOG: [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

Added: 
    

Modified: 
    flang/lib/Evaluate/fold-integer.cpp
    flang/test/Evaluate/folding05.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Evaluate/fold-integer.cpp b/flang/lib/Evaluate/fold-integer.cpp
index 9bb31a0165825..3ef3b957e850e 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
index 3be3904ccab51..f876a56691b83 100644
Binary files a/flang/test/Evaluate/folding05.f90 and b/flang/test/Evaluate/folding05.f90 
diff er


        


More information about the flang-commits mailing list