[flang-commits] [flang] a97afde - [flang][OpenMP] Switch SOURCE/SINK to use modifier infrastructure (#217644)

via flang-commits flang-commits at lists.llvm.org
Thu Aug 20 11:55:56 PDT 2026


Author: Krzysztof Parzyszek
Date: 2026-08-20T13:55:51-05:00
New Revision: a97afdec500cdaed1adaf6adc1ac1eba71570e83

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

LOG: [flang][OpenMP] Switch SOURCE/SINK to use modifier infrastructure (#217644)

They are instances of the dependence-type modifier in the spec. Putting
them into the modifier infrastructure in the compiler will remove the
need for them to be validated by hand in the future.

Added: 
    

Modified: 
    flang/examples/FeatureList/FeatureList.cpp
    flang/include/flang/Parser/dump-parse-tree.h
    flang/include/flang/Parser/parse-tree.h
    flang/lib/Lower/OpenMP/Clauses.cpp
    flang/lib/Parser/openmp-parsers.cpp
    flang/lib/Parser/parse-tree.cpp
    flang/lib/Parser/unparse.cpp
    flang/lib/Semantics/check-omp-structure.cpp
    flang/lib/Semantics/check-omp-structure.h
    flang/test/Parser/OpenMP/doacross-clause.f90
    flang/test/Parser/OpenMP/ordered-block-vs-standalone.f90
    flang/test/Parser/OpenMP/ordered-depend.f90
    flang/test/Semantics/OpenMP/doacross.f90
    flang/test/Semantics/OpenMP/ordered01.f90

Removed: 
    


################################################################################
diff  --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp
index cc8d6934c78d0..c5bcff5ac6088 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -465,8 +465,7 @@ struct NodeVisitor {
   READ_FEATURE(OmpVariableCategory::Value)
   READ_FEATURE(OmpDependClause)
   READ_FEATURE(OmpDependClause::TaskDep)
-  READ_FEATURE(OmpDoacross::Sink)
-  READ_FEATURE(OmpDoacross::Source)
+  READ_FEATURE(OmpDoacross::Modifier)
   READ_FEATURE(OmpDoacrossClause)
   READ_FEATURE(OmpDependenceType)
   READ_FEATURE(OmpDependenceType::Value)

diff  --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 9e3ed0ddc4396..5b6bb820a3394 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -628,8 +628,7 @@ class ParseTreeDumper {
   NODE_ENUM(OmpDirectiveSpecification, Flag)
   NODE_ENUMSET(OmpDirectiveSpecification, Flags)
   NODE(parser, OmpDoacross)
-  NODE(OmpDoacross, Sink)
-  NODE(OmpDoacross, Source)
+  NODE(OmpDoacross, Modifier)
   NODE(parser, OmpDoacrossClause)
   NODE(parser, OmpDynamicAllocatorsClause)
   NODE(parser, OmpDynGroupprivateClause)

diff  --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index e50c1438a1407..1c817805e1dba 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4614,11 +4614,9 @@ struct OmpIterationVector {
 // See: depend-clause, doacross-clause
 struct OmpDoacross {
   OmpDependenceType::Value GetDepType() const;
-
-  WRAPPER_CLASS(Sink, OmpIterationVector);
-  EMPTY_CLASS(Source);
-  UNION_CLASS_BOILERPLATE(OmpDoacross);
-  std::variant<Sink, Source> u;
+  MODIFIER_BOILERPLATE(OmpDependenceType);
+  TUPLE_CLASS_BOILERPLATE(OmpDoacross);
+  std::tuple<MODIFIERS(), std::optional<OmpIterationVector>> t;
 };
 
 // Ref: [4.5:169-172], [5.0:255-259], [5.1:288-292], [5.2:323-326]

diff  --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 3a77371c99276..7f154b2279c79 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -723,30 +723,32 @@ Doacross makeDoacross(const parser::OmpDoacross &doa,
   // Iteration is the equivalent of parser::OmpIteration
   using Iteration = Doacross::Vector::value_type; // LoopIterationT
 
-  auto visitSource = [&](const parser::OmpDoacross::Source &) {
+  auto &mods = semantics::OmpGetModifiers(doa);
+  auto *m0 = semantics::OmpGetUniqueModifier<parser::OmpDependenceType>(mods);
+  assert(m0 && "Expecting dependence-type");
+  if (m0->v == parser::OmpDependenceType::Value::Source) {
     return Doacross{{/*DependenceType=*/Doacross::DependenceType::Source,
                      /*Vector=*/{}}};
-  };
+  }
+
+  using IterOffset = parser::OmpIterationOffset;
+  auto convert2 = [&](const parser::OmpIteration &v) {
+    auto &t0 = std::get<parser::Name>(v.t);
+    auto &t1 = std::get<std::optional<IterOffset>>(v.t);
 
-  auto visitSink = [&](const parser::OmpDoacross::Sink &s) {
-    using IterOffset = parser::OmpIterationOffset;
-    auto convert2 = [&](const parser::OmpIteration &v) {
-      auto &t0 = std::get<parser::Name>(v.t);
-      auto &t1 = std::get<std::optional<IterOffset>>(v.t);
-
-      auto convert3 = [&](const IterOffset &u) {
-        auto &s0 = std::get<parser::DefinedOperator>(u.t);
-        auto &s1 = std::get<parser::ScalarIntConstantExpr>(u.t);
-        return Iteration::Distance{
-            {makeDefinedOperator(s0, semaCtx), makeExpr(s1, semaCtx)}};
-      };
-      return Iteration{{makeObject(t0, semaCtx), maybeApply(convert3, t1)}};
+    auto convert3 = [&](const IterOffset &u) {
+      auto &s0 = std::get<parser::DefinedOperator>(u.t);
+      auto &s1 = std::get<parser::ScalarIntConstantExpr>(u.t);
+      return Iteration::Distance{
+          {makeDefinedOperator(s0, semaCtx), makeExpr(s1, semaCtx)}};
     };
-    return Doacross{{/*DependenceType=*/Doacross::DependenceType::Sink,
-                     /*Vector=*/makeList(s.v.v, convert2)}};
+    return Iteration{{makeObject(t0, semaCtx), maybeApply(convert3, t1)}};
   };
 
-  return common::visit(common::visitors{visitSink, visitSource}, doa.u);
+  auto &vec = std::get<std::optional<parser::OmpIterationVector>>(doa.t);
+  assert(vec && "Expecting iteration vector");
+  return Doacross{{/*DependenceType=*/Doacross::DependenceType::Sink,
+                   /*Vector=*/makeList(vec->v, convert2)}};
 }
 
 Depend makeDepend(const parser::OmpDependClause::TaskDep &inp,

diff  --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index b84abb2d4b586..33c85bb945fdc 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1083,10 +1083,13 @@ TYPE_PARSER(sourced(construct<OmpAllocateClause::Modifier>(sourced(
 TYPE_PARSER(sourced(
     construct<OmpDefaultmapClause::Modifier>(Parser<OmpVariableCategory>{})))
 
-TYPE_PARSER(sourced(construct<OmpDependClause::TaskDep::Modifier>(sourced(
+TYPE_PARSER(
+    sourced(construct<OmpDoacross::Modifier>(Parser<OmpDependenceType>{})))
+
+TYPE_PARSER(sourced( //
     construct<OmpDependClause::TaskDep::Modifier>(Parser<OmpIterator>{}) ||
     construct<OmpDependClause::TaskDep::Modifier>(
-        Parser<OmpTaskDependenceType>{})))))
+        Parser<OmpTaskDependenceType>{})))
 
 TYPE_PARSER( //
     sourced(construct<OmpDynGroupprivateClause::Modifier>(
@@ -1428,9 +1431,10 @@ TYPE_PARSER(construct<OmpIteration>(name, maybe(Parser<OmpIterationOffset>{})))
 TYPE_PARSER(construct<OmpIterationVector>(nonemptyList(Parser<OmpIteration>{})))
 
 TYPE_PARSER(construct<OmpDoacross>(
-    construct<OmpDoacross>(construct<OmpDoacross::Sink>(
-        "SINK"_tok >> ":"_tok >> Parser<OmpIterationVector>{})) ||
-    construct<OmpDoacross>(construct<OmpDoacross::Source>("SOURCE"_tok))))
+    // Don't parse the modifier list as "maybe", or otherwise the parser will
+    // always succeed (never allowing TaskDep in OmpDependClause).
+    nonemptyList(Parser<OmpDoacross::Modifier>{}),
+    maybe(":"_tok >> Parser<OmpIterationVector>{})))
 
 TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US,
     construct<OmpDependClause>(

diff  --git a/flang/lib/Parser/parse-tree.cpp b/flang/lib/Parser/parse-tree.cpp
index 07f04c6e35920..8d5682a4fc430 100644
--- a/flang/lib/Parser/parse-tree.cpp
+++ b/flang/lib/Parser/parse-tree.cpp
@@ -279,16 +279,12 @@ OmpDirectiveName::OmpDirectiveName(const Verbatim &name) {
 }
 
 OmpDependenceType::Value OmpDoacross::GetDepType() const {
-  return common::visit( //
-      common::visitors{
-          [](const OmpDoacross::Sink &) {
-            return OmpDependenceType::Value::Sink;
-          },
-          [](const OmpDoacross::Source &) {
-            return OmpDependenceType::Value::Source;
-          },
-      },
-      u);
+  auto &modifiers{std::get<std::optional<std::list<Modifier>>>(t)};
+  if (modifiers && !modifiers->empty()) {
+    return common::visit([](auto &&s) { return s.v; }, modifiers->front().u);
+  } else {
+    llvm_unreachable("expecting modifiers on OmpDoacross");
+  }
 }
 
 OmpTaskDependenceType::Value OmpDependClause::TaskDep::GetTaskDepType() const {

diff  --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index accb80ddbe8f2..d46c65ae72329 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2285,6 +2285,14 @@ class UnparseVisitor {
     Walk(std::get<OmpDefaultmapClause::ImplicitBehavior>(x.t));
     Walk(":", std::get<std::optional<std::list<Modifier>>>(x.t));
   }
+  void Unparse(const OmpDoacross &x) {
+    using Modifier = OmpDoacross::Modifier;
+    Walk(std::get<std::optional<std::list<Modifier>>>(x.t));
+    if (auto &&vector{std::get<std::optional<OmpIterationVector>>(x.t)}) {
+      Put(": ");
+      Walk(vector->v, ", ");
+    }
+  }
   void Unparse(const OmpDependClause::TaskDep &x) {
     using Modifier = OmpDependClause::TaskDep::Modifier;
     Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
@@ -2337,11 +2345,6 @@ class UnparseVisitor {
       unparseClauses();
     }
   }
-  void Unparse(const OmpDoacross::Sink &x) {
-    Word("SINK: ");
-    Walk(x.v.v);
-  }
-  void Unparse(const OmpDoacross::Source &) { Word("SOURCE"); }
   void Unparse(const OmpDynGroupprivateClause &x) {
     using Modifier = OmpDynGroupprivateClause::Modifier;
     Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
@@ -2928,6 +2931,7 @@ class UnparseVisitor {
   WALK_NESTED_ENUM(OmpProcBindClause, AffinityPolicy) // OMP proc_bind
   WALK_NESTED_ENUM(OmpDefaultClause, DataSharingAttribute) // OMP default
   WALK_NESTED_ENUM(OmpDefaultmapClause, ImplicitBehavior) // OMP defaultmap
+  WALK_NESTED_ENUM(OmpDependenceType, Value)
   WALK_NESTED_ENUM(OmpVariableCategory, Value) // OMP variable-category
   WALK_NESTED_ENUM(OmpLastprivateModifier, Value) // OMP lastprivate-modifier
   WALK_NESTED_ENUM(OmpChunkModifier, Value) // OMP chunk-modifier

diff  --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 274efa64d03d0..332624dac50e1 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -2950,11 +2950,16 @@ void OmpStructureChecker::ChecksOnOrderedAsStandalone() {
 
   auto visitDoacross{[&](const parser::OmpDoacross &doa,
                          const parser::CharBlock &src) {
-    common::visit(
-        common::visitors{
-            [&](const parser::OmpDoacross::Source &) { dependSourceCount++; },
-            [&](const parser::OmpDoacross::Sink &) { dependSinkCount++; }},
-        doa.u);
+    // Modifiers should have been verified by now.
+    auto &modifiers{OmpGetModifiers(doa)};
+    if (auto *source{
+            OmpGetUniqueModifier<parser::OmpDependenceType>(modifiers)}) {
+      if (source->v == parser::OmpDependenceType::Value::Source) {
+        ++dependSourceCount;
+      } else {
+        ++dependSinkCount;
+      }
+    }
     if (!exclusiveShown && dependSinkCount > 0 && dependSourceCount > 0) {
       exclusiveShown = true;
       context_.Say(src,
@@ -3010,11 +3015,17 @@ void OmpStructureChecker::CheckOrderedDependClause(
     std::optional<int64_t> orderedValue) {
   auto visitDoacross{[&](const parser::OmpDoacross &doa,
                          const parser::CharBlock &src) {
-    if (auto *sinkVector{std::get_if<parser::OmpDoacross::Sink>(&doa.u)}) {
-      int64_t numVar = sinkVector->v.v.size();
-      if (orderedValue != numVar) {
-        context_.Say(src,
-            "The number of variables in the SINK iteration vector does not match the parameter specified in ORDERED clause"_err_en_US);
+    auto &modifiers{OmpGetModifiers(doa)};
+    auto *depType{OmpGetUniqueModifier<parser::OmpDependenceType>(modifiers)};
+    assert(depType && "Expecting dependence-type");
+    if (depType->v == parser::OmpDependenceType::Value::Sink) {
+      auto &iterVec{std::get<std::optional<parser::OmpIterationVector>>(doa.t)};
+      if (iterVec) {
+        int64_t numVar = iterVec->v.size();
+        if (orderedValue != numVar) {
+          context_.Say(src,
+              "The number of variables in the SINK iteration vector does not match the parameter specified in ORDERED clause"_err_en_US);
+        }
       }
     }
   }};
@@ -5078,7 +5089,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
       "Unexpected alternative in update clause");
 
   if (doaDep) {
-    CheckDoacross(*doaDep);
+    CheckDoacross(*doaDep, llvm::omp::Clause::OMPC_depend);
     CheckDependenceType(doaDep->GetDepType());
   } else {
     using Modifier = parser::OmpDependClause::TaskDep::Modifier;
@@ -5157,12 +5168,33 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
 }
 
 void OmpStructureChecker::Enter(const parser::OmpClause::Doacross &x) {
-  CheckDoacross(x.v.v);
+  CheckDoacross(x.v.v, llvm::omp::Clause::OMPC_doacross);
 }
 
-void OmpStructureChecker::CheckDoacross(const parser::OmpDoacross &doa) {
-  if (std::holds_alternative<parser::OmpDoacross::Source>(doa.u)) {
-    // Nothing to check here.
+void OmpStructureChecker::CheckDoacross(
+    const parser::OmpDoacross &doa, llvm::omp::Clause clauseId) {
+  parser::CharBlock clauseSource{GetContext().clauseSource};
+
+  if (!OmpVerifyModifiers(doa, clauseId, clauseSource, context_)) {
+    return;
+  }
+
+  auto &iterVec{std::get<std::optional<parser::OmpIterationVector>>(doa.t)};
+
+  auto &modifiers{OmpGetModifiers(doa)};
+  auto &depType{*OmpGetUniqueModifier<parser::OmpDependenceType>(modifiers)};
+  if (depType.v == parser::OmpDependenceType::Value::Source) {
+    if (iterVec) {
+      context_.Say(OmpGetModifierSource(modifiers, &depType),
+          "Iteration vector may not be specified with SOURCE dependence type"_err_en_US);
+    }
+    return;
+  }
+  assert(depType.v == parser::OmpDependenceType::Value::Sink &&
+      "Unexpected dependence-type");
+  if (!iterVec) {
+    context_.Say(OmpGetModifierSource(modifiers, &depType),
+        "Iteration vector must be specified with SINK dependence type"_err_en_US);
     return;
   }
 
@@ -5170,8 +5202,7 @@ void OmpStructureChecker::CheckDoacross(const parser::OmpDoacross &doa) {
   // which references a prior ORDERED(n) clause on a DO or SIMD construct
   // that marks the top of the loop nest.
 
-  auto &sink{std::get<parser::OmpDoacross::Sink>(doa.u)};
-  const std::list<parser::OmpIteration> &vec{sink.v.v};
+  const std::list<parser::OmpIteration> &vec{iterVec->v};
 
   // Check if the variables in the iteration vector are unique.
   struct Less {

diff  --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 5eb33133e1efd..98b6c8e452dfa 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -393,7 +393,8 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
   std::optional<IterTy> FindDuplicate(RangeTy &&);
 
   void CheckDependList(const parser::DataRef &);
-  void CheckDoacross(const parser::OmpDoacross &doa);
+  void CheckDoacross(
+      const parser::OmpDoacross &doa, llvm::omp::Clause clauseId);
   void CheckDimsModifier(parser::CharBlock source, size_t numValues,
       const parser::OmpDimsModifier &x);
   void CheckTypeParamInquiry(const parser::CharBlock &source,

diff  --git a/flang/test/Parser/OpenMP/doacross-clause.f90 b/flang/test/Parser/OpenMP/doacross-clause.f90
index 80a97db248cb1..0b65605f3b6cb 100644
--- a/flang/test/Parser/OpenMP/doacross-clause.f90
+++ b/flang/test/Parser/OpenMP/doacross-clause.f90
@@ -33,7 +33,8 @@ subroutine f00(x)
 ![...]
 !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct -> OmpDirectiveSpecification
 !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = ordered
-!PARSE-TREE: | OmpClauseList -> OmpClause -> Doacross -> OmpDoacrossClause -> OmpDoacross -> Source
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Doacross -> OmpDoacrossClause -> OmpDoacross
+!PARSE-TREE: | | Modifier -> OmpDependenceType -> Value = Source
 
 subroutine f01(x)
   integer :: x(10, 10)
@@ -67,24 +68,28 @@ subroutine f01(x)
 ![...]
 !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct -> OmpDirectiveSpecification
 !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = ordered
-!PARSE-TREE: | OmpClauseList -> OmpClause -> Doacross -> OmpDoacrossClause -> OmpDoacross -> Sink -> OmpIterationVector -> OmpIteration
-!PARSE-TREE: | | Name = 'i'
-!PARSE-TREE: | | OmpIterationOffset
-!PARSE-TREE: | | | DefinedOperator -> IntrinsicOperator = Add
-!PARSE-TREE: | | | Scalar -> Integer -> Constant -> Expr = '1_4'
-!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '1'
-!PARSE-TREE: | OmpIteration
-!PARSE-TREE: | | Name = 'j'
-!PARSE-TREE: | | OmpIterationOffset
-!PARSE-TREE: | | | DefinedOperator -> IntrinsicOperator = Subtract
-!PARSE-TREE: | | | Scalar -> Integer -> Constant -> Expr = '2_4'
-!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '2'
-!PARSE-TREE: | OmpClause -> Doacross -> OmpDoacrossClause -> OmpDoacross -> Sink -> OmpIterationVector -> OmpIteration
-!PARSE-TREE: | | Name = 'i'
-!PARSE-TREE: | OmpIteration
-!PARSE-TREE: | | Name = 'j'
-!PARSE-TREE: | | OmpIterationOffset
-!PARSE-TREE: | | | DefinedOperator -> IntrinsicOperator = Add
-!PARSE-TREE: | | | Scalar -> Integer -> Constant -> Expr = '3_4'
-!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '3'
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Doacross -> OmpDoacrossClause -> OmpDoacross
+!PARSE-TREE: | | Modifier -> OmpDependenceType -> Value = Sink
+!PARSE-TREE: | | OmpIterationVector -> OmpIteration
+!PARSE-TREE: | | | Name = 'i'
+!PARSE-TREE: | | | OmpIterationOffset
+!PARSE-TREE: | | | | DefinedOperator -> IntrinsicOperator = Add
+!PARSE-TREE: | | | | Scalar -> Integer -> Constant -> Expr = '1_4'
+!PARSE-TREE: | | | | | LiteralConstant -> IntLiteralConstant = '1'
+!PARSE-TREE: | | OmpIteration
+!PARSE-TREE: | | | Name = 'j'
+!PARSE-TREE: | | | OmpIterationOffset
+!PARSE-TREE: | | | | DefinedOperator -> IntrinsicOperator = Subtract
+!PARSE-TREE: | | | | Scalar -> Integer -> Constant -> Expr = '2_4'
+!PARSE-TREE: | | | | | LiteralConstant -> IntLiteralConstant = '2'
+!PARSE-TREE: | OmpClause -> Doacross -> OmpDoacrossClause -> OmpDoacross
+!PARSE-TREE: | | Modifier -> OmpDependenceType -> Value = Sink
+!PARSE-TREE: | | OmpIterationVector -> OmpIteration
+!PARSE-TREE: | | | Name = 'i'
+!PARSE-TREE: | | OmpIteration
+!PARSE-TREE: | | | Name = 'j'
+!PARSE-TREE: | | | OmpIterationOffset
+!PARSE-TREE: | | | | DefinedOperator -> IntrinsicOperator = Add
+!PARSE-TREE: | | | | Scalar -> Integer -> Constant -> Expr = '3_4'
+!PARSE-TREE: | | | | | LiteralConstant -> IntLiteralConstant = '3'
 

diff  --git a/flang/test/Parser/OpenMP/ordered-block-vs-standalone.f90 b/flang/test/Parser/OpenMP/ordered-block-vs-standalone.f90
index abc4258472646..78be8540c5060 100644
--- a/flang/test/Parser/OpenMP/ordered-block-vs-standalone.f90
+++ b/flang/test/Parser/OpenMP/ordered-block-vs-standalone.f90
@@ -11,6 +11,7 @@ subroutine standalone
       ! CHECK:      OpenMPConstruct -> OpenMPStandaloneConstruct
       ! CHECK-NEXT: | OmpDirectiveName -> llvm::omp::Directive = ordered
       ! CHECK-NEXT: | OmpClauseList ->
+      ! CHECK-NEXT: | | Modifier -> OmpDependenceType -> Value = Source
       ! CHECK-NEXT: | Flags = {}
       !$omp ordered depend(source)
       x(i, j) = i + j

diff  --git a/flang/test/Parser/OpenMP/ordered-depend.f90 b/flang/test/Parser/OpenMP/ordered-depend.f90
index d937273ae8e1b..8f92b26669fb3 100644
--- a/flang/test/Parser/OpenMP/ordered-depend.f90
+++ b/flang/test/Parser/OpenMP/ordered-depend.f90
@@ -33,8 +33,8 @@ subroutine f00(x)
 ![...]
 !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct -> OmpDirectiveSpecification
 !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = ordered
-!PARSE-TREE: | OmpClauseList -> OmpClause -> Depend -> OmpDependClause -> OmpDoacross -> Source
-
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Depend -> OmpDependClause -> OmpDoacross
+!PARSE-TREE: | | Modifier -> OmpDependenceType -> Value = Source
 subroutine f01(x)
   integer :: x(10, 10)
   !$omp do ordered(2)
@@ -67,24 +67,28 @@ subroutine f01(x)
 ![...]
 !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct -> OmpDirectiveSpecification
 !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = ordered
-!PARSE-TREE: | OmpClauseList -> OmpClause -> Depend -> OmpDependClause -> OmpDoacross -> Sink -> OmpIterationVector -> OmpIteration
-!PARSE-TREE: | | Name = 'i'
-!PARSE-TREE: | | OmpIterationOffset
-!PARSE-TREE: | | | DefinedOperator -> IntrinsicOperator = Add
-!PARSE-TREE: | | | Scalar -> Integer -> Constant -> Expr = '1_4'
-!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '1'
-!PARSE-TREE: | OmpIteration
-!PARSE-TREE: | | Name = 'j'
-!PARSE-TREE: | | OmpIterationOffset
-!PARSE-TREE: | | | DefinedOperator -> IntrinsicOperator = Subtract
-!PARSE-TREE: | | | Scalar -> Integer -> Constant -> Expr = '2_4'
-!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '2'
-!PARSE-TREE: | OmpClause -> Depend -> OmpDependClause -> OmpDoacross -> Sink -> OmpIterationVector -> OmpIteration
-!PARSE-TREE: | | Name = 'i'
-!PARSE-TREE: | OmpIteration
-!PARSE-TREE: | | Name = 'j'
-!PARSE-TREE: | | OmpIterationOffset
-!PARSE-TREE: | | | DefinedOperator -> IntrinsicOperator = Add
-!PARSE-TREE: | | | Scalar -> Integer -> Constant -> Expr = '3_4'
-!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '3'
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Depend -> OmpDependClause -> OmpDoacross
+!PARSE-TREE: | | Modifier -> OmpDependenceType -> Value = Sink
+!PARSE-TREE: | | OmpIterationVector -> OmpIteration
+!PARSE-TREE: | | | Name = 'i'
+!PARSE-TREE: | | | OmpIterationOffset
+!PARSE-TREE: | | | | DefinedOperator -> IntrinsicOperator = Add
+!PARSE-TREE: | | | | Scalar -> Integer -> Constant -> Expr = '1_4'
+!PARSE-TREE: | | | | | LiteralConstant -> IntLiteralConstant = '1'
+!PARSE-TREE: | | OmpIteration
+!PARSE-TREE: | | | Name = 'j'
+!PARSE-TREE: | | | OmpIterationOffset
+!PARSE-TREE: | | | | DefinedOperator -> IntrinsicOperator = Subtract
+!PARSE-TREE: | | | | Scalar -> Integer -> Constant -> Expr = '2_4'
+!PARSE-TREE: | | | | | LiteralConstant -> IntLiteralConstant = '2'
+!PARSE-TREE: | OmpClause -> Depend -> OmpDependClause -> OmpDoacross
+!PARSE-TREE: | | Modifier -> OmpDependenceType -> Value = Sink
+!PARSE-TREE: | | OmpIterationVector -> OmpIteration
+!PARSE-TREE: | | | Name = 'i'
+!PARSE-TREE: | | OmpIteration
+!PARSE-TREE: | | | Name = 'j'
+!PARSE-TREE: | | | OmpIterationOffset
+!PARSE-TREE: | | | | DefinedOperator -> IntrinsicOperator = Add
+!PARSE-TREE: | | | | Scalar -> Integer -> Constant -> Expr = '3_4'
+!PARSE-TREE: | | | | | LiteralConstant -> IntLiteralConstant = '3'
 

diff  --git a/flang/test/Semantics/OpenMP/doacross.f90 b/flang/test/Semantics/OpenMP/doacross.f90
index 381a4118ce7bf..3a01d732428e7 100644
--- a/flang/test/Semantics/OpenMP/doacross.f90
+++ b/flang/test/Semantics/OpenMP/doacross.f90
@@ -7,6 +7,14 @@ subroutine f00(x)
     do j = 1, 10
 !ERROR: Duplicate variable 'i' in the iteration vector
       !$omp ordered doacross(sink: i+1, i-2)
+!ERROR: Iteration vector must be specified with SINK dependence type
+      !$omp ordered doacross(sink)
+!ERROR: Iteration vector may not be specified with SOURCE dependence type
+      !$omp ordered doacross(source: i)
+!ERROR: The number of variables in the SINK iteration vector does not match the parameter specified in ORDERED clause
+!ERROR: 'dependence-type' should be the last modifier
+!ERROR: 'dependence-type' modifier cannot occur multiple times
+      !$omp ordered doacross(sink, sink: i)
       x(i, j) = 0
     enddo
   enddo

diff  --git a/flang/test/Semantics/OpenMP/ordered01.f90 b/flang/test/Semantics/OpenMP/ordered01.f90
index f386feddce01f..b445b0448ba18 100644
--- a/flang/test/Semantics/OpenMP/ordered01.f90
+++ b/flang/test/Semantics/OpenMP/ordered01.f90
@@ -49,6 +49,10 @@ program main
     !ERROR: Only SINK or SOURCE dependence types are allowed when ORDERED construct is a standalone construct with no ORDERED region
     !$omp ordered depend(out: arrayC) depend(in: arrayB)
     arrayC(i) = baz(arrayB(i-1))
+    !ERROR: Iteration vector must be specified with SINK dependence type
+    !$omp ordered depend(sink)
+    !ERROR: Iteration vector may not be specified with SOURCE dependence type
+    !$omp ordered depend(source: i - 2)
   end do
   !$omp end do
 


        


More information about the flang-commits mailing list