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 @@ -548,7 +548,6 @@ NODE(parser, OpenMPDeclareReductionConstruct) NODE(parser, OpenMPDeclareSimdConstruct) NODE(parser, OpenMPDeclareTargetConstruct) - NODE(parser, OmpFlushMemoryClause) NODE(parser, OpenMPFlushConstruct) NODE(parser, OpenMPLoopConstruct) NODE(parser, OpenMPSimpleStandaloneConstruct) 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 @@ -3698,19 +3698,14 @@ }; // 2.17.8 Flush Construct [OpenMP 5.0] +// 2.17.8 flush -> FLUSH [memory-order-clause] [(variable-name-list)] // memory-order-clause -> acq_rel // release // acquire -struct OmpFlushMemoryClause { - WRAPPER_CLASS_BOILERPLATE(OmpFlushMemoryClause, llvm::omp::Clause); - CharBlock source; -}; - -// 2.17.8 flush -> FLUSH [memory-order-clause] [(variable-name-list)] struct OpenMPFlushConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct); CharBlock source; - std::tuple, + std::tuple, std::optional> t; }; 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 @@ -306,13 +306,8 @@ // memory-order-clause -> acq_rel // release // acquire -TYPE_PARSER(sourced(construct( - "ACQ_REL" >> pure(llvm::omp::Clause::OMPC_acq_rel) || - "RELEASE" >> pure(llvm::omp::Clause::OMPC_release) || - "ACQUIRE" >> pure(llvm::omp::Clause::OMPC_acquire)))) - TYPE_PARSER(sourced(construct(verbatim("FLUSH"_tok), - maybe(Parser{}), + maybe(Parser{}), maybe(parenthesized(Parser{}))))) // Simple Standalone Directives 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 @@ -2419,25 +2419,10 @@ Put("\n"); EndOpenMP(); } - void Unparse(const OmpFlushMemoryClause &x) { - switch (x.v) { - case llvm::omp::Clause::OMPC_acq_rel: - Word("ACQ_REL "); - break; - case llvm::omp::Clause::OMPC_release: - Word("RELEASE "); - break; - case llvm::omp::Clause::OMPC_acquire: - Word("ACQUIRE "); - break; - default: - break; - } - } void Unparse(const OpenMPFlushConstruct &x) { BeginOpenMP(); Word("!$OMP FLUSH "); - Walk(std::get>(x.t)); + Walk(std::get>(x.t)); Walk(" (", std::get>(x.t), ")"); Put("\n"); EndOpenMP(); 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 @@ -150,6 +150,12 @@ void Enter(const parser::OmpClause::Uniform &); void Enter(const parser::OmpClause::UseDevicePtr &); void Enter(const parser::OmpClause::IsDevicePtr &); + // Memory-order-clause + void Enter(const parser::OmpClause::SeqCst &); + void Enter(const parser::OmpClause::AcqRel &); + void Enter(const parser::OmpClause::Release &); + void Enter(const parser::OmpClause::Acquire &); + void Enter(const parser::OmpClause::Relaxed &); void Enter(const parser::OmpAlignedClause &); void Enter(const parser::OmpAllocateClause &); 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 @@ -174,7 +174,16 @@ PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_flush); } -void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &) { +void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &x) { + if (FindClause(llvm::omp::Clause::OMPC_acquire) || + FindClause(llvm::omp::Clause::OMPC_release) || + FindClause(llvm::omp::Clause::OMPC_acq_rel)) { + if (const auto &flushList{ + std::get>(x.t)}) { + context_.Say(parser::FindSourceLocation(flushList), + "If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive"_err_en_US); + } + } dirContext_.pop_back(); } @@ -449,6 +458,22 @@ void OmpStructureChecker::Enter(const parser::OmpClause::IsDevicePtr &) { CheckAllowed(llvm::omp::Clause::OMPC_is_device_ptr); } +// Memory-order-clause +void OmpStructureChecker::Enter(const parser::OmpClause::SeqCst &) { + CheckAllowed(llvm::omp::Clause::OMPC_seq_cst); +} +void OmpStructureChecker::Enter(const parser::OmpClause::AcqRel &) { + CheckAllowed(llvm::omp::Clause::OMPC_acq_rel); +} +void OmpStructureChecker::Enter(const parser::OmpClause::Release &) { + CheckAllowed(llvm::omp::Clause::OMPC_release); +} +void OmpStructureChecker::Enter(const parser::OmpClause::Acquire &) { + CheckAllowed(llvm::omp::Clause::OMPC_acquire); +} +void OmpStructureChecker::Enter(const parser::OmpClause::Relaxed &) { + CheckAllowed(llvm::omp::Clause::OMPC_relaxed); +} void OmpStructureChecker::Enter(const parser::OmpAlignedClause &x) { CheckAllowed(llvm::omp::Clause::OMPC_aligned); 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 @@ -475,6 +475,7 @@ !$omp flush acq_rel !$omp flush release !$omp flush acquire + !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive !$omp flush release (c) !$omp cancel DO !$omp cancellation point parallel diff --git a/flang/test/Semantics/omp-flush.f90 b/flang/test/Semantics/omp-flush.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/omp-flush.f90 @@ -0,0 +1,92 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp +! Check OpenMP 5.0 - 2.17.8 flush Construct + use omp_lib + implicit none + + TYPE someStruct + REAL :: rr + end TYPE + integer :: i, a, b + real, DIMENSION(10) :: array + TYPE(someStruct) :: structObj + + a = 1.0 + !$omp parallel num_threads(4) + !No list flushes all. + if (omp_get_thread_num() == 1) THEN + !$omp flush + END IF + + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + !Only memory-order-clauses. + if (omp_get_thread_num() == 1) THEN + ! Allowed clauses. + !$omp flush ACQ_REL + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + !$omp flush RELEASE + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + !$omp flush ACQUIRE + + ! Not allowed more than once. + !ERROR: At most one ACQ_REL clause can appear on the FLUSH directive + !$omp flush ACQ_REL ACQ_REL + !ERROR: At most one RELEASE clause can appear on the FLUSH directive + !$omp flush RELEASE RELEASE + !ERROR: At most one ACQUIRE clause can appear on the FLUSH directive + !$omp flush ACQUIRE ACQUIRE + + ! Not allowed clauses. + !ERROR: SEQ_CST clause is not allowed on the FLUSH directive + !$omp flush SEQ_CST + + !ERROR: RELAXED clause is not allowed on the FLUSH directive + !$omp flush RELAXED + + !ERROR: PRIVATE clause is not allowed on the FLUSH directive + !$omp flush PRIVATE(array) + + ! Mix allowed and not allowed clauses. + !ERROR: SEQ_CST clause is not allowed on the FLUSH directive + !$omp flush SEQ_CST ACQUIRE + END IF + + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + ! No memory-order-clause only list-items. + if (omp_get_thread_num() == 2) THEN + !$omp flush (a) + !$omp flush (i, a, b) + !$omp flush (array, structObj%rr) + ! Too many flush with repeating list items. + !$omp flush (i, a, b, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, b, b, b, b) + !ERROR: No explicit type declared for 'notpresentitem' + !$omp flush (notPresentItem) + END IF + + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + if (omp_get_thread_num() == 3) THEN + !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive + !$omp flush ACQ_REL (array) + !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive + !$omp flush ACQ_REL (array, a, i) + + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive + !$omp flush RELEASE (array) + !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive + !$omp flush RELEASE (array, a) + + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive + !$omp flush ACQUIRE (array) + !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive + !$omp flush ACQUIRE (array, a, structObj%rr) + END IF + !$omp end parallel + + !$omp parallel num_threads(4) + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + !$omp master + !$omp flush (array) + !$omp end master + !$omp end parallel +end 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 @@ -420,11 +420,11 @@ ]; } def OMP_Flush : Directive<"flush"> { - let allowedClauses = [ + let allowedOnceClauses = [ VersionedClause, VersionedClause, VersionedClause, - // TODO This should ne `none` instead. Comment carried over from + // TODO This should be `none` instead. Comment carried over from // OMPKinds.def. VersionedClause ];