[flang-commits] [flang] aaea4e3 - [flang] Add more diagnostic for MAX/MIN intrinsic

Kelvin Li via flang-commits flang-commits at lists.llvm.org
Fri Nov 18 11:41:46 PST 2022


Author: Kelvin Li
Date: 2022-11-18T14:37:37-05:00
New Revision: aaea4e38aba15617ccf08c5d40fb384f6cea1ea8

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

LOG: [flang] Add more diagnostic for MAX/MIN intrinsic

Fix https://github.com/llvm/llvm-project/issues/56303

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

Added: 
    

Modified: 
    flang/lib/Evaluate/intrinsics.cpp
    flang/test/Semantics/call23.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index 935586b118b17..0c4206bfacc97 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -1462,6 +1462,37 @@ static bool CheckMaxMinArgument(std::optional<parser::CharBlock> keyword,
   return true;
 }
 
+static void CheckMaxMinA1A2Argument(const ActualArguments &arguments,
+    std::set<parser::CharBlock> &set, parser::ContextualMessages &messages) {
+  parser::CharBlock kwA1{"a1", 2};
+  parser::CharBlock kwA2{"a2", 2};
+  bool missingA1{set.find(kwA1) == set.end()};
+  bool missingA2{set.find(kwA2) == set.end()};
+
+  if (arguments.size() > 1) {
+    if (arguments.at(0)->keyword()) {
+      // If the keyword is specified in the first argument, the following
+      // arguments must have the keywords.
+      if (missingA1 && missingA2) {
+        messages.Say("missing mandatory '%s=' and '%s=' arguments"_err_en_US,
+            kwA1.ToString(), kwA2.ToString());
+      } else if (missingA1 && !missingA2) {
+        messages.Say(
+            "missing mandatory '%s=' argument"_err_en_US, kwA1.ToString());
+      } else if (!missingA1 && missingA2) {
+        messages.Say(
+            "missing mandatory '%s=' argument"_err_en_US, kwA2.ToString());
+      }
+    } else if (arguments.at(1)->keyword()) {
+      // No keyword is specified in the first argument.
+      if (missingA1 && missingA2) {
+        messages.Say(
+            "missing mandatory '%s=' argument"_err_en_US, kwA2.ToString());
+      }
+    }
+  }
+}
+
 static bool CheckAtomicKind(const ActualArgument &arg,
     const semantics::Scope *builtinsScope,
     parser::ContextualMessages &messages) {
@@ -1570,6 +1601,17 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
     }
   }
 
+  if (isMaxMin) {
+    int nArgs{0};
+    // max() / max(x) is invalid
+    while ((arguments.size() + nArgs) < 2) {
+      actualForDummy.push_back(nullptr);
+      nArgs++;
+    }
+
+    CheckMaxMinA1A2Argument(arguments, maxMinKeywords, messages);
+  }
+
   std::size_t dummies{actualForDummy.size()};
 
   // Check types and kinds of the actual arguments against the intrinsic's
@@ -1590,7 +1632,23 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
     const ActualArgument *arg{actualForDummy[j]};
     if (!arg) {
       if (d.optionality == Optionality::required) {
-        messages.Say("missing mandatory '%s=' argument"_err_en_US, d.keyword);
+        std::string kw{d.keyword};
+        if (isMaxMin && maxMinKeywords.size() == 1) {
+          // max(a1=x) or max(a2=x)
+          const auto kwA1{dummy[0].keyword};
+          const auto kwA2{dummy[1].keyword};
+          if (maxMinKeywords.begin()->ToString().compare(kwA1) == 0) {
+            messages.Say("missing mandatory 'a2=' argument"_err_en_US);
+          } else if (maxMinKeywords.begin()->ToString().compare(kwA2) == 0) {
+            messages.Say("missing mandatory 'a1=' argument"_err_en_US);
+          } else {
+            messages.Say(
+                "missing mandatory 'a1=' and 'a2=' arguments"_err_en_US);
+          }
+        } else {
+          messages.Say(
+              "missing mandatory '%s=' argument"_err_en_US, kw.c_str());
+        }
         return std::nullopt; // missing non-OPTIONAL argument
       } else {
         continue;

diff  --git a/flang/test/Semantics/call23.f90 b/flang/test/Semantics/call23.f90
index cfa7b865badeb..2e33cb092df43 100644
--- a/flang/test/Semantics/call23.f90
+++ b/flang/test/Semantics/call23.f90
@@ -1,6 +1,6 @@
 ! RUN: %python %S/test_errors.py %s %flang_fc1
 ! Check errors on MAX/MIN with keywords, a weird case in Fortran
-real :: x = 0.0 ! prevent folding
+real :: x = 0.0, y = 0.0 , y1 = 0.0 ! prevent folding
 !ERROR: Argument keyword 'a1=' was repeated in call to 'max'
 print *, max(a1=x,a1=1)
 !ERROR: Keyword argument 'a1=' has already been specified positionally (#1) in this procedure reference
@@ -9,4 +9,28 @@
 print *, max(x,0,a99=0) ! ok
 !ERROR: Argument keyword 'a06=' is not known in call to 'max'
 print *, max(a1=x,a2=0,a06=0)
+!ERROR: missing mandatory 'a2=' argument
+print *, max(a3=y, a1=x)
+!ERROR: missing mandatory 'a1=' argument
+print *, max(a3=y, a2=x)
+!ERROR: missing mandatory 'a1=' and 'a2=' arguments
+print *, max(a3=y, a4=x)
+!ERROR: missing mandatory 'a2=' argument
+print *, max(y1, a3=y)
+!ERROR: missing mandatory 'a1=' and 'a2=' arguments
+print *, max(a9=x, a5=y, a4=y1)
+!ERROR: missing mandatory 'a2=' argument
+print *, max(x)
+!ERROR: missing mandatory 'a2=' argument
+print *, max(a1=x)
+!ERROR: missing mandatory 'a1=' argument
+print *, max(a2=y)
+!ERROR: missing mandatory 'a1=' and 'a2=' arguments
+print *, max(a3=x)
+!ERROR: Argument keyword 'a0=' is not known in call to 'max'
+print *, max(a0=x)
+!ERROR: Argument keyword 'a03=' is not known in call to 'max'
+print *, max(a03=x)
+!ERROR: Argument keyword 'abad=' is not known in call to 'max'
+print *, max(abad=x)
 end


        


More information about the flang-commits mailing list