diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -155,8 +155,10 @@ void Enter(const parser::OmpClause::Reduction &); void Enter(const parser::OmpClause::Safelen &); void Enter(const parser::OmpClause::Shared &); + void Enter(const parser::OmpClause::Simd &); void Enter(const parser::OmpClause::Simdlen &); void Enter(const parser::OmpClause::TaskReduction &); + void Enter(const parser::OmpClause::Threads &); void Enter(const parser::OmpClause::ThreadLimit &); void Enter(const parser::OmpClause::To &); void Enter(const parser::OmpClause::Link &); @@ -202,6 +204,7 @@ void CheckDependList(const parser::DataRef &); void CheckDependArraySection( const common::Indirection &, const parser::Name &); + void CheckDependOnOrderedDir(); void CheckIsVarPartOfAnotherVar(const parser::OmpObjectList &objList); void CheckIntentInPointer( const parser::OmpObjectList &, const llvm::omp::Clause); diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -393,6 +393,11 @@ llvm::omp::Clause::OMPC_copyprivate, {llvm::omp::Clause::OMPC_nowait}); } + // [5.0] 2.17.9 Ordered Construct Restriction + if (GetContext().directive == llvm::omp::Directive::OMPD_ordered) { + CheckDependOnOrderedDir(); + } + GetContext().requiredClauses.IterateOverMembers( [this](llvm::omp::Clause c) { CheckRequired(c); }); } @@ -433,6 +438,8 @@ CHECK_SIMPLE_CLAUSE(Hint, OMPC_hint) CHECK_SIMPLE_CLAUSE(ProcBind, OMPC_proc_bind) CHECK_SIMPLE_CLAUSE(DistSchedule, OMPC_dist_schedule) +CHECK_SIMPLE_CLAUSE(Simd, OMPC_simd) +CHECK_SIMPLE_CLAUSE(Threads, OMPC_threads) CHECK_REQ_SCALAR_INT_CLAUSE(Allocator, OMPC_allocator) CHECK_REQ_SCALAR_INT_CLAUSE(Grainsize, OMPC_grainsize) @@ -770,6 +777,66 @@ } } +void OmpStructureChecker::CheckDependOnOrderedDir() { + const auto dependClauseRange{ + GetContext().clauseInfo.equal_range(llvm::omp::Clause::OMPC_depend)}; + const auto numberOfOmpDepend{ + std::distance(dependClauseRange.first, dependClauseRange.second)}; + // Skip the checks/computation when there is only 1 depend clause. + if (numberOfOmpDepend >= 2) { + // Vector of `Fortran::parser::OmpDependClause` pointers. + std::vector ompDependVector; + + for (auto it = dependClauseRange.first; it != dependClauseRange.second; + ++it) { + if (const auto *parserClause{it->second}) { + // Extract `OmpDependClause` from `OmpClause`. + const auto &dependClause{ + std::get(parserClause->u)}; + ompDependVector.push_back(&dependClause); + } + } + + const parser::OmpDependClause::Source *foundSource{nullptr}; + const parser::OmpDependClause::Source *foundSourceFromEnd{nullptr}; + const parser::OmpDependClause::Sink *foundSink{nullptr}; + for (const auto *vecElem : ompDependVector) { + foundSource = std::get_if(&vecElem->u); + if (foundSource != nullptr) { + break; + } + } + for (const auto *vecElem : ompDependVector) { + foundSink = std::get_if(&vecElem->u); + if (foundSink != nullptr) { + break; + } + } + + if (foundSource && foundSink) { + context_.Say(GetContext().clauseSource, + "DEPEND(sink:vec) is not allowed when DEPEND(source) is present on" + " the ORDERED directive"_err_en_US); + } + + if (foundSource) { // Skip loop if no `Source` found initially. + for (auto iter{ompDependVector.cend()}; + iter-- != ompDependVector.cbegin();) { + foundSourceFromEnd = + std::get_if(&(*iter)->u); + if (foundSourceFromEnd != nullptr) { + break; + } + } + } + if (foundSource && foundSourceFromEnd && + foundSource != foundSourceFromEnd) { + context_.Say(GetContext().clauseSource, + "At most one DEPEND(source) clause can appear on the ORDERED" + " directive"_err_en_US); + } + } +} void OmpStructureChecker::CheckIntentInPointer( const parser::OmpObjectList &objectList, const llvm::omp::Clause clause) { std::vector symbols; diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -247,6 +247,9 @@ bool Pre(const parser::OpenMPBlockConstruct &); void Post(const parser::OpenMPBlockConstruct &); + bool Pre(const parser::OpenMPSimpleStandaloneConstruct &); + void Post(const parser::OpenMPSimpleStandaloneConstruct &) { PopContext(); } + void Post(const parser::OmpBeginBlockDirective &) { GetContext().withinConstruct = true; } @@ -321,6 +324,20 @@ ResolveOmpNameList(alignedNameList, Symbol::Flag::OmpAligned); return false; } + bool Pre(const parser::OmpDependClause &x) { + if (const auto *dependSink{ + std::get_if(&x.u)}) { + const auto &dependSinkVec{dependSink->v}; + for (const auto &dependSinkElement : dependSinkVec) { + const auto &name{std::get(dependSinkElement.t)}; + if (!ResolveName(&name)) { + context_.Say( + name.source, "No type declared for '%s'"_err_en_US, name.source); + } + } + } + return false; + } void Post(const parser::Name &); const parser::OmpClause *associatedClause{nullptr}; @@ -874,6 +891,27 @@ PopContext(); } +bool OmpAttributeVisitor::Pre( + const parser::OpenMPSimpleStandaloneConstruct &x) { + const auto &standaloneDir{ + std::get(x.t)}; + switch (standaloneDir.v) { + case llvm::omp::Directive::OMPD_barrier: + case llvm::omp::Directive::OMPD_ordered: + case llvm::omp::Directive::OMPD_target_enter_data: + case llvm::omp::Directive::OMPD_target_exit_data: + case llvm::omp::Directive::OMPD_target_update: + case llvm::omp::Directive::OMPD_taskwait: + case llvm::omp::Directive::OMPD_taskyield: + PushContext(standaloneDir.source, standaloneDir.v); + break; + default: + break; + } + ClearDataSharingAttributeObjects(); + return true; +} + bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) { const auto &beginLoopDir{std::get(x.t)}; const auto &beginDir{std::get(beginLoopDir.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 @@ -477,14 +477,34 @@ !$omp barrier !$omp taskwait !$omp taskwait depend(source) - !ERROR: Internal: no symbol found for 'i' !$omp taskwait depend(sink:i-1) ! !$omp target enter data map(to:arrayA) map(alloc:arrayB) ! !$omp target update from(arrayA) to(arrayB) ! !$omp target exit data map(from:arrayA) map(delete:arrayB) + !$omp ordered depend(source) - !ERROR: Internal: no symbol found for 'i' !$omp ordered depend(sink:i-1) + !ERROR: No type declared for 'undecvar' + !$omp ordered depend(sink:undecvar-1) + !There is no sink/source + !$omp ordered depend(in:p) depend(in:q) depend(out:r) + !Multiple sink allowed but not source. + !$omp ordered depend(sink:i-1) depend(sink:i-1) + !$omp ordered depend(sink:i-1) depend(sink:i-1) depend(in:p) depend(out:p) + !$omp ordered depend(out:p) depend(in:p) + !ERROR: At most one DEPEND(source) clause can appear on the ORDERED directive + !$omp ordered depend(source) depend(source) + !ERROR: At most one DEPEND(source) clause can appear on the ORDERED directive + !$omp ordered depend(source) depend(in:p) depend(source) + !ERROR: DEPEND(sink:vec) is not allowed when DEPEND(source) is present on the ORDERED directive + !$omp ordered depend(source) depend(sink:i-1) + + !ERROR: At most one THREADS clause can appear on the ORDERED directive + !$omp ordered threads threads + !$omp end ordered + !ERROR: At most one SIMD clause can appear on the ORDERED directive + !$omp ordered simd simd + !$omp end ordered !$omp flush (c) !$omp flush acq_rel !$omp flush release @@ -501,10 +521,8 @@ ! 2.13.2 critical Construct - !ERROR: Internal: no symbol found for 'first' !$omp critical (first) a = 3.14 - !ERROR: Internal: no symbol found for 'first' !$omp end critical (first) ! 2.9.1 task-clause -> if-clause | diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -456,9 +456,11 @@ } def OMP_Ordered : Directive<"ordered"> { let allowedClauses = [ + VersionedClause + ]; + let allowedOnceClauses = [ VersionedClause, VersionedClause, - VersionedClause ]; } def OMP_Atomic : Directive<"atomic"> {