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 @@ -3710,7 +3710,7 @@ struct OpenMPFlushConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct); CharBlock source; - std::tuple, + std::tuple>, std::optional> t; }; diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp --- a/flang/lib/Lower/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP.cpp @@ -109,7 +109,8 @@ std::get>( flushConstruct.t)) genObjectList(*ompObjectList, converter, operandRange); - if (std::get>( + if (std::get>>( flushConstruct.t)) TODO("Handle OmpMemoryOrderClause"); converter.getFirOpBuilder().create( 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 @@ -317,7 +317,7 @@ "RELAXED" >> construct(construct()))))) TYPE_PARSER(sourced(construct(verbatim("FLUSH"_tok), - maybe(Parser{}), + many(maybe(","_tok) >> sourced(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 @@ -2423,7 +2423,7 @@ 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.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 @@ -208,7 +208,17 @@ 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(); } 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 @@ -487,6 +487,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) !ERROR: SEQ_CST clause is not allowed on the FLUSH directive !$omp flush seq_cst diff --git a/flang/test/Semantics/omp-flush01.f90 b/flang/test/Semantics/omp-flush01.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/omp-flush01.f90 @@ -0,0 +1,39 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp + +! 2.17.8 Flush construct [OpenMP 5.0] +! memory-order-clause -> +! acq_rel +! release +! acquire +use omp_lib + implicit none + + integer :: i, a, b + real, DIMENSION(10) :: array + + a = 1.0 + !$omp parallel num_threads(4) + !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 + + !ERROR: expected end of line + !ERROR: expected end of line + !$omp flush private(array) + !ERROR: expected end of line + !ERROR: expected end of line + !$omp flush num_threads(4) + + ! Mix allowed and not allowed clauses. + !ERROR: expected end of line + !ERROR: expected end of line + !$omp flush num_threads(4) acquire + end if + !$omp end parallel +end + diff --git a/flang/test/Semantics/omp-flush02.f90 b/flang/test/Semantics/omp-flush02.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/omp-flush02.f90 @@ -0,0 +1,86 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp + +! Check OpenMP 5.0 - 2.17.8 flush Construct +! Restriction - +! If memory-order-clause is release, acquire, or acq_rel, list items must not be specified on the flush directive. + +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 + ! 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 + + ! 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 + + ! Mix of allowed and not allowed. + !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 @@ -445,7 +445,7 @@ ]; } def OMP_Flush : Directive<"flush"> { - let allowedClauses = [ + let allowedOnceClauses = [ VersionedClause, VersionedClause, VersionedClause,