[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