diff --git a/flang/lib/parser/dump-parse-tree.h b/flang/lib/parser/dump-parse-tree.h index 2f9fe06f37fc..85cbb15255dc 100644 --- a/flang/lib/parser/dump-parse-tree.h +++ b/flang/lib/parser/dump-parse-tree.h @@ -413,6 +413,7 @@ public: NODE(parser, OmpAtomicUpdate) NODE(parser, OmpAtomicWrite) NODE(parser, OmpBeginBlockDirective) + NODE(parser, OmpBeginSectionsDirective) NODE(parser, OmpBlockDirective) NODE_ENUM(parser::OmpBlockDirective, Directive) NODE(parser, OmpCancelType) @@ -471,8 +472,7 @@ public: NODE(parser, OmpEndCriticalDirective) NODE(parser, OmpEndDo) NODE(parser, OmpEndDoSimd) - NODE(parser, OmpEndParallelSections) - NODE(parser, OmpEndSections) + NODE(parser, OmpEndSectionsDirective) NODE(parser, OmpIfClause) NODE_ENUM(parser::OmpIfClause, DirectiveNameModifier) NODE(parser, OmpLinearClause) @@ -508,7 +508,9 @@ public: NODE(parser::OmpScheduleModifier, Modifier2) NODE(parser, OmpScheduleModifierType) NODE_ENUM(parser::OmpScheduleModifierType, ModType) - NODE(parser, OmpSection) + NODE(parser, OmpSectionBlocks) + NODE(parser, OmpSectionsDirective) + NODE_ENUM(parser::OmpSectionsDirective, Directive) NODE(parser, OmpSimpleStandaloneDirective) NODE_ENUM(parser::OmpSimpleStandaloneDirective, Directive) NODE(parser, Only) @@ -534,7 +536,6 @@ public: NODE(parser, OpenMPStandaloneConstruct) NODE(parser, OpenMPSectionsConstruct) NODE(parser, OpenMPThreadprivate) - NODE(parser, OpenMPParallelSectionsConstruct) NODE(parser, OpenStmt) NODE(parser, Optional) NODE(parser, OptionalStmt) diff --git a/flang/lib/parser/openmp-grammar.h b/flang/lib/parser/openmp-grammar.h index 5f541b919f6a..c6c06293cbc5 100644 --- a/flang/lib/parser/openmp-grammar.h +++ b/flang/lib/parser/openmp-grammar.h @@ -488,39 +488,40 @@ TYPE_PARSER(construct(maybe(construct("NOWAIT"_tok)))) // OMP END DO [NOWAIT] TYPE_PARSER(construct(maybe(construct("NOWAIT"_tok)))) -// OMP END SECTIONS [NOWAIT] -TYPE_PARSER(startOmpLine >> "END SECTIONS"_tok >> - construct( - maybe("NOWAIT" >> construct()) / endOmpLine)) +// OMP SECTIONS Directive +TYPE_PARSER(construct( + first("SECTIONS" >> pure(OmpSectionsDirective::Directive::Sections), + "PARALLEL SECTIONS" >> + pure(OmpSectionsDirective::Directive::ParallelSections)))) -// OMP SECTIONS -TYPE_PARSER(construct(verbatim("SECTIONS"_tok), - Parser{} / endOmpLine, block, Parser{})) +// OMP BEGIN and END SECTIONS Directive +TYPE_PARSER(construct( + sourced(Parser{}), Parser{})) +TYPE_PARSER( + startOmpLine >> construct( + sourced("END"_tok >> Parser{}), + Parser{})) -// OMP END PARALLEL SECTIONS -TYPE_PARSER(construct( - startOmpLine >> "END PARALLEL SECTIONS"_tok / endOmpLine)) +// OMP SECTION-BLOCK +TYPE_PARSER(maybe(startOmpLine >> "SECTION"_tok / endOmpLine) >> + construct( + nonemptySeparated(block, startOmpLine >> "SECTION"_tok / endOmpLine))) -// OMP PARALLEL SECTIONS -TYPE_PARSER(construct( - verbatim("PARALLEL SECTIONS"_tok), Parser{} / endOmpLine, - block, Parser{})) - -TYPE_PARSER(construct(verbatim("SECTION"_tok) / endOmpLine)) +// OMP SECTIONS, PARALLEL SECTIONS +TYPE_PARSER(construct( + Parser{} / endOmpLine, + Parser{}, Parser{} / endOmpLine)) TYPE_CONTEXT_PARSER("OpenMP construct"_en_US, startOmpLine >> first(construct(Parser{}), - construct( - Parser{}), construct(Parser{}), construct(Parser{}), // OpenMPBlockConstruct is attempted before // OpenMPStandaloneConstruct to resolve !$OMP ORDERED construct(Parser{}), construct(Parser{}), - construct(Parser{}), - construct(Parser{}))) + construct(Parser{}))) // END OMP Block directives TYPE_PARSER( diff --git a/flang/lib/parser/parse-tree.h b/flang/lib/parser/parse-tree.h index 4a2eaac02042..3ad4a07ea245 100644 --- a/flang/lib/parser/parse-tree.h +++ b/flang/lib/parser/parse-tree.h @@ -3468,17 +3468,28 @@ struct OmpClauseList { }; // SECTIONS, PARALLEL SECTIONS -WRAPPER_CLASS(OmpEndSections, std::optional); -WRAPPER_CLASS(OmpSection, Verbatim); -struct OpenMPSectionsConstruct { - TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct); - std::tuple t; +struct OmpSectionsDirective { + ENUM_CLASS(Directive, Sections, ParallelSections); + WRAPPER_CLASS_BOILERPLATE(OmpSectionsDirective, Directive); + CharBlock source; }; -EMPTY_CLASS(OmpEndParallelSections); -struct OpenMPParallelSectionsConstruct { - TUPLE_CLASS_BOILERPLATE(OpenMPParallelSectionsConstruct); - std::tuple t; +struct OmpBeginSectionsDirective { + TUPLE_CLASS_BOILERPLATE(OmpBeginSectionsDirective); + std::tuple t; +}; +struct OmpEndSectionsDirective { + TUPLE_CLASS_BOILERPLATE(OmpEndSectionsDirective); + std::tuple t; +}; + +WRAPPER_CLASS(OmpSectionBlocks, std::list); + +struct OpenMPSectionsConstruct { + TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct); + std::tuple + t; }; // OpenMP directive beginning or ending a block @@ -3729,9 +3740,8 @@ struct OpenMPLoopConstruct { struct OpenMPConstruct { UNION_CLASS_BOILERPLATE(OpenMPConstruct); std::variant + OpenMPLoopConstruct, OpenMPBlockConstruct, OpenMPAtomicConstruct, + OpenMPCriticalConstruct> u; }; } diff --git a/flang/lib/parser/stmt-parser.h b/flang/lib/parser/stmt-parser.h index 021fa7fbe871..ac9a522d2635 100644 --- a/flang/lib/parser/stmt-parser.h +++ b/flang/lib/parser/stmt-parser.h @@ -85,7 +85,7 @@ constexpr auto skipBadLine{SkipPast<'\n'>{} >> construct()}; constexpr auto executionPartErrorRecovery{stmtErrorRecoveryStart >> !"END"_tok >> !"CONTAINS"_tok >> !"ELSE"_tok >> !"CASE"_tok >> !"TYPE IS"_tok >> !"CLASS"_tok >> !"RANK"_tok >> - !("!$OMP "_sptok >> "END"_tok) >> skipBadLine}; + !("!$OMP "_sptok >> ("END"_tok || "SECTION"_id)) >> skipBadLine}; // END statement error recovery constexpr auto missingOptionalName{defaulted(cut >> maybe(name))}; diff --git a/flang/lib/parser/unparse.cc b/flang/lib/parser/unparse.cc index ff4f286fdcb6..fba66fe93178 100644 --- a/flang/lib/parser/unparse.cc +++ b/flang/lib/parser/unparse.cc @@ -2266,33 +2266,33 @@ public: Walk(x.v); EndOpenMP(); } - void Unparse(const OmpSection &x) { - BeginOpenMP(); - Word("!$OMP SECTION"); - Put("\n"); - EndOpenMP(); + void Unparse(const OmpSectionsDirective &x) { + switch (x.v) { + case OmpSectionsDirective::Directive::Sections: Word("SECTIONS "); break; + case OmpSectionsDirective::Directive::ParallelSections: + Word("PARALLEL SECTIONS "); + break; + } + } + void Unparse(const OmpSectionBlocks &x) { + for (const auto &y : x.v) { + BeginOpenMP(); + Word("!$OMP SECTION"); + Put("\n"); + EndOpenMP(); + Walk(y, ""); // y is Block + } } void Unparse(const OpenMPSectionsConstruct &x) { BeginOpenMP(); - Word("!$OMP SECTIONS"); - Walk(std::get(x.t)); + Word("!$OMP "); + Walk(std::get(x.t)); Put("\n"); EndOpenMP(); - Walk(std::get(x.t), ""); + Walk(std::get(x.t)); BeginOpenMP(); - Word("!$OMP END SECTIONS"); - Put("\n"); - EndOpenMP(); - } - void Unparse(const OpenMPParallelSectionsConstruct &x) { - BeginOpenMP(); - Word("!$OMP PARALLEL SECTIONS"); - Walk(std::get(x.t)); - Put("\n"); - EndOpenMP(); - Walk(std::get(x.t), ""); - BeginOpenMP(); - Word("!$OMP END PARALLEL SECTIONS"); + Word("!$OMP END "); + Walk(std::get(x.t)); Put("\n"); EndOpenMP(); } diff --git a/flang/lib/semantics/check-omp-structure.cc b/flang/lib/semantics/check-omp-structure.cc index 81e070d6f05d..bdd3f2531e99 100644 --- a/flang/lib/semantics/check-omp-structure.cc +++ b/flang/lib/semantics/check-omp-structure.cc @@ -212,25 +212,43 @@ void OmpStructureChecker::Leave(const parser::OpenMPBlockConstruct &) { } void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) { - const auto &dir{std::get(x.t)}; - PushContext(dir.source, OmpDirective::SECTIONS); - OmpClauseSet allowed{OmpClause::PRIVATE, OmpClause::FIRSTPRIVATE, - OmpClause::LASTPRIVATE, OmpClause::REDUCTION}; - SetContextAllowed(allowed); + const auto &beginSectionsDir{ + std::get(x.t)}; + const auto &beginDir{ + std::get(beginSectionsDir.t)}; + switch (beginDir.v) { + // 2.7.2 sections-clause -> private-clause | + // firstprivate-clause | + // lastprivate-clause | + // reduction-clause + case parser::OmpSectionsDirective::Directive::Sections: { + PushContext(beginDir.source, OmpDirective::SECTIONS); + OmpClauseSet allowed{OmpClause::PRIVATE, OmpClause::FIRSTPRIVATE, + OmpClause::LASTPRIVATE, OmpClause::REDUCTION}; + SetContextAllowed(allowed); + } break; + case parser::OmpSectionsDirective::Directive::ParallelSections: { + // TODO + } break; + } } void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &) { ompContext_.pop_back(); } -void OmpStructureChecker::Enter(const parser::OmpSection &x) { - const auto &dir{x.v}; // Verbatim - if (!CurrentDirectiveIsNested() || - GetContext().directive != OmpDirective::SECTIONS) { - // if not currently nested, SECTION is orphaned - context_.Say(dir.source, - "SECTION directive must appear within " - "the SECTIONS construct"_err_en_US); +void OmpStructureChecker::Enter(const parser::OmpEndSectionsDirective &x) { + const auto &dir{std::get(x.t)}; + ResetPartialContext(dir.source); + switch (dir.v) { + // 2.7.2 end-sections -> END SECTIONS [nowait-clause] + case parser::OmpSectionsDirective::Directive::Sections: + SetContextDirectiveEnum(OmpDirective::END_SECTIONS); + SetContextAllowed(OmpClauseSet{OmpClause::NOWAIT}); + break; + default: + // no clauses are allowed + break; } } diff --git a/flang/lib/semantics/check-omp-structure.h b/flang/lib/semantics/check-omp-structure.h index 2fcf84680058..a039b2264226 100644 --- a/flang/lib/semantics/check-omp-structure.h +++ b/flang/lib/semantics/check-omp-structure.h @@ -66,7 +66,7 @@ public: void Enter(const parser::OpenMPSectionsConstruct &); void Leave(const parser::OpenMPSectionsConstruct &); - void Enter(const parser::OmpSection &); + void Enter(const parser::OmpEndSectionsDirective &); void Enter(const parser::OpenMPDeclareSimdConstruct &); void Leave(const parser::OpenMPDeclareSimdConstruct &); diff --git a/flang/test/semantics/omp-clause-validity01.f90 b/flang/test/semantics/omp-clause-validity01.f90 index 17d942f4865a..0e7df123ed82 100644 --- a/flang/test/semantics/omp-clause-validity01.f90 +++ b/flang/test/semantics/omp-clause-validity01.f90 @@ -173,13 +173,15 @@ !$omp end sections nowait !$omp end parallel - !ERROR: SECTION directive must appear within the SECTIONS construct - !$omp section - a = 0.0 !$omp parallel - !ERROR: SECTION directive must appear within the SECTIONS construct + !$omp sections + a = 0.0 + b = 1 !$omp section - a = 3.14 + c = 1 + d = 2 + !ERROR: NUM_THREADS clause is not allowed on the END SECTIONS directive + !$omp end sections num_threads(4) !$omp end parallel ! 2.7.3 single-clause -> private-clause |