[flang-commits] [flang] 15fa287 - [flang] Support for image selectors

Pete Steinfeld via flang-commits flang-commits at lists.llvm.org
Wed Jul 8 07:32:16 PDT 2020


Author: Pete Steinfeld
Date: 2020-07-08T07:31:54-07:00
New Revision: 15fa287b64d0ef845201339994cdf6eb3e4d51e1

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

LOG: [flang] Support for image selectors

Summary:
This change implements support for image selectors and image selector
specifications as described in section 9.6.

In check-coarray[.h,cpp] I changed the `Leave()` function for
`parser::ImageSelectorSpec` to take a `parser::ImageSelector`, which
contains a list of image selector specifications.  This allows us to
detect when the same specification is used more than once.  I also added
code to analyze the expressions for the image selector specifications to
expression.cpp and a test for all of the conditions to check at
compile-time.

Note that we do not check at compile-time to see if the value of the
cosubscripts are within the specified cobounds.  We also do not check anything
related to selecting a valid team.  We also do not check that the denotation of
the `stat-variable` is not dependent on the evaluation of an entity in the
same statement.

Reviewers: klausler, tskeith, DavidTruby

Subscribers: llvm-commits

Tags: #llvm, #flang

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

Added: 
    flang/test/Semantics/resolve94.f90

Modified: 
    flang/include/flang/Parser/tools.h
    flang/lib/Parser/tools.cpp
    flang/lib/Semantics/check-coarray.cpp
    flang/lib/Semantics/check-coarray.h
    flang/lib/Semantics/expression.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Parser/tools.h b/flang/include/flang/Parser/tools.h
index c918425a2978..fa6ecd08a318 100644
--- a/flang/include/flang/Parser/tools.h
+++ b/flang/include/flang/Parser/tools.h
@@ -99,6 +99,8 @@ template <typename A, typename B> A *Unwrap(B &x) {
 // Get the CoindexedNamedObject if the entity is a coindexed object.
 const CoindexedNamedObject *GetCoindexedNamedObject(const AllocateObject &);
 const CoindexedNamedObject *GetCoindexedNamedObject(const DataRef &);
+const CoindexedNamedObject *GetCoindexedNamedObject(const Designator &);
+const CoindexedNamedObject *GetCoindexedNamedObject(const Variable &);
 
 // Detects parse tree nodes with "source" members.
 template <typename A, typename = int> struct HasSource : std::false_type {};

diff  --git a/flang/lib/Parser/tools.cpp b/flang/lib/Parser/tools.cpp
index 0a21e73839ed..2db832ab715f 100644
--- a/flang/lib/Parser/tools.cpp
+++ b/flang/lib/Parser/tools.cpp
@@ -135,6 +135,30 @@ const CoindexedNamedObject *GetCoindexedNamedObject(const DataRef &base) {
       },
       base.u);
 }
+const CoindexedNamedObject *GetCoindexedNamedObject(
+    const Designator &designator) {
+  return std::visit(common::visitors{
+                        [](const DataRef &x) -> const CoindexedNamedObject * {
+                          return GetCoindexedNamedObject(x);
+                        },
+                        [](const Substring &x) -> const CoindexedNamedObject * {
+                          return GetCoindexedNamedObject(
+                              std::get<DataRef>(x.t));
+                        },
+                    },
+      designator.u);
+}
+const CoindexedNamedObject *GetCoindexedNamedObject(const Variable &variable) {
+  return std::visit(
+      common::visitors{
+          [](const common::Indirection<Designator> &designator)
+              -> const CoindexedNamedObject * {
+            return GetCoindexedNamedObject(designator.value());
+          },
+          [](const auto &) -> const CoindexedNamedObject * { return nullptr; },
+      },
+      variable.u);
+}
 const CoindexedNamedObject *GetCoindexedNamedObject(
     const AllocateObject &allocateObject) {
   return std::visit(

diff  --git a/flang/lib/Semantics/check-coarray.cpp b/flang/lib/Semantics/check-coarray.cpp
index a9d649ffff47..4ce286d0bca1 100644
--- a/flang/lib/Semantics/check-coarray.cpp
+++ b/flang/lib/Semantics/check-coarray.cpp
@@ -72,6 +72,16 @@ static void CheckTeamType(SemanticsContext &context, const T &x) {
   }
 }
 
+static void CheckTeamStat(
+    SemanticsContext &context, const parser::ImageSelectorSpec::Stat &stat) {
+  const parser::Variable &var{stat.v.thing.thing.value()};
+  if (parser::GetCoindexedNamedObject(var)) {
+    context.Say(parser::FindSourceLocation(var), // C931
+        "Image selector STAT variable must not be a coindexed "
+        "object"_err_en_US);
+  }
+}
+
 void CoarrayChecker::Leave(const parser::ChangeTeamStmt &x) {
   CheckNamesAreDistinct(std::get<std::list<parser::CoarrayAssociation>>(x.t));
   CheckTeamType(context_, std::get<parser::TeamValue>(x.t));
@@ -81,9 +91,42 @@ void CoarrayChecker::Leave(const parser::SyncTeamStmt &x) {
   CheckTeamType(context_, std::get<parser::TeamValue>(x.t));
 }
 
-void CoarrayChecker::Leave(const parser::ImageSelectorSpec &x) {
-  if (const auto *team{std::get_if<parser::TeamValue>(&x.u)}) {
-    CheckTeamType(context_, *team);
+void CoarrayChecker::Leave(const parser::ImageSelector &imageSelector) {
+  haveStat_ = false;
+  haveTeam_ = false;
+  haveTeamNumber_ = false;
+  for (const auto &imageSelectorSpec :
+      std::get<std::list<parser::ImageSelectorSpec>>(imageSelector.t)) {
+    if (const auto *team{
+            std::get_if<parser::TeamValue>(&imageSelectorSpec.u)}) {
+      if (haveTeam_) {
+        context_.Say(parser::FindSourceLocation(imageSelectorSpec), // C929
+            "TEAM value can only be specified once"_err_en_US);
+      }
+      CheckTeamType(context_, *team);
+      haveTeam_ = true;
+    }
+    if (const auto *stat{std::get_if<parser::ImageSelectorSpec::Stat>(
+            &imageSelectorSpec.u)}) {
+      if (haveStat_) {
+        context_.Say(parser::FindSourceLocation(imageSelectorSpec), // C929
+            "STAT variable can only be specified once"_err_en_US);
+      }
+      CheckTeamStat(context_, *stat);
+      haveStat_ = true;
+    }
+    if (std::get_if<parser::ImageSelectorSpec::Team_Number>(
+            &imageSelectorSpec.u)) {
+      if (haveTeamNumber_) {
+        context_.Say(parser::FindSourceLocation(imageSelectorSpec), // C929
+            "TEAM_NUMBER value can only be specified once"_err_en_US);
+      }
+      haveTeamNumber_ = true;
+    }
+  }
+  if (haveTeam_ && haveTeamNumber_) {
+    context_.Say(parser::FindSourceLocation(imageSelector), // C930
+        "Cannot specify both TEAM and TEAM_NUMBER"_err_en_US);
   }
 }
 

diff  --git a/flang/lib/Semantics/check-coarray.h b/flang/lib/Semantics/check-coarray.h
index 2e91c7b259d6..5f30dda6b547 100644
--- a/flang/lib/Semantics/check-coarray.h
+++ b/flang/lib/Semantics/check-coarray.h
@@ -18,9 +18,8 @@ class MessageFixedText;
 struct ChangeTeamStmt;
 struct CoarrayAssociation;
 struct FormTeamStmt;
-struct ImageSelectorSpec;
+struct ImageSelector;
 struct SyncTeamStmt;
-struct TeamValue;
 } // namespace Fortran::parser
 
 namespace Fortran::semantics {
@@ -30,13 +29,16 @@ class CoarrayChecker : public virtual BaseChecker {
   CoarrayChecker(SemanticsContext &context) : context_{context} {}
   void Leave(const parser::ChangeTeamStmt &);
   void Leave(const parser::SyncTeamStmt &);
-  void Leave(const parser::ImageSelectorSpec &);
+  void Leave(const parser::ImageSelector &);
   void Leave(const parser::FormTeamStmt &);
 
   void Enter(const parser::CriticalConstruct &);
 
 private:
   SemanticsContext &context_;
+  bool haveStat_;
+  bool haveTeam_;
+  bool haveTeamNumber_;
 
   void CheckNamesAreDistinct(const std::list<parser::CoarrayAssociation> &);
   void Say2(const parser::CharBlock &, parser::MessageFixedText &&,

diff  --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 27fcf5e2db36..71911718c087 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -1085,7 +1085,14 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::CoindexedNamedObject &x) {
             symbol.name(), symbol.Corank(), numCosubscripts);
       }
     }
-    // TODO: stat=/team=/team_number=
+    for (const auto &imageSelSpec :
+        std::get<std::list<parser::ImageSelectorSpec>>(x.imageSelector.t)) {
+      std::visit(
+          common::visitors{
+              [&](const auto &x) {Analyze(x.v); },
+          },
+          imageSelSpec.u);
+    }
     // Reverse the chain of symbols so that the base is first and coarray
     // ultimate component is last.
     return Designate(

diff  --git a/flang/test/Semantics/resolve94.f90 b/flang/test/Semantics/resolve94.f90
new file mode 100644
index 000000000000..b38037e2d530
--- /dev/null
+++ b/flang/test/Semantics/resolve94.f90
@@ -0,0 +1,69 @@
+! RUN: %S/test_errors.sh %s %t %f18
+! C929   No specifier shall appear more than once in a given 
+!   image-selector-spec-list.
+! C930 TEAM and TEAM_NUMBER shall not both appear in the same
+!   image-selector-spec-list.
+! C931 A stat-variable in an image-selector shall not be a coindexed object.
+subroutine s1()
+  use ISO_FORTRAN_ENV
+  type(team_type) :: team1, team2
+  real :: rCoarray[10,20,*]
+  real :: rVar1, rVar2
+  integer :: iVar1, iVar2
+  integer, dimension(4) :: intArray
+  integer :: intScalarCoarray[*]
+  integer :: intCoarray[3, 4, *]
+  intCoVar = 343
+  ! OK
+  rVar1 = rCoarray[1,2,3]
+  !ERROR: 'rcoarray' has corank 3, but coindexed reference has 2 cosubscripts
+  rVar1 = rCoarray[1,2]
+  !ERROR: Must have INTEGER type, but is REAL(4)
+  rVar1 = rCoarray[1,2,3.4]
+  !ERROR: Must be a scalar value, but is a rank-1 array
+  rVar1 = rCoarray[1,intArray,3]
+  ! OK
+  rVar1 = rCoarray[1,2,3,STAT=iVar1, TEAM=team2]
+  !ERROR: Team value must be of type TEAM_TYPE from module ISO_FORTRAN_ENV
+  rVar1 = rCoarray[1,2,3,STAT=iVar1, TEAM=2]
+  ! OK
+  rVar1 = rCoarray[1,2,3,STAT=iVar1, TEAM_NUMBER=38]
+  ! OK
+  rVar1 = rCoarray[1,2,3,STAT=iVar1]
+  ! OK
+  rVar1 = rCoarray[1,2,3,STAT=intArray(2)]
+  !ERROR: Must have INTEGER type, but is REAL(4)
+  rVar1 = rCoarray[1,2,3,STAT=rVar2]
+  !ERROR: Must be a scalar value, but is a rank-1 array
+  rVar1 = rCoarray[1,2,3,STAT=intArray]
+  ! Error on C929, no specifier can appear more than once
+  !ERROR: STAT variable can only be specified once
+  rVar1 = rCoarray[1,2,3,STAT=iVar1, STAT=iVar2]
+  ! OK
+  rVar1 = rCoarray[1,2,3,TEAM=team1]
+  ! Error on C929, no specifier can appear more than once
+  !ERROR: TEAM value can only be specified once
+  rVar1 = rCoarray[1,2,3,TEAM=team1, TEAM=team2]
+  ! OK
+  rVar1 = rCoarray[1,2,3,TEAM_NUMBER=37]
+  ! OK
+  rVar1 = rCoarray[1,2,3,TEAM_NUMBER=iVar1]
+  ! Error, team number is a scalar integer expression
+  !ERROR: Must be a scalar value, but is a rank-1 array
+  rVar1 = rCoarray[1,2,3,TEAM_NUMBER=intArray]
+  ! Error, team number is a scalar integer expression
+  !ERROR: Must have INTEGER type, but is REAL(4)
+  rVar1 = rCoarray[1,2,3,TEAM_NUMBER=3.7]
+  ! Error on C929, no specifier can appear more than once
+  !ERROR: TEAM_NUMBER value can only be specified once
+  rVar1 = rCoarray[1,2,3,TEAM_NUMBER=37, TEAM_NUMBER=37]
+  !ERROR: Cannot specify both TEAM and TEAM_NUMBER
+  rVar1 = rCoarray[1,2,3,TEAM=team1, TEAM_NUMBER=37]
+  !ERROR: Cannot specify both TEAM and TEAM_NUMBER
+  rVar1 = rCoarray[1,2,3,TEAM_number=43, TEAM=team1]
+  ! OK for a STAT variable to be a coarray integer
+  rVar1 = rCoarray[1,2,3,stat=intScalarCoarray]
+  ! Error for a STAT variable to be a coindexed object
+  !ERROR: Image selector STAT variable must not be a coindexed object
+  rVar1 = rCoarray[1,2,3,stat=intCoarray[2,3, 4]]
+end subroutine s1


        


More information about the flang-commits mailing list