[flang-commits] [flang] 3ee7caa - [flang][OpenMP] Use the LoopSequence-based checks (#185300)

via flang-commits flang-commits at lists.llvm.org
Tue Mar 17 07:55:19 PDT 2026


Author: Krzysztof Parzyszek
Date: 2026-03-17T09:55:14-05:00
New Revision: 3ee7caa273871a3e3178d53a5f8b29ffcf0b8ff2

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

LOG: [flang][OpenMP] Use the LoopSequence-based checks (#185300)

Turn on the new loop-construct checks. Remove some checks from
resolve-directives.cpp which are now done in the semantic analysis.
Update tests.

Issue: https://github.com/llvm/llvm-project/issues/185287

Added: 
    

Modified: 
    flang/include/flang/Semantics/openmp-utils.h
    flang/lib/Semantics/check-omp-loop.cpp
    flang/lib/Semantics/check-omp-structure.h
    flang/lib/Semantics/openmp-utils.cpp
    flang/lib/Semantics/resolve-directives.cpp
    flang/test/Semantics/OpenMP/do-collapse.f90
    flang/test/Semantics/OpenMP/do-concurrent-collapse.f90
    flang/test/Semantics/OpenMP/do-ordered.f90
    flang/test/Semantics/OpenMP/do08.f90
    flang/test/Semantics/OpenMP/do10.f90
    flang/test/Semantics/OpenMP/do13.f90
    flang/test/Semantics/OpenMP/do15.f90
    flang/test/Semantics/OpenMP/do16.f90
    flang/test/Semantics/OpenMP/do22.f90
    flang/test/Semantics/OpenMP/fuse1.f90
    flang/test/Semantics/OpenMP/interchange-permutation.f90
    flang/test/Semantics/OpenMP/interchange01.f90
    flang/test/Semantics/OpenMP/loop-transformation-clauses01.f90
    flang/test/Semantics/OpenMP/tile05.f90
    flang/test/Semantics/OpenMP/tile07.f90

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Semantics/openmp-utils.h b/flang/include/flang/Semantics/openmp-utils.h
index 23bfd6a8de088..cd599237e4182 100644
--- a/flang/include/flang/Semantics/openmp-utils.h
+++ b/flang/include/flang/Semantics/openmp-utils.h
@@ -121,6 +121,7 @@ struct Reason {
     return *this;
   };
   operator bool() const { return !msgs.empty(); }
+  parser::Message &AttachTo(parser::Message &msg);
 };
 
 std::pair<std::optional<int64_t>, Reason> GetArgumentValueWithReason(

diff  --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index b4e38a8e68e56..01d07e30d3ce5 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -245,6 +245,7 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) {
 void OmpStructureChecker::CheckNestedConstruct(
     const parser::OpenMPLoopConstruct &x) {
   const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()};
+  llvm::omp::Directive dir{beginSpec.DirId()};
   unsigned version{context_.langOptions().OpenMPVersion};
 
   // End-directive is not allowed in such cases:
@@ -268,8 +269,8 @@ void OmpStructureChecker::CheckNestedConstruct(
   // Check constructs contained in the body of the loop construct.
   auto &body{std::get<parser::Block>(x.t)};
   for (auto &stmt : BlockRange(body, BlockRange::Step::Over)) {
-    if (auto *dir{parser::Unwrap<parser::CompilerDirective>(stmt)}) {
-      context_.Say(dir->source,
+    if (auto *d{parser::Unwrap<parser::CompilerDirective>(stmt)}) {
+      context_.Say(d->source,
           "Compiler directives are not allowed inside OpenMP loop constructs"_warn_en_US);
     } else if (auto *omp{parser::Unwrap<parser::OpenMPLoopConstruct>(stmt)}) {
       if (!IsLoopTransforming(omp->BeginDir().DirId())) {
@@ -291,19 +292,66 @@ void OmpStructureChecker::CheckNestedConstruct(
 
   // Check if a loop-nest-associated construct has only one top-level loop
   // in it.
+  auto [needFirst, needCount, rangeReason]{
+      GetAffectedLoopRangeWithReason(x, version)};
+
   if (std::optional<int64_t> numLoops{sequence.length()}) {
     if (*numLoops == 0) {
       context_.Say(beginSpec.DirName().source,
           "This construct should contain a DO-loop or a loop-nest-generating OpenMP construct"_err_en_US);
     } else {
-      auto assoc{llvm::omp::getDirectiveAssociation(beginSpec.DirName().v)};
+      auto assoc{llvm::omp::getDirectiveAssociation(dir)};
       if (*numLoops > 1 && assoc == llvm::omp::Association::LoopNest) {
         context_.Say(beginSpec.DirName().source,
             "This construct applies to a loop nest, but has a loop sequence of "
             "length %" PRId64 ""_err_en_US,
             *numLoops);
       }
+      if (assoc == llvm::omp::Association::LoopSeq) {
+        if (auto requiredCount{GetRequiredCount(needFirst, needCount)}) {
+          if (*requiredCount > 0 && *numLoops < *requiredCount) {
+            auto &msg{context_.Say(beginSpec.DirName().source,
+                "This construct requires a sequence of %" PRId64
+                " loops, but the loop sequence has a length of %" PRId64
+                ""_err_en_US,
+                *requiredCount, *numLoops)};
+            rangeReason.AttachTo(msg);
+          }
+        }
+      }
+    }
+  }
+
+  // Check requirements on nest depth.
+  auto [needDepth, needPerfect, depthReason]{
+      GetAffectedNestDepthWithReason(x, version)};
+  auto [haveSema, havePerf]{sequence.depth()};
+
+  if (dir != llvm::omp::Directive::OMPD_fuse) {
+    auto haveDepth = needPerfect ? havePerf : haveSema;
+    // If the present depth is 0, it's likely that the construct doesn't
+    // have any loops in it, which would be diagnosed above.
+    if (needDepth && haveDepth && *haveDepth > 0) {
+      if (*needDepth > *haveDepth) {
+        if (needPerfect) {
+          auto &msg{context_.Say(beginSpec.DirName().source,
+              "This construct requires a perfect nest of depth %" PRId64
+              ", but the associated nest is a perfect nest of depth %" PRId64
+              ""_err_en_US,
+              *needDepth, *haveDepth)};
+          depthReason.AttachTo(msg);
+        } else {
+          auto &msg{context_.Say(beginSpec.DirName().source,
+              "This construct requires a nest of depth %" PRId64
+              ", but the associated nest has a depth of %" PRId64 ""_err_en_US,
+              *needDepth, *haveDepth)};
+          depthReason.AttachTo(msg);
+        }
+      }
     }
+  } else {
+    // FUSE requires a sequence of perfect nests.
+    // TODO: Defer this check for now.
   }
 }
 
@@ -504,29 +552,6 @@ void OmpStructureChecker::CheckDistLinear(
   }
 }
 
-void OmpStructureChecker::CheckLooprangeBounds(
-    const parser::OpenMPLoopConstruct &x) {
-  unsigned version{context_.langOptions().OpenMPVersion};
-  if (auto *clause{parser::omp::FindClause(
-          x.BeginDir(), llvm::omp::Clause::OMPC_looprange)}) {
-    auto *lrClause{parser::Unwrap<parser::OmpLooprangeClause>(clause)};
-    auto first{GetIntValue(std::get<0>(lrClause->t))};
-    auto count{GetIntValue(std::get<1>(lrClause->t))};
-    if (auto requiredCount{GetRequiredCount(first, count)}) {
-      LoopSequence sequence(std::get<parser::Block>(x.t), version, true);
-      if (auto loopCount{sequence.length()}) {
-        if (*loopCount < *requiredCount) {
-          context_.Say(clause->source,
-              "The specified loop range requires %" PRId64
-              " loops, but the loop sequence has a length of %" PRId64
-              ""_err_en_US,
-              *requiredCount, *loopCount);
-        }
-      }
-    }
-  }
-}
-
 void OmpStructureChecker::CheckScanModifier(
     const parser::OmpClause::Reduction &x) {
   using ReductionModifier = parser::OmpReductionModifier;
@@ -575,9 +600,6 @@ void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &x) {
       CheckScanModifier(*reduction);
     }
   }
-  if (beginSpec.DirName().v == llvm::omp::Directive::OMPD_fuse) {
-    CheckLooprangeBounds(x);
-  }
   if (llvm::omp::allSimdSet.test(beginSpec.DirName().v)) {
     ExitDirectiveNest(SIMDNest);
   }

diff  --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index cd98334ad8662..dc84c9d9ae9d8 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -326,7 +326,6 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
   void CheckAtomicUpdate(const parser::OpenMPAtomicConstruct &x);
 
   void CheckScanModifier(const parser::OmpClause::Reduction &x);
-  void CheckLooprangeBounds(const parser::OpenMPLoopConstruct &x);
   void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
   void CheckSIMDNest(const parser::OpenMPConstruct &x);
   void CheckNestedConstruct(const parser::OpenMPLoopConstruct &x);

diff  --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index 4a600ff4bdf84..8abf008a72147 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -532,6 +532,11 @@ MaybeExpr MakeEvaluateExpr(const parser::OmpStylizedInstance &inp) {
       instance.u);
 }
 
+parser::Message &Reason::AttachTo(parser::Message &msg) {
+  msgs.AttachTo(msg);
+  return msg;
+}
+
 std::pair<std::optional<int64_t>, Reason> GetArgumentValueWithReason(
     const parser::OmpDirectiveSpecification &spec, llvm::omp::Clause clauseId,
     unsigned version) {
@@ -550,19 +555,42 @@ std::pair<std::optional<int64_t>, Reason> GetArgumentValueWithReason(
   return {std::nullopt, Reason()};
 }
 
+template <typename T>
+static std::pair<std::optional<int64_t>, Reason>
+GetNumArgumentsWithReasonForType(
+    const parser::OmpClause &clause, const std::string &name) {
+  if (auto *args{parser::Unwrap<std::list<T>>(clause.u)}) {
+    auto num{static_cast<int64_t>(args->size())};
+    Reason reason;
+    reason.Say(clause.source,
+        "%s clause was specified with %" PRId64 " arguments"_because_en_US,
+        name.c_str(), num);
+    return {num, std::move(reason)};
+  }
+  return {std::nullopt, Reason()};
+}
+
 std::pair<std::optional<int64_t>, Reason> GetNumArgumentsWithReason(
     const parser::OmpDirectiveSpecification &spec, llvm::omp::Clause clauseId,
     unsigned version) {
   if (auto *clause{parser::omp::FindClause(spec, clauseId)}) {
-    using ArgumentList = std::list<parser::ScalarIntExpr>;
-    if (auto *args{parser::Unwrap<ArgumentList>(clause->u)}) {
-      std::string name{GetUpperName(clauseId, version)};
-      auto num{static_cast<int64_t>(args->size())};
-      Reason reason;
-      reason.Say(clause->source,
-          "%s clause was specified with %" PRId64 " arguments"_because_en_US,
-          name.c_str(), num);
-      return {num, std::move(reason)};
+    std::string name{GetUpperName(clauseId, version)};
+    // Try the types used for list items.
+    {
+      using Ty = parser::ScalarIntExpr;
+      if (auto [num, reason]{
+              GetNumArgumentsWithReasonForType<Ty>(*clause, name)};
+          num) {
+        return {num, std::move(reason)};
+      }
+    }
+    {
+      using Ty = parser::ScalarIntConstantExpr;
+      if (auto [num, reason]{
+              GetNumArgumentsWithReasonForType<Ty>(*clause, name)};
+          num) {
+        return {num, std::move(reason)};
+      }
     }
   }
   return {std::nullopt, Reason()};
@@ -789,9 +817,20 @@ std::tuple<std::optional<int64_t>, bool, Reason> GetAffectedNestDepthWithReason(
     switch (dir) {
     case llvm::omp::Directive::OMPD_interchange: {
       // Get the length of the argument list to PERMUTATION.
-      auto [num, reason]{GetNumArgumentsWithReason(
-          beginSpec, llvm::omp::Clause::OMPC_permutation, version)};
-      return {num, true, std::move(reason)};
+      if (parser::omp::FindClause(
+              beginSpec, llvm::omp::Clause::OMPC_permutation)) {
+        auto [num, reason]{GetNumArgumentsWithReason(
+            beginSpec, llvm::omp::Clause::OMPC_permutation, version)};
+        return {num, true, std::move(reason)};
+      }
+      // PERMUTATION not specified, assume PERMUTATION(2, 1).
+      std::string name{parser::omp::GetUpperName(
+          llvm::omp::Clause::OMPC_permutation, version)};
+      Reason reason;
+      reason.Say(beginSpec.source,
+          "%s clause was not specified, %s(2, 1) was assumed"_because_en_US,
+          name.c_str(), name.c_str());
+      return {2, true, std::move(reason)};
     }
     case llvm::omp::Directive::OMPD_stripe:
     case llvm::omp::Directive::OMPD_tile: {
@@ -799,7 +838,6 @@ std::tuple<std::optional<int64_t>, bool, Reason> GetAffectedNestDepthWithReason(
       auto [num, reason]{GetNumArgumentsWithReason(
           beginSpec, llvm::omp::Clause::OMPC_sizes, version)};
       return {num, true, std::move(reason)};
-      return {std::nullopt, true, Reason()};
     }
     case llvm::omp::Directive::OMPD_fuse: {
       // Get the value from the argument to DEPTH.

diff  --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 1be0da6562720..96f66246ac676 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -1123,7 +1123,6 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
 
   void CheckDataCopyingClause(
       const parser::Name &, const Symbol &, Symbol::Flag);
-  void CheckAssocLoopLevel(std::int64_t level, const parser::OmpClause *clause);
   void CheckObjectIsPrivatizable(
       const parser::Name &, const Symbol &, Symbol::Flag);
   void CheckSourceLabel(const parser::Label &);
@@ -2157,11 +2156,6 @@ std::int64_t OmpAttributeVisitor::SetAssociatedMaxClause(
   for (auto [level, clause] : llvm::zip_equal(levels, clauses)) {
     if (clause && isCollapseClause(clause) && tileLevel > 0 &&
         tileLevel < level) {
-      context_.Say(clause->source,
-          "The value of the parameter in the COLLAPSE clause must"
-          " not be larger than the number of the number of tiled loops"
-          " because collapse currently is limited to independent loop"
-          " iterations."_err_en_US);
       return 1;
     }
 
@@ -2310,41 +2304,14 @@ void OmpAttributeVisitor::CheckPerfectNestAndRectangularLoop(
         // Recurse into nested loop
         const auto &block{std::get<parser::Block>(loop->t)};
         if (block.empty()) {
-          // Insufficient number of nested loops already reported by
-          // CheckAssocLoopLevel()
           break;
         }
 
         loop = GetDoConstructIf(block.front());
         if (!loop) {
-          // Insufficient number of nested loops already reported by
-          // CheckAssocLoopLevel()
           break;
         }
 
-        auto checkPerfectNest = [&, this]() {
-          if (block.empty())
-            return;
-          auto last = block.end();
-          --last;
-
-          // A trailing CONTINUE is not considered part of the loop body
-          if (parser::Unwrap<parser::ContinueStmt>(*last))
-            --last;
-
-          // In a perfectly nested loop, the nested loop must be the only
-          // statement
-          if (last == block.begin())
-            return;
-
-          // Non-perfectly nested loop
-          // TODO: Point to non-DO statement, directiveSource as a note
-          context_.Say(dirContext.directiveSource,
-              "Canonical loop nest must be perfectly nested."_err_en_US);
-        };
-
-        checkPerfectNest();
-
         ++curLevel;
       }
     }
@@ -2418,36 +2385,6 @@ void OmpAttributeVisitor::PrivatizeAssociatedLoopIndexAndCheckLoopLevel(
           loop = it != block.end() ? GetDoConstructIf(*it) : nullptr;
         }
       }
-      CheckAssocLoopLevel(level, GetAssociatedClause());
-    }
-  }
-}
-
-void OmpAttributeVisitor::CheckAssocLoopLevel(
-    std::int64_t level, const parser::OmpClause *clause) {
-  if (level != 0) {
-    if (clause) {
-      switch (clause->Id()) {
-      case llvm::omp::OMPC_sizes:
-        context_.Say(clause->source,
-            "The SIZES clause has more entries than there are nested canonical loops."_err_en_US);
-        break;
-      case llvm::omp::OMPC_permutation:
-        context_.Say(clause->source,
-            "The PERMUTATION clause has more entries than there are nested canonical loops."_err_en_US);
-        break;
-      default:
-        context_.Say(clause->source,
-            "The value of the parameter in the COLLAPSE or ORDERED clause must"
-            " not be larger than the number of nested loops"
-            " following the construct."_err_en_US);
-        break;
-      }
-    } else if (GetContext().directive ==
-        llvm::omp::Directive::OMPD_interchange) {
-      // OMPD_interchange with no permutation clause needs a level 2 nest
-      context_.Say(GetContext().directiveSource,
-          "The INTERCHANGE construct must be followed by a canonical loop nest of at least 2 levels"_err_en_US);
     }
   }
 }

diff  --git a/flang/test/Semantics/OpenMP/do-collapse.f90 b/flang/test/Semantics/OpenMP/do-collapse.f90
index ec6a3bdad3686..70a84c333236a 100644
--- a/flang/test/Semantics/OpenMP/do-collapse.f90
+++ b/flang/test/Semantics/OpenMP/do-collapse.f90
@@ -3,7 +3,8 @@
 ! 2.7.1 Collapse Clause
 program omp_doCollapse
   integer:: i,j
-  !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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 2
+  !BECAUSE: COLLAPSE clause was specified with argument 3
   !$omp do collapse(3)
   do i = 1,10
     do j = 1, 10
@@ -14,7 +15,8 @@ program omp_doCollapse
 
   do i = 1,10
     do j = 1, 10
-      !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.
+      !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+      !BECAUSE: COLLAPSE clause was specified with argument 2
       !$omp do collapse(2)
       do k = 1, 10
         print *, "hello"
@@ -23,6 +25,8 @@ program omp_doCollapse
     end do
   end do
 
+  !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: COLLAPSE clause was specified with argument 2
   !$omp parallel do collapse(2)
     do i = 1, 3
       !ERROR: Loop control is not present in the DO LOOP
@@ -31,7 +35,8 @@ program omp_doCollapse
       end do
     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.
+  !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: COLLAPSE clause was specified with argument 2
   !ERROR: At most one COLLAPSE clause can appear on the SIMD directive
   !$omp simd collapse(2) collapse(1)
   do i = 1, 4

diff  --git a/flang/test/Semantics/OpenMP/do-concurrent-collapse.f90 b/flang/test/Semantics/OpenMP/do-concurrent-collapse.f90
index 355626f6e73b9..3e382eb3cc4d4 100644
--- a/flang/test/Semantics/OpenMP/do-concurrent-collapse.f90
+++ b/flang/test/Semantics/OpenMP/do-concurrent-collapse.f90
@@ -1,6 +1,8 @@
 !RUN: %python %S/../test_errors.py %s %flang -fopenmp
 
 integer :: i, j
+! ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+! BECAUSE: COLLAPSE clause was specified with argument 2
 ! ERROR: DO CONCURRENT loops cannot be used with the COLLAPSE clause.
 !$omp parallel do collapse(2)
 do i = 1, 1
@@ -30,6 +32,8 @@
   print *, j
 end do
 
+! ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+! BECAUSE: COLLAPSE clause was specified with argument 2
 ! ERROR: DO CONCURRENT loops cannot be used with the COLLAPSE clause.
 !$omp loop collapse(2)
 do i = 1, 1

diff  --git a/flang/test/Semantics/OpenMP/do-ordered.f90 b/flang/test/Semantics/OpenMP/do-ordered.f90
index 79ded3e1b6fe6..00fdd2dc966b5 100644
--- a/flang/test/Semantics/OpenMP/do-ordered.f90
+++ b/flang/test/Semantics/OpenMP/do-ordered.f90
@@ -4,7 +4,8 @@
 
 program omp_doOrdered
   integer:: i,j
-  !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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 2
+  !BECAUSE: ORDERED clause was specified with argument 3
   !$omp do ordered(3)
   do i = 1,10
     do j = 1, 10
@@ -15,7 +16,8 @@ program omp_doOrdered
 
   do i = 1,10
     do j = 1, 10
-      !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.
+      !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+      !BECAUSE: ORDERED clause was specified with argument 2
       !$omp do ordered(2)
       do k = 1, 10
         print *, "hello"
@@ -24,7 +26,8 @@ program omp_doOrdered
     end do
   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.
+  !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: ORDERED clause was specified with argument 2
   !$omp do ordered(2)
   do i = 1,10
     !ERROR: An ORDERED directive without the DEPEND clause must be closely nested in a worksharing-loop (or worksharing-loop SIMD) region with ORDERED clause without the parameter
@@ -36,7 +39,8 @@ program omp_doOrdered
   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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 2
+  !BECAUSE: ORDERED clause was specified with argument 3
   !$omp do collapse(1) ordered(3)
   do i = 1,10
     do j = 1, 10
@@ -46,7 +50,8 @@ program omp_doOrdered
   !$omp end do
 
   !$omp parallel num_threads(4)
-  !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.
+  !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: ORDERED clause was specified with argument 2
   !$omp do ordered(2) collapse(1)
   do i = 1,10
     !ERROR: An ORDERED directive without the DEPEND clause must be closely nested in a worksharing-loop (or worksharing-loop SIMD) region with ORDERED clause without the parameter

diff  --git a/flang/test/Semantics/OpenMP/do08.f90 b/flang/test/Semantics/OpenMP/do08.f90
index 5143dff0dd315..8ab02a0d9acbf 100644
--- a/flang/test/Semantics/OpenMP/do08.f90
+++ b/flang/test/Semantics/OpenMP/do08.f90
@@ -7,7 +7,8 @@ program omp
   logical cond(10,10,10)
   cond = .false.
 
-  !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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: COLLAPSE clause was specified with argument 3
   !$omp do  collapse(3)
   do i = 0, 10
     !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
@@ -20,7 +21,8 @@ program omp
   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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 2
+  !BECAUSE: COLLAPSE clause was specified with argument 3
   !$omp do  collapse(3)
   do i = 0, 10
     do j = 0, 10
@@ -33,7 +35,8 @@ program omp
   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.
+  !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: COLLAPSE clause was specified with argument 2
   !$omp do  collapse(2)
   do i = 0, 10
     !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
@@ -47,7 +50,8 @@ program omp
   !$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.
+  !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: COLLAPSE clause was specified with argument 2
   !$omp do  collapse(2)
   foo: do i = 0, 10
     !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
@@ -61,7 +65,8 @@ program omp
   !$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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 2
+  !BECAUSE: COLLAPSE clause was specified with argument 3
   !$omp do collapse(3)
   do 60 i=2,200,2
     do j=1,10
@@ -124,7 +129,8 @@ program omp
   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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 2
+  !BECAUSE: ORDERED clause was specified with argument 3
   !$omp do  collapse(2) ordered(3)
   foo: do i = 0, 10
     foo1: do j = 0, 10

diff  --git a/flang/test/Semantics/OpenMP/do10.f90 b/flang/test/Semantics/OpenMP/do10.f90
index 936d94d591369..b609567c4d93d 100644
--- a/flang/test/Semantics/OpenMP/do10.f90
+++ b/flang/test/Semantics/OpenMP/do10.f90
@@ -15,7 +15,8 @@ program omp_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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 2
+  !BECAUSE: COLLAPSE clause was specified with argument 3
   !$omp do collapse(3)
   !ERROR: The DO loop iteration variable must be of integer type
   do i = 1, 10

diff  --git a/flang/test/Semantics/OpenMP/do13.f90 b/flang/test/Semantics/OpenMP/do13.f90
index 6e9d1dddade4c..895724e0a10d5 100644
--- a/flang/test/Semantics/OpenMP/do13.f90
+++ b/flang/test/Semantics/OpenMP/do13.f90
@@ -5,7 +5,8 @@
 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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: COLLAPSE clause was specified with argument 3
   !$omp do  collapse(3)
   do i = 0, 10
     !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
@@ -18,7 +19,8 @@ program omp
   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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 2
+  !BECAUSE: COLLAPSE clause was specified with argument 3
   !$omp do  collapse(3)
   do i = 0, 10
     do j = 0, 10
@@ -31,7 +33,8 @@ program omp
   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.
+  !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: COLLAPSE clause was specified with argument 2
   !$omp do  collapse(2)
   do i = 0, 10
     !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
@@ -45,7 +48,8 @@ program omp
   !$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.
+  !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: COLLAPSE clause was specified with argument 2
   !$omp do  collapse(2)
   foo: do i = 0, 10
     !ERROR: CYCLE statement to non-innermost associated loop of an OpenMP DO construct
@@ -59,7 +63,8 @@ program omp
   !$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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 2
+  !BECAUSE: COLLAPSE clause was specified with argument 3
   !$omp do collapse(3)
   do 60 i=1,10
     do j=1,10
@@ -160,7 +165,8 @@ program omp
   !$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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 2
+  !BECAUSE: ORDERED clause was specified with argument 3
   !$omp parallel do ordered(3) collapse(2)
   foo: do i = 0, 10
     foo1: do j = 0, 10

diff  --git a/flang/test/Semantics/OpenMP/do15.f90 b/flang/test/Semantics/OpenMP/do15.f90
index 45c591e66361c..939d7bfde303e 100644
--- a/flang/test/Semantics/OpenMP/do15.f90
+++ b/flang/test/Semantics/OpenMP/do15.f90
@@ -5,7 +5,8 @@
 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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: COLLAPSE clause was specified with argument 3
   !$omp do  collapse(3)
   do i = 0, 10
     if (i .lt. 1) then
@@ -20,7 +21,8 @@ program omp
   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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 2
+  !BECAUSE: COLLAPSE clause was specified with argument 3
   !$omp do  collapse(3)
   do i = 0, 10
     do j = 0, 10
@@ -35,7 +37,6 @@ program omp
   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
@@ -53,7 +54,8 @@ program omp
   !$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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 2
+  !BECAUSE: COLLAPSE clause was specified with argument 3
   !$omp do  collapse(3)
   foo: do i = 0, 10
     foo1: do j = 0, 10
@@ -64,10 +66,10 @@ program omp
         !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
+      foo2: do k  = 0, 10
+        print *, i, j, k
+      end do foo2
+    end do foo1
   end do foo
   !$omp end do
 

diff  --git a/flang/test/Semantics/OpenMP/do16.f90 b/flang/test/Semantics/OpenMP/do16.f90
index 15d13f683cf12..e671c73783e1c 100644
--- a/flang/test/Semantics/OpenMP/do16.f90
+++ b/flang/test/Semantics/OpenMP/do16.f90
@@ -5,7 +5,8 @@
 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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: COLLAPSE clause was specified with argument 3
   !$omp do  collapse(3)
   do i = 0, 10
     select case (i)
@@ -21,7 +22,8 @@ program omp
   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.
+  !ERROR: This construct requires a perfect nest of depth 3, but the associated nest is a perfect nest of depth 2
+  !BECAUSE: COLLAPSE clause was specified with argument 3
   !$omp do  collapse(3)
   do i = 0, 10
     do j = 0, 10

diff  --git a/flang/test/Semantics/OpenMP/do22.f90 b/flang/test/Semantics/OpenMP/do22.f90
index 9d96d3af54e5c..dc38bd5d23253 100644
--- a/flang/test/Semantics/OpenMP/do22.f90
+++ b/flang/test/Semantics/OpenMP/do22.f90
@@ -4,7 +4,8 @@
 subroutine do_imperfectly_nested_before
   integer i, j
 
-  !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.
+  !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: COLLAPSE clause was specified with argument 2
   !$omp do collapse(2)
   do i = 1, 10
     print *, i
@@ -19,7 +20,8 @@ subroutine do_imperfectly_nested_before
 subroutine do_imperfectly_nested_behind
   integer i, j
 
-  !ERROR: Canonical loop nest must be perfectly nested.
+  !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: COLLAPSE clause was specified with argument 2
   !$omp do collapse(2)
   do i = 1, 10
     do j = 1, 10

diff  --git a/flang/test/Semantics/OpenMP/fuse1.f90 b/flang/test/Semantics/OpenMP/fuse1.f90
index 0616a3c52786d..4dab01ca3ec26 100644
--- a/flang/test/Semantics/OpenMP/fuse1.f90
+++ b/flang/test/Semantics/OpenMP/fuse1.f90
@@ -7,7 +7,8 @@ subroutine f
   integer :: i
 
   !$omp do
-  !ERROR: The specified loop range requires 2 loops, but the loop sequence has a length of 1
+  !ERROR: This construct requires a sequence of 2 loops, but the loop sequence has a length of 1
+  !BECAUSE: LOOPRANGE clause was specified with a count of 2 starting at loop 1
   !$omp fuse looprange(1, 2)
   !$omp fuse
   do i = 1, 10

diff  --git a/flang/test/Semantics/OpenMP/interchange-permutation.f90 b/flang/test/Semantics/OpenMP/interchange-permutation.f90
index f0309b159157d..4a187803e37e6 100644
--- a/flang/test/Semantics/OpenMP/interchange-permutation.f90
+++ b/flang/test/Semantics/OpenMP/interchange-permutation.f90
@@ -60,7 +60,8 @@ subroutine insufficient_loops
   implicit none
   integer i
 
-  !ERROR: The PERMUTATION clause has more entries than there are nested canonical loops.
+  !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+  !ERROR: PERMUTATION clause was specified with 2 arguments
   !$omp interchange permutation(2, 1)
   do i = 1, 5
     print *, i

diff  --git a/flang/test/Semantics/OpenMP/interchange01.f90 b/flang/test/Semantics/OpenMP/interchange01.f90
index 1bcdcea17a1da..0bbd5335dca87 100644
--- a/flang/test/Semantics/OpenMP/interchange01.f90
+++ b/flang/test/Semantics/OpenMP/interchange01.f90
@@ -34,7 +34,8 @@ subroutine insufficient_loops
   implicit none
   integer i
 
-  !ERROR: The INTERCHANGE construct must be followed by a canonical loop nest of at least 2 levels
+  !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: PERMUTATION clause was not specified, PERMUTATION(2, 1) was assumed
   !$omp interchange 
   do i = 1, 5
     print *, i

diff  --git a/flang/test/Semantics/OpenMP/loop-transformation-clauses01.f90 b/flang/test/Semantics/OpenMP/loop-transformation-clauses01.f90
index 5e3d32d7c6eff..8e7398fdaaecf 100644
--- a/flang/test/Semantics/OpenMP/loop-transformation-clauses01.f90
+++ b/flang/test/Semantics/OpenMP/loop-transformation-clauses01.f90
@@ -20,7 +20,8 @@ subroutine loop_transformation_construct1
   end do
   !$omp end fuse
 
-  !ERROR: The specified loop range requires 6 loops, but the loop sequence has a length of 2
+  !ERROR: This construct requires a sequence of 6 loops, but the loop sequence has a length of 2
+  !BECAUSE: LOOPRANGE clause was specified with a count of 2 starting at loop 5
   !$omp fuse looprange(5,2)
   do x = 1, i
     v(x) = x * 2

diff  --git a/flang/test/Semantics/OpenMP/tile05.f90 b/flang/test/Semantics/OpenMP/tile05.f90
index 70c43811a5832..36c4b299a7c54 100644
--- a/flang/test/Semantics/OpenMP/tile05.f90
+++ b/flang/test/Semantics/OpenMP/tile05.f90
@@ -6,7 +6,8 @@ subroutine insufficient_loops
   implicit none
   integer i
 
-  !ERROR: The SIZES clause has more entries than there are nested canonical loops.
+  !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: SIZES clause was specified with 2 arguments
   !$omp tile sizes(2, 2)
   do i = 1, 5
     print *, i

diff  --git a/flang/test/Semantics/OpenMP/tile07.f90 b/flang/test/Semantics/OpenMP/tile07.f90
index 70a6f5fc529a4..9642fe10013fd 100644
--- a/flang/test/Semantics/OpenMP/tile07.f90
+++ b/flang/test/Semantics/OpenMP/tile07.f90
@@ -6,7 +6,8 @@ subroutine non_perfectly_nested_loop_behind
   implicit none
   integer i, j
 
-  !ERROR: Canonical loop nest must be perfectly nested.
+  !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: SIZES clause was specified with 2 arguments
   !$omp tile sizes(2,2)
   do i = 1, 5
     do j = 1, 42
@@ -21,7 +22,8 @@ subroutine non_perfectly_nested_loop_before
   implicit none
   integer i, j
 
-  !ERROR: The SIZES clause has more entries than there are nested canonical loops.
+  !ERROR: This construct requires a perfect nest of depth 2, but the associated nest is a perfect nest of depth 1
+  !BECAUSE: SIZES clause was specified with 2 arguments
   !$omp tile sizes(2,2)
   do i = 1, 5
     print *, i


        


More information about the flang-commits mailing list