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 @@ -163,6 +163,7 @@ void Enter(const parser::OmpProcBindClause &); void Enter(const parser::OmpReductionClause &); void Enter(const parser::OmpScheduleClause &); + void Enter(const parser::OmpFlushMemoryClause &); private: 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,23 @@ PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_flush); } -void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &) { +void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &x) { + if (const auto &flushMemClause{ + std::get>(x.t)}) { + switch (flushMemClause.value().v) { + case llvm::omp::Clause::OMPC_release: + case llvm::omp::Clause::OMPC_acq_rel: + case llvm::omp::Clause::OMPC_acquire: + 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); + } + break; + default: + break; + } + } dirContext_.pop_back(); } @@ -579,6 +595,22 @@ CheckAllowed(llvm::omp::Clause::OMPC_reduction); } +void OmpStructureChecker::Enter(const parser::OmpFlushMemoryClause &x) { + switch (x.v) { + case llvm::omp::Clause::OMPC_acquire: + CheckAllowed(llvm::omp::Clause::OMPC_acquire); + break; + case llvm::omp::Clause::OMPC_release: + CheckAllowed(llvm::omp::Clause::OMPC_release); + break; + case llvm::omp::Clause::OMPC_acq_rel: + CheckAllowed(llvm::omp::Clause::OMPC_acq_rel); + break; + default: + break; + } +} + bool OmpStructureChecker::ScheduleModifierHasType( const parser::OmpScheduleClause &x, const parser::OmpScheduleModifierType::ModType &type) { 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,61 @@ +! 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/) + ! 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/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,52 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp +! Check OpenMP 5.0 - 2.17.8 flush Construct +! These checks are caught in parsing as the parser is more strict. + + 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 + + ! Not allowed more than once. + !ERROR: expected end of line + !ERROR: expected end of line + !$omp flush ACQ_REL ACQ_REL + !ERROR: expected end of line + !ERROR: expected end of line + !$omp flush RELEASE RELEASE + !ERROR: expected end of line + !ERROR: expected end of line + !$omp flush ACQUIRE ACQUIRE + + ! Not allowed clauses. + !ERROR: expected end of line + !ERROR: expected end of line + !$omp flush SEQ_CST + + !ERROR: expected end of line + !ERROR: expected end of line + !$omp flush RELAXED + + !ERROR: expected end of line + !ERROR: expected end of line + !$omp flush PRIVATE(array) + + ! Mix allowed and not allowed clauses. + !ERROR: expected end of line + !ERROR: expected end of line + !$omp flush SEQ_CST ACQUIRE + END IF + !$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 ];