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,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(); } 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,53 @@ +! 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 + + ! 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 + + !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 seq_cst acquire + !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,75 @@ +! 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 + 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 +