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 @@ -97,6 +97,7 @@ void Enter(const parser::OpenMPBlockConstruct &); void Leave(const parser::OpenMPBlockConstruct &); + void Leave(const parser::OmpBeginBlockDirective &); void Enter(const parser::OmpEndBlockDirective &); void Enter(const parser::OpenMPSectionsConstruct &); @@ -139,6 +140,7 @@ void Enter(const parser::OmpClause::Copyin &); void Enter(const parser::OmpClause::Copyprivate &); void Enter(const parser::OmpClause::Default &); + void Enter(const parser::OmpClause::Depend &); void Enter(const parser::OmpClause::Device &); void Enter(const parser::OmpClause::DistSchedule &); void Enter(const parser::OmpClause::Final &); @@ -156,8 +158,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 &); @@ -182,7 +186,6 @@ void Leave(const parser::OmpAtomic &); void Enter(const parser::OmpAlignedClause &); void Enter(const parser::OmpDefaultmapClause &); - void Enter(const parser::OmpDependClause &); void Enter(const parser::OmpIfClause &); void Enter(const parser::OmpLinearClause &); void Enter(const parser::OmpMapClause &); @@ -203,6 +206,9 @@ void CheckDependList(const parser::DataRef &); void CheckDependArraySection( const common::Indirection &, const parser::Name &); + void ChecksOnOrderedAsStandalone( + const parser::OpenMPSimpleStandaloneConstruct &); + void ChecksOnOrderedAsBlock(); 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 @@ -207,6 +207,19 @@ } } +void OmpStructureChecker::Leave( + const parser::OmpBeginBlockDirective &beginBlockDir) { + const auto &beginDir{std::get(beginBlockDir.t)}; + switch (beginDir.v) { + case llvm::omp::OMPD_ordered: { + // [5.0] 2.17.9 Ordered Construct Restriction + ChecksOnOrderedAsBlock(); + } break; + default: + break; + } +} + void OmpStructureChecker::Leave(const parser::OpenMPBlockConstruct &) { dirContext_.pop_back(); } @@ -289,7 +302,17 @@ } void OmpStructureChecker::Leave( - const parser::OpenMPSimpleStandaloneConstruct &) { + const parser::OpenMPSimpleStandaloneConstruct &x) { + const auto &beginStandaloneDir{ + std::get(x.t)}; + switch (beginStandaloneDir.v) { + case llvm::omp::OMPD_ordered: { + // [5.0] 2.17.9 Ordered Construct Restriction + ChecksOnOrderedAsStandalone(x); + } break; + default: + break; + } dirContext_.pop_back(); } @@ -502,6 +525,8 @@ CHECK_SIMPLE_CLAUSE(Relaxed, OMPC_relaxed) CHECK_SIMPLE_CLAUSE(Hint, OMPC_hint) CHECK_SIMPLE_CLAUSE(ProcBind, OMPC_proc_bind) +CHECK_SIMPLE_CLAUSE(Simd, OMPC_simd) +CHECK_SIMPLE_CLAUSE(Threads, OMPC_threads) CHECK_SIMPLE_CLAUSE(DistSchedule, OMPC_dist_schedule) CHECK_REQ_SCALAR_INT_CLAUSE(Allocator, OMPC_allocator) @@ -781,9 +806,9 @@ } } -void OmpStructureChecker::Enter(const parser::OmpDependClause &x) { +void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) { CheckAllowed(llvm::omp::Clause::OMPC_depend); - if (const auto *inOut{std::get_if(&x.u)}) { + if (const auto *inOut{std::get_if(&x.v.u)}) { const auto &designators{std::get>(inOut->t)}; for (const auto &ele : designators) { if (const auto *dataRef{std::get_if(&ele.u)}) { @@ -857,6 +882,49 @@ } } +void OmpStructureChecker::ChecksOnOrderedAsStandalone( + const parser::OpenMPSimpleStandaloneConstruct &x) { + const auto &ompClauseList{std::get(x.t)}; + bool isSourcePresent{false}; + bool isSinkPresent{false}; + int dependSourceCount{0}; + for (const auto &clause : ompClauseList.v) { + if (const auto *dependClause{ + parser::Unwrap(clause.u)}) { + if (parser::Unwrap(*dependClause)) { + isSourcePresent = true; + dependSourceCount++; + } + if (parser::Unwrap(*dependClause)) { + isSinkPresent = true; + } + } else { // SIMD/THREADS not allowed. + context_.Say(parser::FindSourceLocation(clause), + "Threads, simd clauses are not allowed when ORDERED construct is a " + "standalone " + "construct with no ORDERED region"_err_en_US); + } + } + if (isSourcePresent && isSinkPresent) { + context_.Say(ompClauseList.source, + "DEPEND(sink:vec) is not allowed when DEPEND(source) is present on" + " the ORDERED directive"_err_en_US); + } + if (dependSourceCount > 1) { + context_.Say(ompClauseList.source, + "At most one DEPEND(source) clause can appear on the ORDERED" + " directive"_err_en_US); + } +} + +void OmpStructureChecker::ChecksOnOrderedAsBlock() { + if (FindClause(llvm::omp::Clause::OMPC_depend)) { + context_.Say(GetContext().clauseSource, + "DEPEND(*) clauses are not allowed when ORDERED construct is a block" + " construct with an ORDERED region"_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 @@ -249,6 +249,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; } @@ -323,6 +326,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}; @@ -954,6 +971,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,47 @@ !$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) + + ![5.0][2.17.9] Ordered construct !$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 + !$omp ordered simd + !$omp end ordered + !ERROR: DEPEND(*) clauses are not allowed when ORDERED construct is a block construct with an ORDERED region + !$omp ordered depend(source) + !$omp end ordered + !ERROR: DEPEND(*) clauses are not allowed when ORDERED construct is a block construct with an ORDERED region + !$omp ordered depend(sink:i-4) + !$omp end ordered + !ERROR: At most one SIMD clause can appear on the ORDERED directive + !$omp ordered simd simd + !$omp end ordered + !ERROR: Threads, simd clauses are not allowed when ORDERED construct is a standalone construct with no ORDERED region + !$omp ordered simd + !ERROR: Threads, simd clauses are not allowed when ORDERED construct is a standalone construct with no ORDERED region + !$omp ordered threads + !$omp flush (c) !$omp flush acq_rel !$omp flush release @@ -501,10 +534,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"> {