[flang-commits] [flang] 553cd19 - [flang] Error recovery in bad specific MIN/MAX calls

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Thu Jun 22 06:48:13 PDT 2023


Author: Peter Klausler
Date: 2023-06-22T06:48:03-07:00
New Revision: 553cd1924d39927ef8a0889b9f643de147b9037a

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

LOG: [flang] Error recovery in bad specific MIN/MAX calls

When a specific MIN/MAX intrinsic function (e.g. MAX1) reference
has an actual argument error, ensure that a later attempt to fold
the call into a constant doesn't crash due to a missing argument.
Fixes https://github.com/llvm/llvm-project/issues/63140

Differential Revision: https://reviews.llvm.org/D153470

Added: 
    

Modified: 
    flang/lib/Evaluate/fold-implementation.h
    flang/test/Semantics/call23.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h
index 16924e9bd0c01..ad18d7ed83b1b 100644
--- a/flang/lib/Evaluate/fold-implementation.h
+++ b/flang/lib/Evaluate/fold-implementation.h
@@ -1063,26 +1063,29 @@ Expr<T> RewriteSpecificMINorMAX(
   auto &intrinsic{DEREF(std::get_if<SpecificIntrinsic>(&funcRef.proc().u))};
   // Rewrite MAX1(args) to INT(MAX(args)) and fold. Same logic for MIN1.
   // Find result type for max/min based on the arguments.
-  DynamicType resultType{args[0].value().GetType().value()};
-  auto *resultTypeArg{&args[0]};
-  for (auto j{args.size() - 1}; j > 0; --j) {
-    DynamicType type{args[j].value().GetType().value()};
-    if (type.category() == resultType.category()) {
-      if (type.kind() > resultType.kind()) {
-        resultTypeArg = &args[j];
-        resultType = type;
-      }
-    } else if (resultType.category() == TypeCategory::Integer) {
+  std::optional<DynamicType> resultType;
+  ActualArgument *resultTypeArg{nullptr};
+  for (auto j{args.size()}; j-- > 0;) {
+    if (args[j]) {
+      DynamicType type{args[j]->GetType().value()};
       // Handle mixed real/integer arguments: all the previous arguments were
       // integers and this one is real. The type of the MAX/MIN result will
       // be the one of the real argument.
-      resultTypeArg = &args[j];
-      resultType = type;
+      if (!resultType ||
+          (type.category() == resultType->category() &&
+              type.kind() > resultType->kind()) ||
+          resultType->category() == TypeCategory::Integer) {
+        resultType = type;
+        resultTypeArg = &*args[j];
+      }
     }
   }
+  if (!resultType) { // error recovery
+    return Expr<T>{std::move(funcRef)};
+  }
   intrinsic.name =
       intrinsic.name.find("max") != std::string::npos ? "max"s : "min"s;
-  intrinsic.characteristics.value().functionResult.value().SetType(resultType);
+  intrinsic.characteristics.value().functionResult.value().SetType(*resultType);
   auto insertConversion{[&](const auto &x) -> Expr<T> {
     using TR = ResultType<decltype(x)>;
     FunctionRef<TR> maxRef{std::move(funcRef.proc()), std::move(args)};

diff  --git a/flang/test/Semantics/call23.f90 b/flang/test/Semantics/call23.f90
index 2e33cb092df43..38c860ad3b516 100644
--- a/flang/test/Semantics/call23.f90
+++ b/flang/test/Semantics/call23.f90
@@ -5,6 +5,8 @@
 print *, max(a1=x,a1=1)
 !ERROR: Keyword argument 'a1=' has already been specified positionally (#1) in this procedure reference
 print *, max(x,a1=1)
+!ERROR: Keyword argument 'a1=' has already been specified positionally (#1) in this procedure reference
+print *, min1(1.,a1=2.,a2=3.)
 print *, max(a1=x,a2=0,a4=0) ! ok
 print *, max(x,0,a99=0) ! ok
 !ERROR: Argument keyword 'a06=' is not known in call to 'max'


        


More information about the flang-commits mailing list