[llvm-branch-commits] [flang] b73736a - [flang][openacc] Enforce delcare directive restriction

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Jan 7 06:33:41 PST 2021


Author: Valentin Clement
Date: 2021-01-07T09:28:55-05:00
New Revision: b73736a4048172c48b6b5c23d1321f230d442306

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

LOG: [flang][openacc] Enforce delcare directive restriction

Add semantic check for most of the restrictions for the declare directive.

Reviewed By: kiranktp

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

Added: 
    flang/test/Semantics/acc-declare-validity.f90

Modified: 
    flang/lib/Semantics/check-acc-structure.cpp
    flang/lib/Semantics/resolve-directives.cpp
    flang/test/Semantics/acc-clause-validity.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/check-acc-structure.cpp b/flang/lib/Semantics/check-acc-structure.cpp
index 45499a69e604..2f3138d11f80 100644
--- a/flang/lib/Semantics/check-acc-structure.cpp
+++ b/flang/lib/Semantics/check-acc-structure.cpp
@@ -134,9 +134,30 @@ void AccStructureChecker::Enter(
 }
 
 void AccStructureChecker::Leave(
-    const parser::OpenACCStandaloneDeclarativeConstruct &) {
+    const parser::OpenACCStandaloneDeclarativeConstruct &x) {
   // Restriction - line 2409
   CheckAtLeastOneClause();
+
+  // Restriction - line 2417-2418 - In a Fortran module declaration section,
+  // only create, copyin, device_resident, and link clauses are allowed.
+  const auto &declarativeDir{std::get<parser::AccDeclarativeDirective>(x.t)};
+  const auto &scope{context_.FindScope(declarativeDir.source)};
+  const Scope &containingScope{GetProgramUnitContaining(scope)};
+  if (containingScope.kind() == Scope::Kind::Module) {
+    for (auto cl : GetContext().actualClauses) {
+      if (cl != llvm::acc::Clause::ACCC_create &&
+          cl != llvm::acc::Clause::ACCC_copyin &&
+          cl != llvm::acc::Clause::ACCC_device_resident &&
+          cl != llvm::acc::Clause::ACCC_link)
+        context_.Say(GetContext().directiveSource,
+            "%s clause is not allowed on the %s directive in module "
+            "declaration "
+            "section"_err_en_US,
+            parser::ToUpperCaseLetters(
+                llvm::acc::getOpenACCClauseName(cl).str()),
+            ContextDirectiveAsFortran());
+    }
+  }
   dirContext_.pop_back();
 }
 

diff  --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index e10d797d0308..81e0ee61df4a 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -124,6 +124,7 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
 
   bool Pre(const parser::OpenACCRoutineConstruct &);
   bool Pre(const parser::AccBindClause &);
+  void Post(const parser::OpenACCStandaloneDeclarativeConstruct &);
 
   void Post(const parser::AccBeginBlockDirective &) {
     GetContext().withinConstruct = true;
@@ -215,6 +216,7 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
   void CheckMultipleAppearances(
       const parser::Name &, const Symbol &, Symbol::Flag);
   void AllowOnlyArrayAndSubArray(const parser::AccObjectList &objectList);
+  void DoNotAllowAssumedSizedArray(const parser::AccObjectList &objectList);
 };
 
 // Data-sharing and Data-mapping attributes for data-refs in OpenMP construct
@@ -470,6 +472,60 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCDeclarativeConstruct &x) {
   return true;
 }
 
+static const parser::AccObjectList &GetAccObjectList(
+    const parser::AccClause &clause) {
+  if (const auto *copyClause =
+          std::get_if<Fortran::parser::AccClause::Copy>(&clause.u)) {
+    return copyClause->v;
+  } else if (const auto *createClause =
+                 std::get_if<Fortran::parser::AccClause::Create>(&clause.u)) {
+    const Fortran::parser::AccObjectListWithModifier &listWithModifier =
+        createClause->v;
+    const Fortran::parser::AccObjectList &accObjectList =
+        std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
+    return accObjectList;
+  } else if (const auto *copyinClause =
+                 std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
+    const Fortran::parser::AccObjectListWithModifier &listWithModifier =
+        copyinClause->v;
+    const Fortran::parser::AccObjectList &accObjectList =
+        std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
+    return accObjectList;
+  } else if (const auto *copyoutClause =
+                 std::get_if<Fortran::parser::AccClause::Copyout>(&clause.u)) {
+    const Fortran::parser::AccObjectListWithModifier &listWithModifier =
+        copyoutClause->v;
+    const Fortran::parser::AccObjectList &accObjectList =
+        std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
+    return accObjectList;
+  } else if (const auto *presentClause =
+                 std::get_if<Fortran::parser::AccClause::Present>(&clause.u)) {
+    return presentClause->v;
+  } else if (const auto *deviceptrClause =
+                 std::get_if<Fortran::parser::AccClause::Deviceptr>(
+                     &clause.u)) {
+    return deviceptrClause->v;
+  } else if (const auto *deviceResidentClause =
+                 std::get_if<Fortran::parser::AccClause::DeviceResident>(
+                     &clause.u)) {
+    return deviceResidentClause->v;
+  } else if (const auto *linkClause =
+                 std::get_if<Fortran::parser::AccClause::Link>(&clause.u)) {
+    return linkClause->v;
+  } else {
+    llvm_unreachable("Clause without object list!");
+  }
+}
+
+void AccAttributeVisitor::Post(
+    const parser::OpenACCStandaloneDeclarativeConstruct &x) {
+  const auto &clauseList = std::get<parser::AccClauseList>(x.t);
+  for (const auto &clause : clauseList.v) {
+    // Restriction - line 2414
+    DoNotAllowAssumedSizedArray(GetAccObjectList(clause));
+  }
+}
+
 bool AccAttributeVisitor::Pre(const parser::OpenACCLoopConstruct &x) {
   const auto &beginDir{std::get<parser::AccBeginLoopDirective>(x.t)};
   const auto &loopDir{std::get<parser::AccLoopDirective>(beginDir.t)};
@@ -588,6 +644,30 @@ void AccAttributeVisitor::AllowOnlyArrayAndSubArray(
   }
 }
 
+void AccAttributeVisitor::DoNotAllowAssumedSizedArray(
+    const parser::AccObjectList &objectList) {
+  for (const auto &accObject : objectList.v) {
+    std::visit(
+        common::visitors{
+            [&](const parser::Designator &designator) {
+              const auto &name{GetLastName(designator)};
+              if (name.symbol && semantics::IsAssumedSizeArray(*name.symbol))
+                context_.Say(designator.source,
+                    "Assumed-size dummy arrays may not appear on the %s "
+                    "directive"_err_en_US,
+                    parser::ToUpperCaseLetters(
+                        llvm::acc::getOpenACCDirectiveName(
+                            GetContext().directive)
+                            .str()));
+            },
+            [&](const auto &name) {
+
+            },
+        },
+        accObject.u);
+  }
+}
+
 bool AccAttributeVisitor::Pre(const parser::OpenACCCacheConstruct &x) {
   const auto &verbatim{std::get<parser::Verbatim>(x.t)};
   PushContext(verbatim.source, llvm::acc::Directive::ACCD_cache);

diff  --git a/flang/test/Semantics/acc-clause-validity.f90 b/flang/test/Semantics/acc-clause-validity.f90
index 167051d18760..d0852a1e3d1b 100644
--- a/flang/test/Semantics/acc-clause-validity.f90
+++ b/flang/test/Semantics/acc-clause-validity.f90
@@ -7,7 +7,6 @@
 !   2.5.3 Kernels
 !   2.9 Loop
 !   2.12 Atomic
-!   2.13 Declare
 !   2.14.3 Set
 !   2.14.4 Update
 !   2.15.1 Routine
@@ -42,8 +41,6 @@ program openacc_clause_validity
   type(atype) :: t
   type(atype), dimension(10) :: ta
 
-  !ERROR: At least one clause is required on the DECLARE directive
-  !$acc declare
   real(8), dimension(N) :: a, f, g, h
 
   !$acc init

diff  --git a/flang/test/Semantics/acc-declare-validity.f90 b/flang/test/Semantics/acc-declare-validity.f90
new file mode 100644
index 000000000000..026ec7ea4a67
--- /dev/null
+++ b/flang/test/Semantics/acc-declare-validity.f90
@@ -0,0 +1,57 @@
+! RUN: %S/test_errors.sh %s %t %f18 -fopenacc
+
+! Check OpenACC clause validity for the following construct and directive:
+!   2.13 Declare
+
+module openacc_declare_validity
+
+  implicit none
+
+  real(8), dimension(10) :: aa, bb, ab, cc
+
+  !ERROR: At least one clause is required on the DECLARE directive
+  !$acc declare
+
+  !$acc declare create(aa, bb)
+
+  !$acc declare link(ab)
+
+  !$acc declare device_resident(cc)
+
+  !ERROR: COPYOUT clause is not allowed on the DECLARE directive in module declaration section
+  !$acc declare copyout(ab)
+
+  !ERROR: COPY clause is not allowed on the DECLARE directive in module declaration section
+  !$acc declare copy(ab)
+
+  !ERROR: PRESENT clause is not allowed on the DECLARE directive in module declaration section
+  !$acc declare present(ab)
+
+  !ERROR: DEVICEPTR clause is not allowed on the DECLARE directive in module declaration section
+  !$acc declare deviceptr(ab)
+
+contains
+
+  subroutine sub1(cc, dd)
+    real(8) :: cc(:)
+    real(8) :: dd(:)
+    !$acc declare present(cc, dd)
+  end subroutine sub1
+
+  function fct1(ee, ff, gg, hh, ii)
+    integer :: fct1
+    real(8), intent(in) :: ee(:)
+    !$acc declare copyin(readonly: ee)
+    real(8) :: ff(:), hh(:), ii(:,:)
+    !$acc declare link(hh) device_resident(ii)
+    real(8), intent(out) :: gg(:)
+    !$acc declare copy(ff) copyout(gg)
+  end function fct1
+
+  subroutine sub2(cc)
+    real(8), dimension(*) :: cc
+    !ERROR: Assumed-size dummy arrays may not appear on the DECLARE directive
+    !$acc declare present(cc)
+  end subroutine sub2
+
+end module openacc_declare_validity


        


More information about the llvm-branch-commits mailing list