[flang-commits] [flang] e3b6b92 - [flang] Emit error when a positional actual argument follows an argument with a keyword

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Mon Mar 27 15:33:58 PDT 2023


Author: Peter Klausler
Date: 2023-03-27T15:24:14-07:00
New Revision: e3b6b9299c9691c7dcde0f80b8af679a50540979

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

LOG: [flang] Emit error when a positional actual argument follows an argument with a keyword

A positional (non-keyword) actual argument or alternate return label is not
allowed to follow an actual argument with a keyword.

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

Added: 
    

Modified: 
    flang/lib/Evaluate/intrinsics.cpp
    flang/lib/Semantics/check-call.cpp
    flang/test/Evaluate/fold-ishftc.f90
    flang/test/Semantics/collectives01.f90
    flang/test/Semantics/collectives02.f90
    flang/test/Semantics/collectives03.f90
    flang/test/Semantics/collectives04.f90
    flang/test/Semantics/lcobound.f90
    flang/test/Semantics/ucobound.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index 7e8285a8a8d15..a27d211420181 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -1543,17 +1543,32 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
       dummy[dummyArgPatterns - 1].optionality == Optionality::repeats};
   std::vector<ActualArgument *> actualForDummy(
       isMaxMin ? 0 : dummyArgPatterns, nullptr);
-  int missingActualArguments{0};
+  bool anyMissingActualArgument{false};
   std::set<parser::CharBlock> maxMinKeywords;
+  bool anyKeyword{false};
+  int which{0};
   for (std::optional<ActualArgument> &arg : arguments) {
-    if (!arg) {
-      ++missingActualArguments;
-    } else if (arg->isAlternateReturn()) {
-      messages.Say(arg->sourceLocation(),
-          "alternate return specifier not acceptable on call to intrinsic '%s'"_err_en_US,
-          name);
-      return std::nullopt;
-    } else if (isMaxMin) {
+    ++which;
+    if (arg) {
+      if (arg->isAlternateReturn()) {
+        messages.Say(arg->sourceLocation(),
+            "alternate return specifier not acceptable on call to intrinsic '%s'"_err_en_US,
+            name);
+        return std::nullopt;
+      }
+      if (arg->keyword()) {
+        anyKeyword = true;
+      } else if (anyKeyword) {
+        messages.Say(arg ? arg->sourceLocation() : std::nullopt,
+            "actual argument #%d without a keyword may not follow an actual argument with a keyword"_err_en_US,
+            which);
+        return std::nullopt;
+      }
+    } else {
+      anyMissingActualArgument = true;
+      continue;
+    }
+    if (isMaxMin) {
       if (CheckMaxMinArgument(arg->keyword(), maxMinKeywords, name, messages)) {
         actualForDummy.push_back(&*arg);
       } else {
@@ -1561,7 +1576,6 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
       }
     } else {
       bool found{false};
-      int slot{missingActualArguments};
       for (std::size_t j{0}; j < dummyArgPatterns && !found; ++j) {
         if (dummy[j].optionality == Optionality::missing) {
           continue;
@@ -1584,7 +1598,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
             }
           }
         } else {
-          found = !actualForDummy[j] && slot-- == 0;
+          found = !actualForDummy[j] && !anyMissingActualArgument;
         }
         if (found) {
           actualForDummy[j] = &*arg;

diff  --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index e4b65fc8adfe4..d398c5ec0d05a 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -873,8 +873,11 @@ static void RearrangeArguments(const characteristics::Procedure &proc,
         actuals.size(), proc.dummyArguments.size());
   }
   std::map<std::string, evaluate::ActualArgument> kwArgs;
+  bool anyKeyword{false};
+  int which{1};
   for (auto &x : actuals) {
-    if (x && x->keyword()) {
+    if (!x) {
+    } else if (x->keyword()) {
       auto emplaced{
           kwArgs.try_emplace(x->keyword()->ToString(), std::move(*x))};
       if (!emplaced.second) {
@@ -883,7 +886,13 @@ static void RearrangeArguments(const characteristics::Procedure &proc,
             *x->keyword());
       }
       x.reset();
+      anyKeyword = true;
+    } else if (anyKeyword) {
+      messages.Say(x ? x->sourceLocation() : std::nullopt,
+          "Actual argument #%d without a keyword may not follow any actual argument with a keyword"_err_en_US,
+          which);
     }
+    ++which;
   }
   if (!kwArgs.empty()) {
     int index{0};

diff  --git a/flang/test/Evaluate/fold-ishftc.f90 b/flang/test/Evaluate/fold-ishftc.f90
index 705134823956c..9fca0175a75c4 100644
--- a/flang/test/Evaluate/fold-ishftc.f90
+++ b/flang/test/Evaluate/fold-ishftc.f90
@@ -1,7 +1,7 @@
 ! RUN: %python %S/test_folding.py %s %flang_fc1
 ! Tests folding of ISHFTC
 module m
-  integer, parameter :: shift8s(*) = ishftc(257, shift = [(ict, ict = -8, 8)], 8)
+  integer, parameter :: shift8s(*) = ishftc(257, shift = [(ict, ict = -8, 8)], size=8)
   integer, parameter :: expect1(*) = 256 + [1, 2, 4, 8, 16, 32, 64, 128, &
                                             1, 2, 4, 8, 16, 32, 64, 128, 1]
   logical, parameter :: test_1 = all(shift8s == expect1)

diff  --git a/flang/test/Semantics/collectives01.f90 b/flang/test/Semantics/collectives01.f90
index c87e228508e15..00e2aefb8f603 100644
--- a/flang/test/Semantics/collectives01.f90
+++ b/flang/test/Semantics/collectives01.f90
@@ -135,7 +135,7 @@ program test_co_sum
   !ERROR: 'errmsg=' argument has unacceptable rank 1
   call co_sum(d, errmsg=character_array)
 
-  !ERROR: too many actual arguments for intrinsic 'co_sum'
+  !ERROR: actual argument #5 without a keyword may not follow an actual argument with a keyword
   call co_sum(r, result_image=1, stat=status, errmsg=message, 3.4)
 
   ! keyword argument with incorrect name

diff  --git a/flang/test/Semantics/collectives02.f90 b/flang/test/Semantics/collectives02.f90
index 96485ce2ebae6..4febeee17ce8d 100644
--- a/flang/test/Semantics/collectives02.f90
+++ b/flang/test/Semantics/collectives02.f90
@@ -120,7 +120,7 @@ program test_co_min
   !ERROR: 'errmsg=' argument has unacceptable rank 1
   call co_min(d, errmsg=character_array)
 
-  !ERROR: too many actual arguments for intrinsic 'co_min'
+  !ERROR: actual argument #5 without a keyword may not follow an actual argument with a keyword
   call co_min(r, result_image=1, stat=status, errmsg=message, 3.4)
 
   !ERROR: unknown keyword argument to intrinsic 'co_min'

diff  --git a/flang/test/Semantics/collectives03.f90 b/flang/test/Semantics/collectives03.f90
index e5de68b99bef0..811a7b79bba5f 100644
--- a/flang/test/Semantics/collectives03.f90
+++ b/flang/test/Semantics/collectives03.f90
@@ -120,7 +120,7 @@ program test_co_max
   !ERROR: 'errmsg=' argument has unacceptable rank 1
   call co_max(d, errmsg=character_array)
 
-  !ERROR: too many actual arguments for intrinsic 'co_max'
+  !ERROR: actual argument #5 without a keyword may not follow an actual argument with a keyword
   call co_max(r, result_image=1, stat=status, errmsg=message, 3.4)
 
   !ERROR: unknown keyword argument to intrinsic 'co_max'

diff  --git a/flang/test/Semantics/collectives04.f90 b/flang/test/Semantics/collectives04.f90
index 3cd3c3f422d06..bcd1a7ec29789 100644
--- a/flang/test/Semantics/collectives04.f90
+++ b/flang/test/Semantics/collectives04.f90
@@ -126,7 +126,7 @@ program test_co_broadcast
   !ERROR: 'errmsg=' argument has unacceptable rank 1
   call co_broadcast(d, errmsg=character_array, source_image=1)
 
-  !ERROR: too many actual arguments for intrinsic 'co_broadcast'
+  !ERROR: actual argument #5 without a keyword may not follow an actual argument with a keyword
   call co_broadcast(r, source_image=1, stat=status, errmsg=message, 3.4)
 
   !ERROR: unknown keyword argument to intrinsic 'co_broadcast'

diff  --git a/flang/test/Semantics/lcobound.f90 b/flang/test/Semantics/lcobound.f90
index 8feb496e1984e..ce2f001ce2ea7 100644
--- a/flang/test/Semantics/lcobound.f90
+++ b/flang/test/Semantics/lcobound.f90
@@ -104,8 +104,11 @@ program lcobound_tests
   !ERROR: missing mandatory 'coarray=' argument
   n = lcobound(dim=i, kind=c_int32_t)
 
+  !ERROR: actual argument #2 without a keyword may not follow an actual argument with a keyword
   n = lcobound(coarray=scalar_coarray, i)
 
+  n = lcobound(coarray=scalar_coarray, dim=i)
+
   !ERROR: missing mandatory 'coarray=' argument
   lcobounds = lcobound()
 

diff  --git a/flang/test/Semantics/ucobound.f90 b/flang/test/Semantics/ucobound.f90
index da9f995f1a97b..f9da11a03a6b0 100644
--- a/flang/test/Semantics/ucobound.f90
+++ b/flang/test/Semantics/ucobound.f90
@@ -104,8 +104,11 @@ program ucobound_tests
   !ERROR: missing mandatory 'coarray=' argument
   n = ucobound(dim=i, kind=c_int32_t)
 
+  !ERROR: actual argument #2 without a keyword may not follow an actual argument with a keyword
   n = ucobound(coarray=scalar_coarray, i)
 
+  n = ucobound(coarray=scalar_coarray, dim=i)
+
   !ERROR: missing mandatory 'coarray=' argument
   ucobounds = ucobound()
 


        


More information about the flang-commits mailing list