diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -456,6 +456,9 @@ NODE(parser, OmpDefaultmapClause) NODE_ENUM(OmpDefaultmapClause, ImplicitBehavior) NODE_ENUM(OmpDefaultmapClause, VariableCategory) + NODE(parser, OmpIteratorSpecifier) + NODE(parser, OmpIteratorSpecifierList) + NODE(parser, OmpIterator) NODE(parser, OmpDependClause) NODE(OmpDependClause, InOut) NODE(OmpDependClause, Sink) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3276,7 +3276,28 @@ WRAPPER_CLASS(PauseStmt, std::optional); -// Parse tree nodes for OpenMP 4.5 directives and clauses +// Parse tree nodes for OpenMP 4.5/5.0 directives and clauses + +// 2.1.6 Iterators [OpenMP 5.0] +// iterators-specifier -> [ iterator-type ] identifier = range-specification +// iterator-type -> integer type +// range-specification -> begin:end[:step] +struct OmpIteratorSpecifier { + TUPLE_CLASS_BOILERPLATE(OmpIteratorSpecifier); + CharBlock source; + using Bounds = LoopBounds; + std::tuple, Bounds> t; +}; + +WRAPPER_CLASS(OmpIteratorSpecifierList, std::list); + +// 2.1.6 iterators -> iterator(iterators-definition) +// iterators-definition -> iterator-specifier [, iterators-definition ] +struct OmpIterator { + TUPLE_CLASS_BOILERPLATE(OmpIterator); + CharBlock source; + std::tuple t; +}; // 2.5 proc-bind-clause -> PROC_BIND (MASTER | CLOSE | SPREAD) struct OmpProcBindClause { @@ -3404,34 +3425,42 @@ std::tuple> t; }; -// 2.13.9 depend-vec-length -> +/- non-negative-constant +// 2.17.11 Depend Clause [OpenMP 5.0] +// 2.17.11 depend-vec-length -> +/- non-negative-constant struct OmpDependSinkVecLength { TUPLE_CLASS_BOILERPLATE(OmpDependSinkVecLength); std::tuple t; }; -// 2.13.9 depend-vec -> iterator [+/- depend-vec-length],...,iterator[...] +// 2.17.11 depend-vec -> iterator [+/- depend-vec-length],...,iterator[...] struct OmpDependSinkVec { TUPLE_CLASS_BOILERPLATE(OmpDependSinkVec); std::tuple> t; }; -// 2.13.9 depend-type -> IN | OUT | INOUT | SOURCE | SINK +// 2.17.11 dependence-type -> IN | OUT | INOUT | MUTEXINOUTSET | DEPOBJ struct OmpDependenceType { - ENUM_CLASS(Type, In, Out, Inout, Source, Sink) + ENUM_CLASS(Type, In, Out, Inout, Mutexinoutset, Depobj) WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Type); }; -// 2.13.9 depend-clause -> DEPEND (((IN | OUT | INOUT) : variable-name-list) | -// SOURCE | SINK : depend-vec) +// 2.17.11 depend-clause -> DEPEND (([ITERATOR(iterators-definition),] +// (IN | OUT | INOUT | +// MUTEXINOUTSET | DEPOBJ) : +// variable-name-list) | +// SOURCE | +// SINK : depend-vec) struct OmpDependClause { UNION_CLASS_BOILERPLATE(OmpDependClause); EMPTY_CLASS(Source); WRAPPER_CLASS(Sink, std::list); struct InOut { TUPLE_CLASS_BOILERPLATE(InOut); - std::tuple> t; + std::tuple, OmpDependenceType, + std::list> + t; }; + CharBlock source; std::variant u; }; diff --git a/flang/include/flang/Semantics/scope.h b/flang/include/flang/Semantics/scope.h --- a/flang/include/flang/Semantics/scope.h +++ b/flang/include/flang/Semantics/scope.h @@ -56,7 +56,7 @@ public: ENUM_CLASS(Kind, Global, Module, MainProgram, Subprogram, BlockData, - DerivedType, Block, Forall, ImpliedDos) + DerivedType, Block, Forall, ImpliedDos, OmpIterators) using ImportKind = common::ImportKind; // Create the Global scope -- the root of the scope tree diff --git a/flang/lib/Parser/expr-parsers.h b/flang/lib/Parser/expr-parsers.h --- a/flang/lib/Parser/expr-parsers.h +++ b/flang/lib/Parser/expr-parsers.h @@ -101,5 +101,9 @@ return construct>( doVariable / "=", p / ",", p, maybe("," >> p)); } +template inline constexpr auto ompLoopBounds(const PA &p) { + return construct>( + doVariable / "=", p / ":", p, maybe(":" >> p)); +} } // namespace Fortran::parser #endif diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -27,6 +27,19 @@ return sourced(construct(x)); } +// 2.1.6 ITERATOR(iterators-definition) +// iterators-definition -> iterator-specifier [, iterators-definition ] +// iterator-specifier -> [ iterator-type ] identifier = +// range-specification +TYPE_PARSER(sourced(construct( + maybe(integerTypeSpec / "::"), ompLoopBounds(scalarIntExpr)))) + +TYPE_PARSER(construct( + many(maybe(","_tok) >> Parser{}))) + +TYPE_PARSER(sourced(construct(verbatim("ITERATOR"_tok), + parenthesized(Parser{})))) + // OpenMP Clauses // 2.15.3.1 DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE) TYPE_PARSER(construct( @@ -108,7 +121,12 @@ TYPE_PARSER(construct( Parser{} / ":", nonemptyList(designator))) -// 2.13.9 DEPEND (SOURCE | SINK : vec | (IN | OUT | INOUT) : list +// 2.17.11 DEPEND (source-dependence | sink-dependence | other-dependence) +// source-dependence -> SOURCE +// sink-dependence -> SINK : vec +// other-dependence -> dependence-modifier dependence-type : list +// dependence-modifier -> [ITERATOR(iterators-definition), ] +// dependence-type -> IN | OUT | INOUT | MUTEXINOUTSET | DEPOBJ TYPE_PARSER(construct( Parser{}, scalarIntConstantExpr)) @@ -117,16 +135,20 @@ TYPE_PARSER( construct("IN"_id >> pure(OmpDependenceType::Type::In) || + "OUT" >> pure(OmpDependenceType::Type::Out) || "INOUT" >> pure(OmpDependenceType::Type::Inout) || - "OUT" >> pure(OmpDependenceType::Type::Out))) + "MUTEXINOUTSET" >> pure(OmpDependenceType::Type::Mutexinoutset) || + "DEPOBJ" >> pure(OmpDependenceType::Type::Depobj))) TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US, construct(construct( "SINK :" >> nonemptyList(Parser{}))) || construct( construct("SOURCE"_tok)) || - construct(construct( - Parser{}, ":" >> nonemptyList(designator)))) + sourced(construct( + construct(maybe(Parser{}), + maybe(","_tok) >> Parser{}, + ":" >> nonemptyList(designator))))) // 2.15.3.7 LINEAR (linear-list: linear-step) // linear-list -> list | modifier(list) diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -1778,6 +1778,18 @@ Walk(std::get(x.t)); } // OpenMP Clauses & Directives + void Unparse(const OmpIteratorSpecifier &x) { + Walk(std::get>(x.t), "::"); + const auto &bounds{std::get(x.t)}; + Walk(bounds.name), Put('='); + Walk(bounds.lower), Put(':'), Walk(bounds.upper), Walk(":", bounds.step); + } + void Unparse(const OmpIteratorSpecifierList &x) { Walk(" ", x.v, ", "); } + void Unparse(const OmpIterator &x) { + Word("ITERATOR("); + Walk(std::get(x.t)); + Put(")"); + } void Unparse(const OmpObject &x) { std::visit(common::visitors{ [&](const Designator &y) { Walk(y); }, @@ -1842,6 +1854,7 @@ } void Unparse(const OmpDependClause::InOut &x) { Put("("); + Walk(std::get>(x.t), ", "); Walk(std::get(x.t)); Put(":"); Walk(std::get>(x.t), ","); diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1083,6 +1083,9 @@ static bool NeedsScope(const parser::OpenMPBlockConstruct &); + bool Pre(const parser::OmpIteratorSpecifier &); + bool Pre(const parser::OmpDependClause &); + void Post(const parser::OmpDependClause &); bool Pre(const parser::OpenMPBlockConstruct &); void Post(const parser::OpenMPBlockConstruct &); bool Pre(const parser::OmpBeginBlockDirective &x) { @@ -6400,6 +6403,34 @@ bool pushedScope_{false}; }; +bool OmpVisitor::Pre(const parser::OmpIteratorSpecifier &x) { + auto &type{std::get>(x.t)}; + auto &bounds{std::get(x.t)}; + DeclareStatementEntity(bounds.name.thing.thing, type); + Walk(bounds); + return false; +} + +bool OmpVisitor::Pre(const parser::OmpDependClause &x) { + messageHandler().set_currStmtSource(x.source); + std::visit( + common::visitors{ + [&](const parser::OmpDependClause::Source &) {}, + [&](const parser::OmpDependClause::Sink &) {}, + [&](const parser::OmpDependClause::InOut &y) { + PushScope(Scope::Kind::OmpIterators, nullptr); + Walk(y); + PopScope(); + }, + }, + x.u); + return false; +} + +void OmpVisitor::Post(const parser::OmpDependClause &) { + messageHandler().set_currStmtSource(std::nullopt); +} + bool OmpAttributeVisitor::Pre(const parser::OpenMPBlockConstruct &x) { const auto &beginBlockDir{std::get(x.t)}; const auto &beginDir{std::get(beginBlockDir.t)}; diff --git a/flang/test/Semantics/omp-clause-validity01.f90 b/flang/test/Semantics/omp-clause-validity01.f90 --- a/flang/test/Semantics/omp-clause-validity01.f90 +++ b/flang/test/Semantics/omp-clause-validity01.f90 @@ -445,6 +445,22 @@ a = 3.14 !$omp end task + !$omp task depend(iterator( it=1_4:100:2), in:arrayA(it)) + a = 3.14 + !$omp end task + + !$omp task depend(iterator(integer :: it=1_4:100:2), in:arrayA(it)) + a = 3.14 + !$omp end task + + !$omp task depend(in: b) depend(mutexinoutset: c) + a = 3.14 + !$omp end task + + !$omp task depend(depobj: obj) + a = 3.14 + !$omp end task + ! 2.9.3 taskloop-simd-clause -> taskloop-clause | ! simd-clause