[flang-commits] [flang] 20e3a6c - Add Semantic check for Flang OpenMP 4.5 - 2.7.1 Do Loop restrictions.

via flang-commits flang-commits at lists.llvm.org
Mon Feb 15 05:14:43 PST 2021


Author: Yashaswini
Date: 2021-02-15T18:39:14+05:30
New Revision: 20e3a6cb6270b68139f74529ab8efdfad1263533

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

LOG: Add Semantic check for Flang OpenMP 4.5 - 2.7.1  Do Loop restrictions.
Implementation of Do loop iteration variable check, Do while loop check, Do loop cycle restrictions.
Also to check whether the ordered clause is present on the loop construct if any ordered region ever
 binds to a loop region arising from the loop construct.

Files:

check-omp-structure.h
check-omp-structure.cpp
resolve-directives.cpp

Testcases:

omp-do06-positivecases.f90
omp-do06.f90
omp-do08.f90
omp-do09.f90
omp-do10.f90
omp-do11.f90
omp-do12.f90
omp-do13.f90
omp-do14.f90
omp-do15.f90
omp-do16.f90
omp-do17.f90

Reviewed by: Kiran Chandramohan @kiranchandramohan , Valentin Clement @clementval

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

Added: 
    flang/test/Semantics/omp-do06-positivecases.f90
    flang/test/Semantics/omp-do11.f90
    flang/test/Semantics/omp-do12.f90
    flang/test/Semantics/omp-do13.f90
    flang/test/Semantics/omp-do14.f90
    flang/test/Semantics/omp-do15.f90
    flang/test/Semantics/omp-do16.f90
    flang/test/Semantics/omp-do17.f90

Modified: 
    flang/lib/Semantics/check-omp-structure.cpp
    flang/lib/Semantics/check-omp-structure.h
    flang/lib/Semantics/resolve-directives.cpp
    flang/test/Semantics/omp-do06.f90
    flang/test/Semantics/omp-do08.f90
    flang/test/Semantics/omp-do09.f90
    flang/test/Semantics/omp-do10.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index bb642dc0e92c..4a9192d1926c 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -84,6 +84,49 @@ class OmpWorkshareBlockChecker {
   parser::CharBlock source_;
 };
 
+class OmpCycleChecker {
+public:
+  OmpCycleChecker(SemanticsContext &context, std::int64_t cycleLevel)
+      : context_{context}, cycleLevel_{cycleLevel} {}
+
+  template <typename T> bool Pre(const T &) { return true; }
+  template <typename T> void Post(const T &) {}
+
+  bool Pre(const parser::DoConstruct &dc) {
+    cycleLevel_--;
+    const auto &labelName{std::get<0>(std::get<0>(dc.t).statement.t)};
+    if (labelName) {
+      labelNamesandLevels_.emplace(labelName.value().ToString(), cycleLevel_);
+    }
+    return true;
+  }
+
+  bool Pre(const parser::CycleStmt &cyclestmt) {
+    std::map<std::string, std::int64_t>::iterator it;
+    bool err{false};
+    if (cyclestmt.v) {
+      it = labelNamesandLevels_.find(cyclestmt.v->source.ToString());
+      err = (it != labelNamesandLevels_.end() && it->second > 0);
+    }
+    if (cycleLevel_ > 0 || err) {
+      context_.Say(*cycleSource_,
+          "CYCLE statement to non-innermost associated loop of an OpenMP DO construct"_err_en_US);
+    }
+    return true;
+  }
+
+  bool Pre(const parser::Statement<parser::ActionStmt> &actionstmt) {
+    cycleSource_ = &actionstmt.source;
+    return true;
+  }
+
+private:
+  SemanticsContext &context_;
+  const parser::CharBlock *cycleSource_;
+  std::int64_t cycleLevel_;
+  std::map<std::string, std::int64_t> labelNamesandLevels_;
+};
+
 bool OmpStructureChecker::HasInvalidWorksharingNesting(
     const parser::CharBlock &source, const OmpDirectiveSet &set) {
   // set contains all the invalid closely nested directives
@@ -147,6 +190,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
     const auto &doBlock{std::get<parser::Block>(doConstruct->t)};
     CheckNoBranching(doBlock, beginDir.v, beginDir.source);
   }
+  CheckDoWhile(x);
+  CheckLoopItrVariableIsInt(x);
+  CheckCycleConstraints(x);
 }
 const parser::Name OmpStructureChecker::GetLoopIndex(
     const parser::DoConstruct *x) {
@@ -163,6 +209,85 @@ void OmpStructureChecker::SetLoopInfo(const parser::OpenMPLoopConstruct &x) {
     }
   }
 }
+void OmpStructureChecker::CheckDoWhile(const parser::OpenMPLoopConstruct &x) {
+  const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)};
+  const auto &beginDir{std::get<parser::OmpLoopDirective>(beginLoopDir.t)};
+  if (beginDir.v == llvm::omp::Directive::OMPD_do) {
+    if (const auto &doConstruct{
+            std::get<std::optional<parser::DoConstruct>>(x.t)}) {
+      if (doConstruct.value().IsDoWhile()) {
+        const auto &doStmt{std::get<parser::Statement<parser::NonLabelDoStmt>>(
+            doConstruct.value().t)};
+        context_.Say(doStmt.source,
+            "The DO loop cannot be a DO WHILE with DO directive."_err_en_US);
+      }
+    }
+  }
+}
+
+void OmpStructureChecker::CheckLoopItrVariableIsInt(
+    const parser::OpenMPLoopConstruct &x) {
+  if (const auto &loopConstruct{
+          std::get<std::optional<parser::DoConstruct>>(x.t)}) {
+
+    for (const parser::DoConstruct *loop{&*loopConstruct}; loop;) {
+      if (loop->IsDoNormal()) {
+        const parser::Name &itrVal{GetLoopIndex(loop)};
+        if (itrVal.symbol) {
+          const auto *type{itrVal.symbol->GetType()};
+          if (!type->IsNumeric(TypeCategory::Integer)) {
+            context_.Say(itrVal.source,
+                "The DO loop iteration"
+                " variable must be of the type integer."_err_en_US,
+                itrVal.ToString());
+          }
+        }
+      }
+      // Get the next DoConstruct if block is not empty.
+      const auto &block{std::get<parser::Block>(loop->t)};
+      const auto it{block.begin()};
+      loop = it != block.end() ? parser::Unwrap<parser::DoConstruct>(*it)
+                               : nullptr;
+    }
+  }
+}
+
+std::int64_t OmpStructureChecker::GetOrdCollapseLevel(
+    const parser::OpenMPLoopConstruct &x) {
+  const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)};
+  const auto &clauseList{std::get<parser::OmpClauseList>(beginLoopDir.t)};
+  std::int64_t orderedCollapseLevel{1};
+  std::int64_t orderedLevel{0};
+  std::int64_t collapseLevel{0};
+
+  for (const auto &clause : clauseList.v) {
+    if (const auto *collapseClause{
+            std::get_if<parser::OmpClause::Collapse>(&clause.u)}) {
+      if (const auto v{GetIntValue(collapseClause->v)}) {
+        collapseLevel = *v;
+      }
+    }
+    if (const auto *orderedClause{
+            std::get_if<parser::OmpClause::Ordered>(&clause.u)}) {
+      if (const auto v{GetIntValue(orderedClause->v)}) {
+        orderedLevel = *v;
+      }
+    }
+  }
+  if (orderedLevel >= collapseLevel) {
+    orderedCollapseLevel = orderedLevel;
+  } else {
+    orderedCollapseLevel = collapseLevel;
+  }
+  return orderedCollapseLevel;
+}
+
+void OmpStructureChecker::CheckCycleConstraints(
+    const parser::OpenMPLoopConstruct &x) {
+  std::int64_t ordCollapseLevel{GetOrdCollapseLevel(x)};
+  OmpCycleChecker ompCycleChecker{context_, ordCollapseLevel};
+  parser::Walk(x, ompCycleChecker);
+}
 
 void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &) {
   dirContext_.pop_back();
@@ -199,6 +324,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
     HasInvalidWorksharingNesting(
         beginDir.source, {llvm::omp::Directive::OMPD_do});
   }
+  CheckIfDoOrderedClause(beginDir);
 
   PushContextAndClauseSets(beginDir.source, beginDir.v);
   CheckNoBranching(block, beginDir.v, beginDir.source);
@@ -213,6 +339,18 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
   }
 }
 
+void OmpStructureChecker::CheckIfDoOrderedClause(
+    const parser::OmpBlockDirective &blkDirective) {
+  if (blkDirective.v == llvm::omp::OMPD_ordered) {
+    if (!FindClause(llvm::omp::Clause::OMPC_ordered)) {
+      context_.Say(blkDirective.source,
+          "The ORDERED clause must be present on the loop"
+          " construct if any ORDERED region ever binds"
+          " to a loop region arising from the loop construct."_err_en_US);
+    }
+  }
+}
+
 void OmpStructureChecker::Leave(const parser::OpenMPBlockConstruct &) {
   dirContext_.pop_back();
 }
@@ -583,7 +721,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Private &x) {
 
 void OmpStructureChecker::CheckIsVarPartOfAnotherVar(
     const parser::OmpObjectList &objList) {
-
   for (const auto &ompObject : objList.v) {
     std::visit(
         common::visitors{

diff  --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 0f42079c437d..c5d98d39d639 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -165,6 +165,12 @@ class OmpStructureChecker
   void CheckIsLoopIvPartOfClause(
       llvmOmpClause clause, const parser::OmpObjectList &ompObjectList);
   void CheckWorkshareBlockStmts(const parser::Block &, parser::CharBlock);
+
+  void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct &x);
+  void CheckDoWhile(const parser::OpenMPLoopConstruct &x);
+  void CheckCycleConstraints(const parser::OpenMPLoopConstruct &x);
+  std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);
+  void CheckIfDoOrderedClause(const parser::OmpBlockDirective &blkDirectiv);
 };
 } // namespace Fortran::semantics
 #endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_

diff  --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index a73357132e59..59cdf2060f57 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -1070,6 +1070,15 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) {
   }
   ClearDataSharingAttributeObjects();
   SetContextAssociatedLoopLevel(GetAssociatedLoopLevelFromClauses(clauseList));
+
+  if (beginDir.v == llvm::omp::Directive::OMPD_do) {
+    if (const auto &doConstruct{
+            std::get<std::optional<parser::DoConstruct>>(x.t)}) {
+      if (doConstruct.value().IsDoWhile()) {
+        return true;
+      }
+    }
+  }
   PrivatizeAssociatedLoopIndexAndCheckLoopLevel(x);
   return true;
 }

diff  --git a/flang/test/Semantics/omp-do06-positivecases.f90 b/flang/test/Semantics/omp-do06-positivecases.f90
new file mode 100644
index 000000000000..0776817edbaa
--- /dev/null
+++ b/flang/test/Semantics/omp-do06-positivecases.f90
@@ -0,0 +1,23 @@
+! RUN: %S/test_symbols.sh %s %t %f18 -fopenmp
+! OpenMP Version 4.5
+! 2.7.1 Loop Construct
+! The ordered clause must be present on the loop construct if any ordered
+! region ever binds to a loop region arising from the loop construct.
+
+! A positive case
+!DEF: /omp_do MainProgram
+program omp_do
+  !DEF: /omp_do/i ObjectEntity INTEGER(4)
+  !DEF: /omp_do/j ObjectEntity INTEGER(4)
+  !DEF: /omp_do/k ObjectEntity INTEGER(4)
+  integer i, j, k
+  !$omp do  ordered
+    !DEF: /omp_do/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+    do i=1,10
+      !$omp ordered
+      !DEF: /my_func EXTERNAL (Subroutine) ProcEntity
+      call my_func
+      !$omp end ordered
+    end do
+  !$omp end do
+end program omp_do

diff  --git a/flang/test/Semantics/omp-do06.f90 b/flang/test/Semantics/omp-do06.f90
index bcba318d2178..d68767904751 100644
--- a/flang/test/Semantics/omp-do06.f90
+++ b/flang/test/Semantics/omp-do06.f90
@@ -1,6 +1,4 @@
 ! RUN: %S/test_errors.sh %s %t %flang -fopenmp
-! XFAIL:*
-
 ! OpenMP Version 4.5
 ! 2.7.1 Loop Construct
 ! The ordered clause must be present on the loop construct if any ordered
@@ -11,11 +9,25 @@ program omp_do
 
   !$omp do
   do i = 1, 10
-    !ERROR: ‘ordered’ region inside a loop region without an ordered clause.
+    !ERROR: The ORDERED clause must be present on the loop construct if any ORDERED region ever binds to a loop region arising from the loop construct.
     !$omp ordered
     call my_func()
     !$omp end ordered
   end do
   !$omp end do
 
+  !$omp do ordered private(i)
+  do i = 1, 10
+    !$omp parallel do
+    do j = 1, 10
+      print *,i
+      !ERROR: The ORDERED clause must be present on the loop construct if any ORDERED region ever binds to a loop region arising from the loop construct.
+      !$omp ordered
+      print *,i
+      !$omp end ordered
+    end do
+    !$omp end parallel do
+  end do
+  !$omp end do
+
 end program omp_do

diff  --git a/flang/test/Semantics/omp-do08.f90 b/flang/test/Semantics/omp-do08.f90
index 58e77b71e288..3ec7ac30b243 100644
--- a/flang/test/Semantics/omp-do08.f90
+++ b/flang/test/Semantics/omp-do08.f90
@@ -1,19 +1,138 @@
 ! RUN: %S/test_errors.sh %s %t %flang -fopenmp
-! XFAIL: *
-
 ! OpenMP Version 4.5
 ! 2.7.1 Loop Construct
 
-program omp_do
+program omp
   integer i, j, k
-  !$omp do collapse(2)
-  do i = 1, 10
-    !ERROR: CYCLE statement to non-innermost collapsed !$OMP DO loop
-    if (i .lt. 5) cycle
-    do j = 1, 10
-      print *, "Hello"
+
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do  collapse(3)
+  do i = 0, 10
+    !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+    if (i .lt. 1) cycle
+    do j = 0, 10
+      do k  = 0, 10
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do  collapse(3)
+  do i = 0, 10
+    do j = 0, 10
+      !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+      if (i .lt. 1) cycle
+      do k  = 0, 10
+        print *, i, j, k
+      end do
     end do
   end do
   !$omp end do
 
-end program omp_do
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do  collapse(2)
+  do i = 0, 10
+    !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+    if (i .lt. 1) cycle
+    do j = 0, 10
+      do k  = 0, 10
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do  collapse(2)
+  foo: do i = 0, 10
+    !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+    if (i .lt. 1) cycle foo
+    do j = 0, 10
+      do k  = 0, 10
+        print *, i, j, k
+      end do
+    end do
+  end do foo
+  !$omp end do
+
+
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do collapse(3)
+  do 60 i=2,200,2
+    do j=1,10
+      !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+      if(i==100) cycle
+      do k=1,10
+        print *,i
+      end do
+    end do
+  60 continue
+  !$omp end do
+
+  !$omp do  collapse(3)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+         foo2:  do k  = 0, 10
+             !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+             if (k .lt. 1) cycle foo
+             print *, i, j, k
+           end do foo2
+         end do foo1
+  end do foo
+  !$omp end do
+
+  !$omp do  collapse(3)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+         foo2:  do k  = 0, 10
+             !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+             if (k .lt. 1) cycle foo1
+             print *, i, j, k
+           end do foo2
+         end do foo1
+  end do foo
+  !$omp end do
+
+
+  !$omp do  collapse(2)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+         foo2:  do k  = 0, 10
+             !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+             if (k .lt. 1) cycle foo
+             print *, i, j, k
+           end do foo2
+         end do foo1
+  end do foo
+  !$omp end do
+
+
+  !$omp do  ordered(2)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+             !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+             if (k .lt. 1) cycle foo
+         foo2:  do k  = 0, 10
+             print *, i, j, k
+           end do foo2
+         end do foo1
+  end do foo
+  !$omp end do
+
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do  collapse(2) ordered(3)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+             !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+             if (k .lt. 1) cycle foo
+         foo2:  do k  = 0, 10
+             print *, i, j, k
+           end do foo2
+         end do foo1
+  end do foo
+  !$omp end do
+
+end program omp

diff  --git a/flang/test/Semantics/omp-do09.f90 b/flang/test/Semantics/omp-do09.f90
index 22a9b56983e8..9ce2757d04ba 100644
--- a/flang/test/Semantics/omp-do09.f90
+++ b/flang/test/Semantics/omp-do09.f90
@@ -1,22 +1,26 @@
-! RUN: %S/test_errors.sh %s %t %flang -fopenmp
-! XFAIL: *
-
+! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
 ! OpenMP Version 4.5
 ! 2.7.1 Loop Construct
 ! The do-loop cannot be a DO WHILE or a DO loop without loop control.
 
 program omp_do
-  integer i, j, k
-  i = 0
+  integer ::  i = 0,k
+  !$omp do
+  !ERROR: The DO loop cannot be a DO WHILE with DO directive.
+  do while (i <= 10)
+    print *, "it",i
+    i = i+1
+  end do
+  !$omp end do
 
   !$omp do
-  !ERROR: !$OMP DO cannot be a DO WHILE or DO without loop control
-  do while (i .lt. 10)
-    do j = 1, 10
-      print *, "Hello"
+  !ERROR: The DO loop cannot be a DO WHILE with DO directive.
+  do while (i <= 10)
+    do while (j <= 10)
+      print *, "it",k
+      j = j+1
     end do
-    i = i + 1
+    i = i+1
   end do
   !$omp end do
-
 end program omp_do

diff  --git a/flang/test/Semantics/omp-do10.f90 b/flang/test/Semantics/omp-do10.f90
index cc2071d874b5..b06065c31631 100644
--- a/flang/test/Semantics/omp-do10.f90
+++ b/flang/test/Semantics/omp-do10.f90
@@ -1,18 +1,37 @@
-! RUN: %S/test_errors.sh %s %t %flang -fopenmp
-! XFAIL: *
-
+! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
 ! OpenMP Version 4.5
 ! 2.7.1 Loop Construct
-! The do-loop iteration variable must be of type integer.
+! The DO loop iteration variable must be of type integer.
 
 program omp_do
   real i, j, k
-
   !$omp do
-  !ERROR: The do-loop iteration variable must be of type integer.
+  !ERROR: The DO loop iteration variable must be of the type integer.
+  do i = 1, 10
+    !ERROR: The DO loop iteration variable must be of the type integer.
+    do j = 1, 10
+      print *, "it", i, j
+    end do
+  end do
+  !$omp end do
+
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do collapse(3)
+  !ERROR: The DO loop iteration variable must be of the type integer.
+  do i = 1, 10
+    !ERROR: The DO loop iteration variable must be of the type integer.
+    do j = 1, 10
+      print *, "it", i, j
+    end do
+  end do
+  !$omp end do
+
+  !$omp do collapse(2)
+  !ERROR: The DO loop iteration variable must be of the type integer.
   do i = 1, 10
+    !ERROR: The DO loop iteration variable must be of the type integer.
     do j = 1, 10
-      print *, "Hello"
+      print *, "it", i, j
     end do
   end do
   !$omp end do

diff  --git a/flang/test/Semantics/omp-do11.f90 b/flang/test/Semantics/omp-do11.f90
new file mode 100644
index 000000000000..7ce034c8c57f
--- /dev/null
+++ b/flang/test/Semantics/omp-do11.f90
@@ -0,0 +1,36 @@
+! RUN: %S/test_symbols.sh %s %t %f18 -fopenmp
+! OpenMP Version 4.5
+! 2.7.1 Do Loop Constructs
+
+!DEF: /omp_do MainProgram
+program omp_do
+  !DEF: /omp_do/i ObjectEntity INTEGER(4)
+  !DEF: /omp_do/j ObjectEntity INTEGER(4)
+  !DEF: /omp_do/k ObjectEntity INTEGER(4)
+  integer i, j, k
+  !$omp do
+  !DEF: /omp_do/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+  do i=1,10
+    !REF: /omp_do/j
+    do j=1,10
+      !REF: /omp_do/Block1/i
+      !REF: /omp_do/j
+      print *, "it", i, j
+    end do
+  end do
+  !$omp end do
+end program omp_do
+
+!DEF: /omp_do2 MainProgram
+program omp_do2
+  !DEF: /omp_do2/i ObjectEntity INTEGER(4)
+  !DEF: /omp_do2/k ObjectEntity INTEGER(4)
+  integer :: i = 0, k
+  !$omp do
+  !DEF: /omp_do2/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+  do i=1,10
+    !REF: /omp_do2/Block1/i
+    print *, "it", i
+  end do
+  !$omp end do
+end program omp_do2

diff  --git a/flang/test/Semantics/omp-do12.f90 b/flang/test/Semantics/omp-do12.f90
new file mode 100644
index 000000000000..baabb7e82d4d
--- /dev/null
+++ b/flang/test/Semantics/omp-do12.f90
@@ -0,0 +1,96 @@
+! RUN: %S/test_symbols.sh %s %t %f18 -fopenmp
+! OpenMP Version 4.5
+! 2.7.1 Do Loop constructs.
+
+!DEF: /omp_cycle MainProgram
+program omp_cycle
+  !$omp do  collapse(1)
+  !DEF: /omp_cycle/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+  do i=0,10
+    !REF: /omp_cycle/Block1/i
+    if (i<1) cycle
+    !DEF: /omp_cycle/j (Implicit) ObjectEntity INTEGER(4)
+    do j=0,10
+      !DEF: /omp_cycle/k (Implicit) ObjectEntity INTEGER(4)
+      do k=0,10
+        !REF: /omp_cycle/Block1/i
+        !REF: /omp_cycle/j
+        !REF: /omp_cycle/k
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+  !$omp do  collapse(1)
+  !DEF: /omp_cycle/Block2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+  do i=0,10
+    !REF: /omp_cycle/j
+    do j=0,10
+      !REF: /omp_cycle/Block2/i
+      if (i<1) cycle
+      !REF: /omp_cycle/k
+      do k=0,10
+        !REF: /omp_cycle/Block2/i
+        !REF: /omp_cycle/j
+        !REF: /omp_cycle/k
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+  !$omp do  collapse(2)
+  !DEF: /omp_cycle/Block3/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+  do i=0,10
+    !DEF: /omp_cycle/Block3/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+    do j=0,10
+      !REF: /omp_cycle/k
+      do k=0,10
+        !REF: /omp_cycle/Block3/i
+        if (i<1) cycle
+        !REF: /omp_cycle/Block3/i
+        !REF: /omp_cycle/Block3/j
+        !REF: /omp_cycle/k
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+  !$omp do  collapse(3)
+  !DEF: /omp_cycle/Block4/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+  do i=0,10
+    !DEF: /omp_cycle/Block4/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+    do j=0,10
+      !DEF: /omp_cycle/Block4/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+      do k=0,10
+        !REF: /omp_cycle/Block4/i
+        if (i<1) cycle
+        !REF: /omp_cycle/Block4/i
+        !REF: /omp_cycle/Block4/j
+        !REF: /omp_cycle/Block4/k
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+  !$omp do  collapse(3)
+  !DEF: /omp_cycle/Block5/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+  foo:do i=0,10
+    !DEF: /omp_cycle/Block5/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+    foo1:do j=0,10
+      !DEF: /omp_cycle/Block5/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+      foo2:do k=0,10
+        !REF: /omp_cycle/Block5/i
+        if (i<1) cycle foo2
+        !REF: /omp_cycle/Block5/i
+        !REF: /omp_cycle/Block5/j
+        !REF: /omp_cycle/Block5/k
+        print *, i, j, k
+      end do foo2
+    end do foo1
+  end do foo
+  !$omp end do
+end program omp_cycle

diff  --git a/flang/test/Semantics/omp-do13.f90 b/flang/test/Semantics/omp-do13.f90
new file mode 100644
index 000000000000..3a4fb9a71fd2
--- /dev/null
+++ b/flang/test/Semantics/omp-do13.f90
@@ -0,0 +1,185 @@
+! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
+! OpenMP Version 4.5
+! 2.7.1 Loop Construct
+
+program omp
+  integer i, j, k
+
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do  collapse(3)
+  do i = 0, 10
+    !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+    cycle
+    do j = 0, 10
+      do k  = 0, 10
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do  collapse(3)
+  do i = 0, 10
+    do j = 0, 10
+      !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+      cycle
+      do k  = 0, 10
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do  collapse(2)
+  do i = 0, 10
+    !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+    cycle
+    do j = 0, 10
+      do k  = 0, 10
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do  collapse(2)
+  foo: do i = 0, 10
+    !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+    cycle foo
+    do j = 0, 10
+      do k  = 0, 10
+        print *, i, j, k
+      end do
+    end do
+  end do foo
+  !$omp end do
+
+
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do collapse(3)
+  do 60 i=1,10
+    do j=1,10
+      !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+      cycle
+      do k=1,10
+        print *,i
+      end do
+    end do
+  60 continue
+  !$omp end do
+
+  !$omp do  collapse(3)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+         foo2:  do k  = 0, 10
+             !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+             cycle foo
+             print *, i, j, k
+           end do foo2
+         end do foo1
+  end do foo
+  !$omp end do
+
+  !$omp do  collapse(3)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+         foo2:  do k  = 0, 10
+             !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+              cycle foo1
+             print *, i, j, k
+           end do foo2
+         end do foo1
+  end do foo
+  !$omp end do
+
+
+  !$omp do  collapse(2)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+         foo2:  do k  = 0, 10
+             !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+             cycle foo
+             print *, i, j, k
+           end do foo2
+         end do foo1
+  end do foo
+  !$omp end do
+
+
+  !$omp do  collapse(2)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+             !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+             cycle foo
+         foo2:  do k  = 0, 10
+             print *, i, j, k
+           end do foo2
+         end do foo1
+  end do foo
+  !$omp end do
+
+  !$omp do  ordered(2)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+      !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+      cycle foo
+      !ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region
+      !$omp do  collapse(1)
+      foo2:  do k  = 0, 10
+        print *, i, j, k
+        end do foo2
+     !$omp end do
+     end do foo1
+  end do foo
+  !$omp end do
+
+  !$omp parallel
+  !$omp do collapse(2)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+      !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+      cycle foo
+      !$omp parallel
+      !$omp do collapse(2)
+      foo2:  do k  = 0, 10
+        foo3:  do l  = 0, 10
+          print *, i, j, k, l
+          !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+          cycle foo2
+        end do foo3
+      end do foo2
+      !$omp end do
+      !$omp end parallel
+    end do foo1
+  end do foo
+  !$omp end do
+  !$omp end parallel
+
+  !$omp parallel
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp parallel do ordered(3) collapse(2)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+      !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+      cycle foo
+      !$omp parallel
+      !$omp parallel do collapse(2)
+      foo2:  do k  = 0, 10
+        foo3:  do l  = 0, 10
+          print *, i, j, k, l
+          !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+          cycle foo2
+        end do foo3
+      end do foo2
+      !$omp end parallel do
+      !$omp end parallel
+    end do foo1
+  end do foo
+!$omp end parallel do
+!$omp end parallel
+
+end program omp

diff  --git a/flang/test/Semantics/omp-do14.f90 b/flang/test/Semantics/omp-do14.f90
new file mode 100644
index 000000000000..df4a369095e2
--- /dev/null
+++ b/flang/test/Semantics/omp-do14.f90
@@ -0,0 +1,91 @@
+! RUN: %S/test_symbols.sh %s %t %f18 -fopenmp
+! OpenMP Version 4.5
+! 2.7.1 Do Loop constructs.
+
+!DEF: /omp_cycle MainProgram
+program omp_cycle
+  !$omp do  collapse(1)
+  !DEF: /omp_cycle/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+  do i=0,10
+    cycle
+    !DEF: /omp_cycle/j (Implicit) ObjectEntity INTEGER(4)
+    do j=0,10
+      !DEF: /omp_cycle/k (Implicit) ObjectEntity INTEGER(4)
+      do k=0,10
+        !REF: /omp_cycle/Block1/i
+        !REF: /omp_cycle/j
+        !REF: /omp_cycle/k
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+  !$omp do  collapse(1)
+  !DEF: /omp_cycle/Block2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+  do i=0,10
+    !REF: /omp_cycle/j
+    do j=0,10
+      cycle
+      !REF: /omp_cycle/k
+      do k=0,10
+        !REF: /omp_cycle/Block2/i
+        !REF: /omp_cycle/j
+        !REF: /omp_cycle/k
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+  !$omp do  collapse(2)
+  !DEF: /omp_cycle/Block3/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+  do i=0,10
+    !DEF: /omp_cycle/Block3/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+    do j=0,10
+      !REF: /omp_cycle/k
+      do k=0,10
+        cycle
+        !REF: /omp_cycle/Block3/i
+        !REF: /omp_cycle/Block3/j
+        !REF: /omp_cycle/k
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+  !$omp do  collapse(3)
+  !DEF: /omp_cycle/Block4/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+  do i=0,10
+    !DEF: /omp_cycle/Block4/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+    do j=0,10
+      !DEF: /omp_cycle/Block4/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+      do k=0,10
+        cycle
+        !REF: /omp_cycle/Block4/i
+        !REF: /omp_cycle/Block4/j
+        !REF: /omp_cycle/Block4/k
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+  !$omp do  ordered(3)
+  !DEF: /omp_cycle/Block5/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+  foo:do i=0,10
+    !DEF: /omp_cycle/Block5/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+    foo1:do j=0,10
+      !DEF: /omp_cycle/Block5/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+      foo2:do k=0,10
+        cycle foo2
+        !REF: /omp_cycle/Block5/i
+        !REF: /omp_cycle/Block5/j
+        !REF: /omp_cycle/Block5/k
+        print *, i, j, k
+      end do foo2
+    end do foo1
+  end do foo
+  !$omp end do
+end program omp_cycle

diff  --git a/flang/test/Semantics/omp-do15.f90 b/flang/test/Semantics/omp-do15.f90
new file mode 100644
index 000000000000..955e6aad69bb
--- /dev/null
+++ b/flang/test/Semantics/omp-do15.f90
@@ -0,0 +1,94 @@
+! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
+! OpenMP Version 4.5
+! 2.7.1 Loop Construct
+
+program omp
+  integer i, j, k
+
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do  collapse(3)
+  do i = 0, 10
+    if (i .lt. 1) then
+      !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+      cycle
+    end if
+    do j = 0, 10
+      do k  = 0, 10
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do  collapse(3)
+  do i = 0, 10
+    do j = 0, 10
+      if (i .lt. 1) then
+        !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+        cycle
+      end if
+      do k  = 0, 10
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+  !!ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do  collapse(2)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+      if (i .lt. 1) then
+        !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+        cycle foo
+      else if (i .gt. 3) then
+        cycle foo1
+      end if
+      do k  = 0, 10
+        print *, i, j, k
+      end do
+    end do foo1
+  end do foo
+  !$omp end do
+
+
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do  collapse(3)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+      if (i .lt. 1) then
+        !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+        cycle foo
+      else if (i .gt. 3) then
+        !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+        cycle foo1
+      end if
+         foo2:  do k  = 0, 10
+             print *, i, j, k
+           end do foo2
+         end do foo1
+  end do foo
+  !$omp end do
+
+  !$omp do  ordered(3)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+         foo2:  do k  = 0, 10
+           if (i .lt. 1) then
+             !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+             cycle foo
+           else if (i .gt. 3) then
+             !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+             cycle foo1
+          else
+             !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+             cycle foo
+          end if
+             print *, i, j, k
+           end do foo2
+         end do foo1
+  end do foo
+  !$omp end do
+
+end program omp

diff  --git a/flang/test/Semantics/omp-do16.f90 b/flang/test/Semantics/omp-do16.f90
new file mode 100644
index 000000000000..05cd817986ff
--- /dev/null
+++ b/flang/test/Semantics/omp-do16.f90
@@ -0,0 +1,77 @@
+! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
+! OpenMP Version 4.5
+! 2.7.1 Loop Construct
+
+program omp
+  integer i, j, k
+
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do  collapse(3)
+  do i = 0, 10
+    select case (i)
+    case(1)
+      !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+      cycle
+    end select
+    do j = 0, 10
+      do k  = 0, 10
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+  !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+  !$omp do  collapse(3)
+  do i = 0, 10
+    do j = 0, 10
+      select case (i)
+      case(1)
+        !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+        cycle
+      end select
+      do k  = 0, 10
+        print *, i, j, k
+      end do
+    end do
+  end do
+  !$omp end do
+
+  !$omp do  collapse(2)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+      select case (i)
+      case(1)
+        !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+        cycle foo
+      case(5)
+        cycle foo1
+      end select
+      do k  = 0, 10
+        print *, i, j, k
+      end do
+    end do foo1
+  end do foo
+  !$omp end do
+
+  !$omp do  ordered(3)
+  foo: do i = 0, 10
+    foo1: do j = 0, 10
+      foo2: do k  = 0, 10
+        select case (i)
+        case(1)
+          !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+          cycle foo
+        case(5)
+          !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
+          cycle foo1
+        case(7)
+          cycle foo2
+        end select
+        print *, i, j, k
+      end do foo2
+    end do foo1
+  end do foo
+  !$omp end do
+
+end program omp

diff  --git a/flang/test/Semantics/omp-do17.f90 b/flang/test/Semantics/omp-do17.f90
new file mode 100644
index 000000000000..54f315cd927b
--- /dev/null
+++ b/flang/test/Semantics/omp-do17.f90
@@ -0,0 +1,57 @@
+! RUN: %S/test_symbols.sh %s %t %f18 -fopenmp
+! OpenMP Version 4.5
+! 2.7.1 Do Loop constructs.
+
+!DEF: /test MainProgram
+program test
+ !DEF: /test/i ObjectEntity INTEGER(4)
+ !DEF: /test/j ObjectEntity INTEGER(4)
+ !DEF: /test/k ObjectEntity INTEGER(4)
+ integer i, j, k
+ !$omp do  collapse(2)
+ !DEF: /test/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+ foo: do i=0,10
+  !DEF: /test/Block1/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+  foo1: do j=0,10
+   !REF: /test/k
+   foo2: do k=0,10
+    !REF: /test/Block1/i
+    select case (i)
+    case (5)
+     cycle foo1
+    case (7)
+     cycle foo2
+    end select
+    !REF: /test/Block1/i
+    !REF: /test/Block1/j
+    !REF: /test/k
+    print *, i, j, k
+   end do foo2
+  end do foo1
+ end do foo
+
+ !$omp do  collapse(2)
+ !DEF: /test/Block2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+ foo: do i=0,10
+  !DEF: /test/Block2/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+  foo1: do j=0,10
+   !REF: /test/k
+   foo2: do k=0,10
+    !REF: /test/Block2/i
+    if (i<3) then
+     cycle foo1
+     !REF: /test/Block2/i
+    else if (i>8) then
+     cycle foo1
+    else
+     cycle foo2
+    end if
+    !REF: /test/Block2/i
+    !REF: /test/Block2/j
+    !REF: /test/k
+    print *, i, j, k
+   end do foo2
+  end do foo1
+ end do foo
+!$omp end do
+end program test


        


More information about the flang-commits mailing list