@@ -1281,6 +1281,16 @@ static bool IsFortranBlockConstruct(const ExecutionPartConstruct &epc) {
12811281 }
12821282}
12831283
1284+ static bool IsStandaloneOrdered(const OmpDirectiveSpecification &dirSpec) {
1285+ // An ORDERED construct is standalone if it has DOACROSS or DEPEND clause.
1286+ return dirSpec.DirId() == llvm::omp::Directive::OMPD_ordered &&
1287+ llvm::any_of(dirSpec.Clauses().v, [](const OmpClause &clause) {
1288+ llvm::omp::Clause id{clause.Id()};
1289+ return id == llvm::omp::Clause::OMPC_depend ||
1290+ id == llvm::omp::Clause::OMPC_doacross;
1291+ });
1292+ }
1293+
12841294struct StrictlyStructuredBlockParser {
12851295 using resultType = Block;
12861296
@@ -1464,6 +1474,9 @@ struct OmpBlockConstructParser {
14641474
14651475 std::optional<resultType> Parse(ParseState &state) const {
14661476 if (auto &&begin{OmpBeginDirectiveParser(dir_).Parse(state)}) {
1477+ if (IsStandaloneOrdered(*begin)) {
1478+ return std::nullopt;
1479+ }
14671480 if (auto &&body{attempt(StrictlyStructuredBlockParser{}).Parse(state)}) {
14681481 // Try strictly-structured block with an optional end-directive
14691482 auto end{maybe(OmpEndDirectiveParser{dir_}).Parse(state)};
@@ -1475,17 +1488,6 @@ struct OmpBlockConstructParser {
14751488 attempt(LooselyStructuredBlockParser{}).Parse(state)}) {
14761489 // Try loosely-structured block with a mandatory end-directive.
14771490 auto end{maybe(OmpEndDirectiveParser{dir_}).Parse(state)};
1478- // Dereference outer optional (maybe() always succeeds) and look at the
1479- // inner optional.
1480- bool endPresent{end->has_value()};
1481-
1482- // ORDERED is special. We do need to return failure here so that the
1483- // standalone ORDERED construct can be distinguished from the block
1484- // associated construct.
1485- if (!endPresent && dir_ == llvm::omp::Directive::OMPD_ordered) {
1486- return std::nullopt;
1487- }
1488-
14891491 // Delay the error for a missing end-directive until semantics so that
14901492 // we have better control over the output.
14911493 return OmpBlockConstruct{OmpBeginDirective(std::move(*begin)),
@@ -1642,7 +1644,6 @@ TYPE_PARSER(sourced( //
16421644static bool IsSimpleStandalone(const OmpDirectiveName &name) {
16431645 switch (name.v) {
16441646 case llvm::omp::Directive::OMPD_barrier:
1645- case llvm::omp::Directive::OMPD_ordered:
16461647 case llvm::omp::Directive::OMPD_scan:
16471648 case llvm::omp::Directive::OMPD_target_enter_data:
16481649 case llvm::omp::Directive::OMPD_target_exit_data:
@@ -1658,7 +1659,9 @@ static bool IsSimpleStandalone(const OmpDirectiveName &name) {
16581659TYPE_PARSER(sourced( //
16591660 construct<OpenMPSimpleStandaloneConstruct>(
16601661 predicated(OmpDirectiveNameParser{}, IsSimpleStandalone) >=
1661- Parser<OmpDirectiveSpecification>{})))
1662+ Parser<OmpDirectiveSpecification>{}) ||
1663+ construct<OpenMPSimpleStandaloneConstruct>(
1664+ predicated(Parser<OmpDirectiveSpecification>{}, IsStandaloneOrdered))))
16621665
16631666TYPE_PARSER(sourced( //
16641667 construct<OpenMPFlushConstruct>(
0 commit comments