diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp index 8d370adc51d61..bdc06a260284d 100644 --- a/flang/examples/FeatureList/FeatureList.cpp +++ b/flang/examples/FeatureList/FeatureList.cpp @@ -527,7 +527,6 @@ struct NodeVisitor { READ_FEATURE(OmpChunkModifier::Value) READ_FEATURE(OmpOrderingModifier) READ_FEATURE(OmpOrderingModifier::Value) - READ_FEATURE(OmpSectionsDirective) READ_FEATURE(Only) READ_FEATURE(OpenACCAtomicConstruct) READ_FEATURE(OpenACCBlockConstruct) diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 1c9fd7673e06d..c34b2190c6b77 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -662,7 +662,6 @@ class ParseTreeDumper { NODE(parser, OmpScheduleClause) NODE(OmpScheduleClause, Modifier) NODE_ENUM(OmpScheduleClause, Kind) - NODE(parser, OmpSectionsDirective) NODE(parser, OmpSelfModifier) NODE_ENUM(OmpSelfModifier, Value) NODE(parser, OmpSeverityClause) diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h index 032fb8996fe48..98e849eef9bbc 100644 --- a/flang/include/flang/Parser/openmp-utils.h +++ b/flang/include/flang/Parser/openmp-utils.h @@ -80,8 +80,7 @@ struct DirectiveNameScope { static OmpDirectiveName GetOmpDirectiveName( const OmpBeginSectionsDirective &x) { - auto &dir{std::get(x.t)}; - return MakeName(dir.source, dir.v); + return x.DirName(); } template diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 7307283eb91ec..72b5c27752e45 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -4879,20 +4879,13 @@ struct OpenMPAssumeConstruct : public OmpBlockConstruct { // 2.7.2 SECTIONS // 2.11.2 PARALLEL SECTIONS -struct OmpSectionsDirective { - WRAPPER_CLASS_BOILERPLATE(OmpSectionsDirective, llvm::omp::Directive); - CharBlock source; +struct OmpBeginSectionsDirective : public OmpBeginDirective { + INHERITED_TUPLE_CLASS_BOILERPLATE( + OmpBeginSectionsDirective, OmpBeginDirective); }; -struct OmpBeginSectionsDirective { - TUPLE_CLASS_BOILERPLATE(OmpBeginSectionsDirective); - std::tuple t; - CharBlock source; -}; -struct OmpEndSectionsDirective { - TUPLE_CLASS_BOILERPLATE(OmpEndSectionsDirective); - std::tuple t; - CharBlock source; +struct OmpEndSectionsDirective : public OmpEndDirective { + INHERITED_TUPLE_CLASS_BOILERPLATE(OmpEndSectionsDirective, OmpEndDirective); }; // [!$omp section] @@ -4909,6 +4902,12 @@ struct OpenMPSectionConstruct { struct OpenMPSectionsConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct); CharBlock source; + const OmpBeginSectionsDirective &BeginDir() const { + return std::get(t); + } + const std::optional &EndDir() const { + return std::get>(t); + } // Each of the OpenMPConstructs in the list below contains an // OpenMPSectionConstruct. This is guaranteed by the parser. // The end sections directive is optional here because it is difficult to diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 3a59c0f5f5a90..5681be664d450 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -3858,30 +3858,22 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, - const parser::OpenMPSectionsConstruct §ionsConstruct) { - const auto &beginSectionsDirective = - std::get(sectionsConstruct.t); - List clauses = makeClauses( - std::get(beginSectionsDirective.t), semaCtx); - const auto &endSectionsDirective = - std::get>( - sectionsConstruct.t); - assert(endSectionsDirective && + const parser::OpenMPSectionsConstruct &construct) { + const parser::OmpDirectiveSpecification &beginSpec{construct.BeginDir()}; + List clauses = makeClauses(beginSpec.Clauses(), semaCtx); + const auto &endSpec{construct.EndDir()}; + assert(endSpec && "Missing end section directive should have been handled in semantics"); - clauses.append(makeClauses( - std::get(endSectionsDirective->t), semaCtx)); + clauses.append(makeClauses(endSpec->Clauses(), semaCtx)); mlir::Location currentLocation = converter.getCurrentLocation(); - llvm::omp::Directive directive = - std::get(beginSectionsDirective.t).v; - const parser::CharBlock &source = - std::get(beginSectionsDirective.t).source; + const parser::OmpDirectiveName &beginName{beginSpec.DirName()}; ConstructQueue queue{ buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx, - eval, source, directive, clauses)}; + eval, beginName.source, beginName.v, clauses)}; mlir::SaveStateStack saveStateStack{ - converter.getStateStack(), sectionsConstruct}; + converter.getStateStack(), construct}; genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, queue.begin()); } diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index c6d4de108fb59..a8f2f0056fe4a 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -1862,17 +1862,21 @@ TYPE_PARSER( // #undef MakeBlockConstruct // OMP SECTIONS Directive -TYPE_PARSER(construct(first( - "SECTIONS" >> pure(llvm::omp::Directive::OMPD_sections), - "PARALLEL SECTIONS" >> pure(llvm::omp::Directive::OMPD_parallel_sections)))) +static constexpr DirectiveSet GetSectionsDirectives() { + using Directive = llvm::omp::Directive; + constexpr DirectiveSet sectionsDirectives{ + unsigned(Directive::OMPD_sections), + unsigned(Directive::OMPD_parallel_sections), + }; + return sectionsDirectives; +} // OMP BEGIN and END SECTIONS Directive -TYPE_PARSER(sourced(construct( - sourced(Parser{}), Parser{}))) -TYPE_PARSER( - startOmpLine >> sourced(construct( - sourced("END"_tok >> Parser{}), - Parser{}))) +TYPE_PARSER(construct( + OmpBeginDirectiveParser(GetSectionsDirectives()))) + +TYPE_PARSER(construct( + OmpEndDirectiveParser(GetSectionsDirectives()))) static constexpr auto sectionDir{ startOmpLine >> (predicated(OmpDirectiveNameParser{}, diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 73bbbc04f46b1..9d73bcafa0e15 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2618,18 +2618,6 @@ class UnparseVisitor { Word("!$OMP NOTHING"); Put("\n"); } - void Unparse(const OmpSectionsDirective &x) { - switch (x.v) { - case llvm::omp::Directive::OMPD_sections: - Word("SECTIONS "); - break; - case llvm::omp::Directive::OMPD_parallel_sections: - Word("PARALLEL SECTIONS "); - break; - default: - break; - } - } void Unparse(const OpenMPSectionConstruct &x) { if (auto &&dirSpec{ std::get>(x.t)}) { @@ -2641,18 +2629,16 @@ class UnparseVisitor { } Walk(std::get(x.t), ""); } + void Unparse(const OmpBeginSectionsDirective &x) { + Unparse(static_cast(x)); + } + void Unparse(const OmpEndSectionsDirective &x) { + Unparse(static_cast(x)); + } void Unparse(const OpenMPSectionsConstruct &x) { - BeginOpenMP(); - Word("!$OMP "); Walk(std::get(x.t)); - Put("\n"); - EndOpenMP(); Walk(std::get>(x.t), ""); - BeginOpenMP(); - Word("!$OMP END "); Walk(std::get>(x.t)); - Put("\n"); - EndOpenMP(); } // Clause unparsers are usually generated by tablegen in the form // CLAUSE(VALUE). Here we only want to print VALUE so a custom unparser is diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 4c7cd1734e0e7..c84591ac17552 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -596,10 +596,6 @@ template struct DirectiveSpellingVisitor { return std::get(t).DirName(); } - bool Pre(const parser::OmpSectionsDirective &x) { - checker_(x.source, x.v); - return false; - } bool Pre(const parser::OpenMPDeclarativeAllocate &x) { checker_(std::get(x.t).source, Directive::OMPD_allocate); return false; @@ -1154,34 +1150,30 @@ void OmpStructureChecker::Leave(const parser::OmpBeginDirective &) { } void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) { - const auto &beginSectionsDir{ - std::get(x.t)}; - const auto &endSectionsDir{ - std::get>(x.t)}; - const auto &beginDir{ - std::get(beginSectionsDir.t)}; - PushContextAndClauseSets(beginDir.source, beginDir.v); - - if (!endSectionsDir) { - context_.Say(beginSectionsDir.source, - "Expected OpenMP END SECTIONS directive"_err_en_US); + const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()}; + const parser::OmpDirectiveName &beginName{beginSpec.DirName()}; + const auto &endSpec{x.EndDir()}; + PushContextAndClauseSets(beginName.source, beginName.v); + + if (!endSpec) { + context_.Say( + beginName.source, "Expected OpenMP END SECTIONS directive"_err_en_US); // Following code assumes the option is present. return; } - const auto &endDir{std::get(endSectionsDir->t)}; - CheckMatching(beginDir, endDir); + CheckMatching(beginName, endSpec->DirName()); - AddEndDirectiveClauses(std::get(endSectionsDir->t)); + AddEndDirectiveClauses(endSpec->Clauses()); const auto §ionBlocks{std::get>(x.t)}; for (const parser::OpenMPConstruct &construct : sectionBlocks) { auto §ion{std::get(construct.u)}; CheckNoBranching( - std::get(section.t), beginDir.v, beginDir.source); + std::get(section.t), beginName.v, beginName.source); } HasInvalidWorksharingNesting( - beginDir.source, llvm::omp::nestedWorkshareErrSet); + beginName.source, llvm::omp::nestedWorkshareErrSet); } void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &) { @@ -1189,13 +1181,13 @@ void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &) { } void OmpStructureChecker::Enter(const parser::OmpEndSectionsDirective &x) { - const auto &dir{std::get(x.t)}; - ResetPartialContext(dir.source); - switch (dir.v) { + const parser::OmpDirectiveName &dirName{x.DirName()}; + ResetPartialContext(dirName.source); + switch (dirName.v) { // 2.7.2 end-sections -> END SECTIONS [nowait-clause] case llvm::omp::Directive::OMPD_sections: PushContextAndClauseSets( - dir.source, llvm::omp::Directive::OMPD_end_sections); + dirName.source, llvm::omp::Directive::OMPD_end_sections); break; default: // no clauses are allowed @@ -4648,12 +4640,7 @@ void OmpStructureChecker::CheckWorkshareBlockStmts( } else if (const auto *ompSectionsConstruct{ std::get_if( &ompConstruct->u)}) { - const auto &beginSectionsDir{ - std::get( - ompSectionsConstruct->t)}; - const auto &beginDir{ - std::get(beginSectionsDir.t)}; - currentDir = beginDir.v; + currentDir = ompSectionsConstruct->BeginDir().DirId(); } if (!llvm::omp::topParallelSet.test(currentDir)) { diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index abb8f6430b29b..2d1bec9968593 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -2278,14 +2278,12 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPGroupprivate &x) { } bool OmpAttributeVisitor::Pre(const parser::OpenMPSectionsConstruct &x) { - const auto &beginSectionsDir{ - std::get(x.t)}; - const auto &beginDir{ - std::get(beginSectionsDir.t)}; - switch (beginDir.v) { + const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()}; + const parser::OmpDirectiveName &beginName{beginSpec.DirName()}; + switch (beginName.v) { case llvm::omp::Directive::OMPD_parallel_sections: case llvm::omp::Directive::OMPD_sections: - PushContext(beginDir.source, beginDir.v); + PushContext(beginName.source, beginName.v); GetContext().withinConstruct = true; break; default: diff --git a/flang/test/Parser/OpenMP/sections.f90 b/flang/test/Parser/OpenMP/sections.f90 index 8ba2294fb0faa..76e6b90f05721 100644 --- a/flang/test/Parser/OpenMP/sections.f90 +++ b/flang/test/Parser/OpenMP/sections.f90 @@ -15,13 +15,15 @@ subroutine openmp_sections(x, y) !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct !PARSE-TREE: | OmpBeginSectionsDirective -!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> +!PARSE-TREE: | | Flags = None !PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct !PARSE-TREE: | | Block !PARSE-TREE: | OmpEndSectionsDirective -!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> +!PARSE-TREE: | | Flags = None !============================================================================== ! single section, without `!$omp section` @@ -35,16 +37,18 @@ subroutine openmp_sections(x, y) !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct !PARSE-TREE: | OmpBeginSectionsDirective -!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> +!PARSE-TREE: | | Flags = None !PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct !PARSE-TREE: | | Block !PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f1()' !PARSE-TREE: | | | | Call !PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f1' !PARSE-TREE: | OmpEndSectionsDirective -!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> +!PARSE-TREE: | | Flags = None !============================================================================== ! single section with `!$omp section` @@ -60,8 +64,9 @@ subroutine openmp_sections(x, y) !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct !PARSE-TREE: | OmpBeginSectionsDirective -!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> +!PARSE-TREE: | | Flags = None !PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct !PARSE-TREE: | | OmpDirectiveSpecification !PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section @@ -72,8 +77,9 @@ subroutine openmp_sections(x, y) !PARSE-TREE: | | | | Call !PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f1' !PARSE-TREE: | OmpEndSectionsDirective -!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> +!PARSE-TREE: | | Flags = None !============================================================================== ! multiple sections @@ -97,8 +103,9 @@ subroutine openmp_sections(x, y) !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct !PARSE-TREE: | OmpBeginSectionsDirective -!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> +!PARSE-TREE: | | Flags = None !PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct !PARSE-TREE: | | OmpDirectiveSpecification !PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section @@ -127,8 +134,9 @@ subroutine openmp_sections(x, y) !PARSE-TREE: | | | | Call !PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f3' !PARSE-TREE: | OmpEndSectionsDirective -!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> +!PARSE-TREE: | | Flags = None !============================================================================== ! multiple sections with clauses @@ -152,9 +160,10 @@ subroutine openmp_sections(x, y) !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct !PARSE-TREE: | OmpBeginSectionsDirective -!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> OmpClause -> Private -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | OmpClause -> Firstprivate -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'y' +!PARSE-TREE: | | Flags = None !PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct !PARSE-TREE: | | OmpDirectiveSpecification !PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section @@ -183,7 +192,8 @@ subroutine openmp_sections(x, y) !PARSE-TREE: | | | | Call !PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f3' !PARSE-TREE: | OmpEndSectionsDirective -!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> OmpClause -> Nowait +!PARSE-TREE: | | Flags = None END subroutine openmp_sections