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 @@ -520,6 +520,8 @@ NODE(parser, OpenMPDeclareReductionConstruct) NODE(parser, OpenMPDeclareSimdConstruct) NODE(parser, OpenMPDeclareTargetConstruct) + NODE(parser, OmpFlushMemoryClause) + NODE_ENUM(OmpFlushMemoryClause, FlushMemoryOrder) 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 @@ -3716,11 +3716,23 @@ std::tuple> t; }; -// 2.13.7 flush -> FLUSH [(variable-name-list)] +// 2.17.8 Flush Construct [OpenMP 5.0] +// memory-order-clause -> acq_rel +// release +// acquire +struct OmpFlushMemoryClause { + ENUM_CLASS(FlushMemoryOrder, AcqRel, Release, Acquire) + WRAPPER_CLASS_BOILERPLATE(OmpFlushMemoryClause, FlushMemoryOrder); + CharBlock source; +}; + +// 2.17.8 flush -> FLUSH [memory-order-clause] [(variable-name-list)] struct OpenMPFlushConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct); CharBlock source; - std::tuple> t; + std::tuple, + std::optional> + t; }; struct OmpSimpleStandaloneDirective { 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 @@ -298,9 +298,19 @@ TYPE_PARSER(sourced(construct(verbatim("CANCEL"_tok), Parser{}, maybe("IF" >> parenthesized(scalarLogicalExpr))))) -// 2.13.7 Flush construct -TYPE_PARSER(sourced(construct( - verbatim("FLUSH"_tok), maybe(parenthesized(Parser{}))))) +// 2.17.8 Flush construct [OpenMP 5.0] +// flush -> FLUSH [memory-order-clause] [(variable-name-list)] +// memory-order-clause -> acq_rel +// release +// acquire +TYPE_PARSER(sourced(construct( + "ACQ_REL" >> pure(OmpFlushMemoryClause::FlushMemoryOrder::AcqRel) || + "RELEASE" >> pure(OmpFlushMemoryClause::FlushMemoryOrder::Release) || + "ACQUIRE" >> pure(OmpFlushMemoryClause::FlushMemoryOrder::Acquire)))) + +TYPE_PARSER(sourced(construct(verbatim("FLUSH"_tok), + maybe(Parser{}), + maybe(parenthesized(Parser{}))))) // Simple Standalone Directives TYPE_PARSER(sourced(construct(first( 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 @@ -2359,10 +2359,24 @@ Put("\n"); EndOpenMP(); } + void Unparse(const OmpFlushMemoryClause &x) { + switch (x.v) { + case OmpFlushMemoryClause::FlushMemoryOrder::AcqRel: + Word("ACQ_REL "); + break; + case OmpFlushMemoryClause::FlushMemoryOrder::Release: + Word("RELEASE "); + break; + case OmpFlushMemoryClause::FlushMemoryOrder::Acquire: + Word("ACQUIRE "); + break; + } + } void Unparse(const OpenMPFlushConstruct &x) { BeginOpenMP(); - Word("!$OMP FLUSH"); - Walk("(", std::get>(x.t), ")"); + Word("!$OMP FLUSH "); + Walk(std::get>(x.t)); + Walk(" (", std::get>(x.t), ")"); Put("\n"); EndOpenMP(); } 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 @@ -403,6 +403,10 @@ !ERROR: Internal: no symbol found for 'i' !$omp ordered depend(sink:i-1) !$omp flush (c) + !$omp flush acq_rel + !$omp flush release + !$omp flush acquire + !$omp flush release (c) !$omp cancel DO !$omp cancellation point parallel