From 66c18fa8a408d6ec0123f901566a03159d2eb593 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Sat, 26 Jul 2025 09:47:03 -0500 Subject: [PATCH 1/4] [flang][OpenMP] Make OmpDirectiveNameModifier a distrinct type It was an alias for OmpDirectiveName, which could cause confusion in parse-tree visitors: a visitor for OmpDirectiveNameModifier could be executed for an OmpDirectiveName node, leading to unexpected results. --- flang/include/flang/Parser/parse-tree.h | 12 +++++++++++- flang/lib/Parser/openmp-parsers.cpp | 5 ++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 3a28f6f9731c3..0fb66c9f683e4 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3469,6 +3469,12 @@ WRAPPER_CLASS(PauseStmt, std::optional); // --- Common definitions +#define INHERITED_WRAPPER_CLASS_BOILERPLATE(classname, basename) \ + BOILERPLATE(classname); \ + classname(decltype(basename::v) &&x) : basename(std::move(x)) {} \ + classname(basename &&base) : basename(std::move(base)) {} \ + using WrapperTrait = std::true_type + struct OmpClause; struct OmpDirectiveSpecification; @@ -3476,6 +3482,7 @@ struct OmpDirectiveName { // No boilerplates: this class should be copyable, movable, etc. constexpr OmpDirectiveName() = default; constexpr OmpDirectiveName(const OmpDirectiveName &) = default; + constexpr OmpDirectiveName(llvm::omp::Directive x) : v(x) {} // Construct from an already parsed text. Use Verbatim for this because // Verbatim's source corresponds to an actual source location. // This allows "construct(Verbatim(""))". @@ -3848,7 +3855,10 @@ struct OmpDeviceModifier { // [*] The IF clause is allowed on CANCEL in OpenMP 4.5, but only without // the directive-name-modifier. For the sake of uniformity CANCEL can be // considered a valid value in 4.5 as well. -using OmpDirectiveNameModifier = OmpDirectiveName; +struct OmpDirectiveNameModifier : public OmpDirectiveName { + INHERITED_WRAPPER_CLASS_BOILERPLATE( + OmpDirectiveNameModifier, OmpDirectiveName); +}; // Ref: [5.1:205-209], [5.2:166-168] // diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 1c626148a03ae..9abec5aef8329 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -466,6 +466,8 @@ TYPE_PARSER(construct( "ANCESTOR" >> pure(OmpDeviceModifier::Value::Ancestor) || "DEVICE_NUM" >> pure(OmpDeviceModifier::Value::Device_Num))) +TYPE_PARSER(construct(OmpDirectiveNameParser{})) + TYPE_PARSER(construct( // "PRESENT" >> pure(OmpExpectation::Value::Present))) @@ -609,7 +611,8 @@ TYPE_PARSER(sourced(construct( TYPE_PARSER(sourced( construct(Parser{}))) -TYPE_PARSER(sourced(construct(OmpDirectiveNameParser{}))) +TYPE_PARSER(sourced( + construct(Parser{}))) TYPE_PARSER(sourced( construct( From 14dc21327817f681c7b62cb54fa5ceafb6ca9788 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Sat, 26 Jul 2025 10:08:46 -0500 Subject: [PATCH 2/4] fix test --- flang/test/Examples/omp-atomic.f90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flang/test/Examples/omp-atomic.f90 b/flang/test/Examples/omp-atomic.f90 index 934f84f132484..5695b621e4bff 100644 --- a/flang/test/Examples/omp-atomic.f90 +++ b/flang/test/Examples/omp-atomic.f90 @@ -31,13 +31,13 @@ ! CHECK-NEXT: - clause: read ! CHECK-NEXT: details: '' ! CHECK-NEXT: - clause: seq_cst -! CHECK-NEXT: details: 'name_modifier=atomic;' +! CHECK-NEXT: details: '' ! CHECK-NEXT:- file: '{{[^"]*}}omp-atomic.f90' ! CHECK-NEXT: line: 12 ! CHECK-NEXT: construct: atomic ! CHECK-NEXT: clauses: ! CHECK-NEXT: - clause: seq_cst -! CHECK-NEXT: details: 'name_modifier=atomic;' +! CHECK-NEXT: details: '' ! CHECK-NEXT: - clause: write ! CHECK-NEXT: details: '' ! CHECK-NEXT:- file: '{{[^"]*}}omp-atomic.f90' @@ -45,7 +45,7 @@ ! CHECK-NEXT: construct: atomic ! CHECK-NEXT: clauses: ! CHECK-NEXT: - clause: capture -! CHECK-NEXT: details: 'name_modifier=atomic;name_modifier=atomic;' +! CHECK-NEXT: details: '' ! CHECK-NEXT: - clause: seq_cst ! CHECK-NEXT: details: '' ! CHECK-NEXT:- file: '{{[^"]*}}omp-atomic.f90' From 4f48c1cfef2a5e75055aaaa6a1a2bace5ae0c871 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Fri, 25 Jul 2025 13:30:31 -0500 Subject: [PATCH 3/4] [flang][OpenMP] Store directive information in OpenMPSectionConstruct The OpenMPSectionConstruct corresponds to `!$omp section` directive, but there is nothing in the AST node that stores the directive information. Even though the only possibility (at the moment) is "section" without any clauses, for improved generality it is helpful to have that information anyway. --- flang/examples/FeatureList/FeatureList.cpp | 1 - .../FlangOmpReport/FlangOmpReportVisitor.cpp | 57 +------ flang/include/flang/Parser/dump-parse-tree.h | 1 - flang/include/flang/Parser/openmp-utils.h | 8 + flang/include/flang/Parser/parse-tree.h | 13 +- flang/lib/Lower/OpenMP/OpenMP.cpp | 4 +- flang/lib/Parser/openmp-parsers.cpp | 54 +++++-- flang/lib/Parser/unparse.cpp | 14 +- flang/lib/Semantics/check-omp-structure.cpp | 9 +- flang/test/Examples/omp-sections.f90 | 4 +- flang/test/Parser/OpenMP/sections.f90 | 144 +++++++++++++----- 11 files changed, 183 insertions(+), 126 deletions(-) diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp index e9aeed18ab0b7..64b57b633feaf 100644 --- a/flang/examples/FeatureList/FeatureList.cpp +++ b/flang/examples/FeatureList/FeatureList.cpp @@ -529,7 +529,6 @@ struct NodeVisitor { READ_FEATURE(OmpChunkModifier::Value) READ_FEATURE(OmpOrderingModifier) READ_FEATURE(OmpOrderingModifier::Value) - READ_FEATURE(OmpSectionBlocks) READ_FEATURE(OmpSectionsDirective) READ_FEATURE(Only) READ_FEATURE(OpenACCAtomicConstruct) diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp index feb7b4eced9e9..5c64870b74be2 100644 --- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp +++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "FlangOmpReportVisitor.h" +#include "flang/Parser/openmp-utils.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Frontend/OpenMP/OMP.h" @@ -118,60 +119,8 @@ std::string OpenMPCounterVisitor::getName(const OpenMPDeclarativeConstruct &c) { c.u); } std::string OpenMPCounterVisitor::getName(const OpenMPConstruct &c) { - return std::visit( - Fortran::common::visitors{ - [&](const OpenMPStandaloneConstruct &c) -> std::string { - return common::visit( - common::visitors{ - [&](const OmpMetadirectiveDirective &d) { - return normalize_construct_name(d.source.ToString()); - }, - [&](auto &&d) { - const CharBlock &source{ - std::get(d.v.t).source}; - return normalize_construct_name(source.ToString()); - }, - }, - c.u); - }, - [&](const OpenMPExecutableAllocate &c) -> std::string { - const CharBlock &source{std::get<0>(c.t).source}; - return normalize_construct_name(source.ToString()); - }, - [&](const OpenMPDeclarativeAllocate &c) -> std::string { - const CharBlock &source{std::get<0>(c.t).source}; - return normalize_construct_name(source.ToString()); - }, - [&](const OpenMPAssumeConstruct &c) -> std::string { - const CharBlock &source{std::get<0>(c.t).source}; - return normalize_construct_name(source.ToString()); - }, - [&](const OpenMPAllocatorsConstruct &c) -> std::string { - const CharBlock &source{std::get<0>(c.t).source}; - return normalize_construct_name(source.ToString()); - }, - [&](const OpenMPAtomicConstruct &c) -> std::string { - auto &dirSpec = std::get(c.t); - auto &dirName = std::get(dirSpec.t); - return normalize_construct_name(dirName.source.ToString()); - }, - [&](const OpenMPUtilityConstruct &c) -> std::string { - const CharBlock &source{c.source}; - return normalize_construct_name(source.ToString()); - }, - [&](const OpenMPSectionConstruct &c) -> std::string { - return "section"; - }, - // OpenMPSectionsConstruct, OpenMPLoopConstruct, - // OpenMPBlockConstruct, OpenMPCriticalConstruct Get the source from - // the directive field of the begin directive or from the verbatim - // field of the begin directive in Critical - [&](const auto &c) -> std::string { - const CharBlock &source{std::get<0>(std::get<0>(c.t).t).source}; - return normalize_construct_name(source.ToString()); - }, - }, - c.u); + return normalize_construct_name( + omp::GetOmpDirectiveName(c).source.ToString()); } bool OpenMPCounterVisitor::Pre(const OpenMPDeclarativeConstruct &c) { diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 23e35d106c077..ebac54f6e29ba 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -681,7 +681,6 @@ class ParseTreeDumper { NODE_ENUM(OmpChunkModifier, Value) NODE(parser, OmpOrderingModifier) NODE_ENUM(OmpOrderingModifier, Value) - NODE(parser, OmpSectionBlocks) NODE(parser, OmpSectionsDirective) NODE(parser, OmpToClause) NODE(OmpToClause, Modifier) diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h index 579ea7d74957f..41c04424e91c6 100644 --- a/flang/include/flang/Parser/openmp-utils.h +++ b/flang/include/flang/Parser/openmp-utils.h @@ -78,6 +78,14 @@ struct DirectiveNameScope { return MakeName(dir.source, dir.v); } + static OmpDirectiveName GetOmpDirectiveName(const OpenMPSectionConstruct &x) { + if (auto &spec{std::get>(x.t)}) { + return spec->DirName(); + } else { + return MakeName({}, llvm::omp::Directive::OMPD_section); + } + } + static OmpDirectiveName GetOmpDirectiveName( const OmpBeginSectionsDirective &x) { auto &dir{std::get(x.t)}; diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 0fb66c9f683e4..da0a3632b8a63 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -4818,18 +4818,17 @@ struct OmpEndSectionsDirective { // structured-block] // ... struct OpenMPSectionConstruct { - WRAPPER_CLASS_BOILERPLATE(OpenMPSectionConstruct, Block); + TUPLE_CLASS_BOILERPLATE(OpenMPSectionConstruct); + std::tuple, Block> t; CharBlock source; }; -// `OmpSectionBlocks` is a list of section constructs. The parser guarentees -// that the `OpenMPConstruct` here always encapsulates an -// `OpenMPSectionConstruct` and not any other OpenMP construct. -WRAPPER_CLASS(OmpSectionBlocks, std::list); - struct OpenMPSectionsConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct); - std::tuple, OmpEndSectionsDirective> t; }; diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 12089d6caa5fe..6dd4b16a1fb55 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -2329,7 +2329,7 @@ genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable, assert(sectionsConstruct && "Missing additional parsing information"); const auto §ionBlocks = - std::get(sectionsConstruct->t); + std::get>(sectionsConstruct->t); mlir::omp::SectionsOperands clauseOps; llvm::SmallVector reductionSyms; genSectionsClauses(converter, semaCtx, item->clauses, loc, clauseOps, @@ -2382,7 +2382,7 @@ genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable, // because we need to run genReductionVars on each omp.section so that the // reduction variable gets mapped to the private version for (auto [construct, nestedEval] : - llvm::zip(sectionBlocks.v, eval.getNestedEvaluations())) { + llvm::zip(sectionBlocks, eval.getNestedEvaluations())) { const auto *sectionConstruct = std::get_if(&construct.u); if (!sectionConstruct) { diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 9abec5aef8329..8c780388b9cb1 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -34,6 +34,39 @@ namespace Fortran::parser { constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok; constexpr auto endOmpLine = space >> endOfLine; +// Given a parser for a single element, and a parser for a list of elements +// of the same type, create a parser that constructs the entire list by having +// the single element be the head of the list, and the rest be the tail. +template struct ConsParser { + static_assert(std::is_same_v, + typename ParserT::resultType>); + + using resultType = typename ParserT::resultType; + constexpr ConsParser(ParserH h, ParserT t) : head_(h), tail_(t) {} + + std::optional Parse(ParseState &state) const { + if (auto &&first{head_.Parse(state)}) { + if (auto rest{tail_.Parse(state)}) { + rest->push_front(std::move(*first)); + return std::move(*rest); + } + } + return std::nullopt; + } + +private: + const ParserH head_; + const ParserT tail_; +}; + +template , ValueT>>> +constexpr auto cons(ParserH head, ParserT tail) { + return ConsParser(head, tail); +} + // Given a parser P for a wrapper class, invoke P, and if it succeeds return // the wrapped object. template struct UnwrapParser { @@ -1831,19 +1864,20 @@ TYPE_PARSER( sourced("END"_tok >> Parser{}), Parser{}))) -// OMP SECTION-BLOCK - -TYPE_PARSER(construct(block)) - -TYPE_PARSER(maybe(startOmpLine >> "SECTION"_tok / endOmpLine) >> - construct(nonemptySeparated( - construct(sourced(Parser{})), - startOmpLine >> "SECTION"_tok / endOmpLine))) +static constexpr auto sectionDir{ + startOmpLine >> (predicated(OmpDirectiveNameParser{}, + IsDirective(llvm::omp::Directive::OMPD_section)) >= + Parser{})}; // OMP SECTIONS (OpenMP 5.0 - 2.8.1), PARALLEL SECTIONS (OpenMP 5.0 - 2.13.3) -TYPE_PARSER(construct( +TYPE_PARSER(sourced(construct( Parser{} / endOmpLine, - Parser{}, Parser{} / endOmpLine)) + cons( // + construct(sourced( + construct(maybe(sectionDir), block))), + many(construct( + sourced(construct(sectionDir, block))))), + Parser{} / endOmpLine))) static bool IsExecutionPart(const OmpDirectiveName &name) { return name.IsExecutionPart(); diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index fc15d46a8c727..1d4d53de1491d 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2801,16 +2801,16 @@ class UnparseVisitor { break; } } - void Unparse(const OmpSectionBlocks &x) { - for (const auto &y : x.v) { + void Unparse(const OpenMPSectionConstruct &x) { + if (auto &&dirSpec{ + std::get>(x.t)}) { BeginOpenMP(); - Word("!$OMP SECTION"); + Word("!$OMP "); + Walk(*dirSpec); Put("\n"); EndOpenMP(); - // y.u is an OpenMPSectionConstruct - // (y.u).v is Block - Walk(std::get(y.u).v, ""); } + Walk(std::get(x.t), ""); } void Unparse(const OpenMPSectionsConstruct &x) { BeginOpenMP(); @@ -2818,7 +2818,7 @@ class UnparseVisitor { Walk(std::get(x.t)); Put("\n"); EndOpenMP(); - Walk(std::get(x.t)); + Walk(std::get>(x.t), ""); BeginOpenMP(); Word("!$OMP END "); Walk(std::get(x.t)); diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index d214d222e7c90..c191ad8d088d3 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -1057,10 +1057,11 @@ void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) { PushContextAndClauseSets(beginDir.source, beginDir.v); AddEndDirectiveClauses(std::get(endSectionsDir.t)); - const auto §ionBlocks{std::get(x.t)}; - for (const parser::OpenMPConstruct &block : sectionBlocks.v) { - CheckNoBranching(std::get(block.u).v, - beginDir.v, beginDir.source); + 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); } HasInvalidWorksharingNesting( beginDir.source, llvm::omp::nestedWorkshareErrSet); diff --git a/flang/test/Examples/omp-sections.f90 b/flang/test/Examples/omp-sections.f90 index 41e6e8fd9e5ab..a6d28065c8001 100644 --- a/flang/test/Examples/omp-sections.f90 +++ b/flang/test/Examples/omp-sections.f90 @@ -13,11 +13,11 @@ subroutine omp_sections() end subroutine omp_sections !CHECK: - file: {{.*}} -!CHECK: line: 9 +!CHECK: line: 8 !CHECK: construct: section !CHECK: clauses: [] !CHECK: - file: {{.*}} -!CHECK: line: 11 +!CHECK: line: 10 !CHECK: construct: section !CHECK: clauses: [] !CHECK: - file: {{.*}} diff --git a/flang/test/Parser/OpenMP/sections.f90 b/flang/test/Parser/OpenMP/sections.f90 index 3752cef624329..8ba2294fb0faa 100644 --- a/flang/test/Parser/OpenMP/sections.f90 +++ b/flang/test/Parser/OpenMP/sections.f90 @@ -10,32 +10,41 @@ subroutine openmp_sections(x, y) !============================================================================== !CHECK: !$omp sections !$omp sections - !CHECK: !$omp section !CHECK: !$omp end sections !$omp end sections -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionsConstruct -!PARSE-TREE: OmpBeginSectionsDirective -!PARSE-TREE-NOT: ExecutionPartConstruct -!PARSE-TREE: OmpEndSectionsDirective +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct +!PARSE-TREE: | OmpBeginSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> +!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | Block +!PARSE-TREE: | OmpEndSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> !============================================================================== ! single section, without `!$omp section` !============================================================================== !CHECK: !$omp sections !$omp sections - !CHECK: !$omp section !CHECK: CALL call F1() !CHECK: !$omp end sections !$omp end sections -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionsConstruct -!PARSE-TREE: OmpBeginSectionsDirective -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block -!PARSE-TREE: CallStmt -!PARSE-TREE-NOT: ExecutionPartConstruct -!PARSE-TREE: OmpEndSectionsDirective +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct +!PARSE-TREE: | OmpBeginSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> +!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: | | OmpClauseList -> !============================================================================== ! single section with `!$omp section` @@ -49,12 +58,22 @@ subroutine openmp_sections(x, y) !CHECK: !$omp end sections !$omp end sections -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionsConstruct -!PARSE-TREE: OmpBeginSectionsDirective -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block -!PARSE-TREE: CallStmt -!PARSE-TREE-NOT: ExecutionPartConstruct -!PARSE-TREE: OmpEndSectionsDirective +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct +!PARSE-TREE: | OmpBeginSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> +!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section +!PARSE-TREE: | | | OmpClauseList -> +!PARSE-TREE: | | | Flags = None +!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: | | OmpClauseList -> !============================================================================== ! multiple sections @@ -76,16 +95,40 @@ subroutine openmp_sections(x, y) !CHECK: !$omp end sections !$omp end sections -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionsConstruct -!PARSE-TREE: OmpBeginSectionsDirective -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block -!PARSE-TREE: CallStmt -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block -!PARSE-TREE: CallStmt -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block -!PARSE-TREE: CallStmt -!PARSE-TREE-NOT: ExecutionPartConstruct -!PARSE-TREE: OmpEndSectionsDirective +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct +!PARSE-TREE: | OmpBeginSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> +!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section +!PARSE-TREE: | | | OmpClauseList -> +!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | Block +!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f1()' +!PARSE-TREE: | | | | Call +!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f1' +!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section +!PARSE-TREE: | | | OmpClauseList -> +!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | Block +!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f2()' +!PARSE-TREE: | | | | Call +!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f2' +!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section +!PARSE-TREE: | | | OmpClauseList -> +!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | Block +!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f3()' +!PARSE-TREE: | | | | Call +!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f3' +!PARSE-TREE: | OmpEndSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> !============================================================================== ! multiple sections with clauses @@ -107,15 +150,40 @@ subroutine openmp_sections(x, y) !CHECK: !$omp end sections NOWAIT !$omp end sections NOWAIT -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionsConstruct -!PARSE-TREE: OmpBeginSectionsDirective -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block -!PARSE-TREE: CallStmt -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block -!PARSE-TREE: CallStmt -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block -!PARSE-TREE: CallStmt -!PARSE-TREE-NOT: ExecutionPartConstruct -!PARSE-TREE: OmpEndSectionsDirective +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct +!PARSE-TREE: | OmpBeginSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> 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: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section +!PARSE-TREE: | | | OmpClauseList -> +!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | Block +!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f1()' +!PARSE-TREE: | | | | Call +!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f1' +!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section +!PARSE-TREE: | | | OmpClauseList -> +!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | Block +!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f2()' +!PARSE-TREE: | | | | Call +!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f2' +!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section +!PARSE-TREE: | | | OmpClauseList -> +!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | Block +!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f3()' +!PARSE-TREE: | | | | Call +!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f3' +!PARSE-TREE: | OmpEndSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> OmpClause -> Nowait END subroutine openmp_sections From 0d64559614272cdf5bfa021d7120a273567f1e2d Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 28 Jul 2025 08:58:06 -0500 Subject: [PATCH 4/4] [flang][OpenMP] Use GetOmpDirectiveName to find directive source location --- .../lib/Lower/OpenMP/DataSharingProcessor.cpp | 52 +++++-------------- 1 file changed, 13 insertions(+), 39 deletions(-) diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp index 2ac4d9548b65b..2c0cbb2b6168f 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp @@ -389,42 +389,16 @@ void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) { } } -static const parser::CharBlock * -getSource(const semantics::SemanticsContext &semaCtx, - const lower::pft::Evaluation &eval) { - const parser::CharBlock *source = nullptr; - - auto ompConsVisit = [&](const parser::OpenMPConstruct &x) { - std::visit( - common::visitors{ - [&](const parser::OpenMPSectionsConstruct &x) { - source = &std::get<0>(x.t).source; - }, - [&](const parser::OpenMPLoopConstruct &x) { - source = &std::get<0>(x.t).source; - }, - [&](const parser::OpenMPBlockConstruct &x) { - source = &std::get<0>(x.t).source; - }, - [&](const parser::OpenMPCriticalConstruct &x) { - source = &std::get<0>(x.t).source; - }, - [&](const parser::OpenMPAtomicConstruct &x) { - source = &std::get(x.t).source; - }, - [&](const auto &x) { source = &x.source; }, - }, - x.u); - }; - - eval.visit(common::visitors{ - [&](const parser::OpenMPConstruct &x) { ompConsVisit(x); }, - [&](const parser::OpenMPDeclarativeConstruct &x) { source = &x.source; }, - [&](const parser::OmpEndLoopDirective &x) { source = &x.source; }, - [&](const auto &x) {}, +static parser::CharBlock getSource(const semantics::SemanticsContext &semaCtx, + const lower::pft::Evaluation &eval) { + return eval.visit(common::visitors{ + [&](const parser::OpenMPConstruct &x) { + return parser::omp::GetOmpDirectiveName(x).source; + }, + [&](const parser::OpenMPDeclarativeConstruct &x) { return x.source; }, + [&](const parser::OmpEndLoopDirective &x) { return x.source; }, + [&](const auto &x) { return parser::CharBlock{}; }, }); - - return source; } static void collectPrivatizingConstructs( @@ -518,11 +492,11 @@ void DataSharingProcessor::collectSymbols( for (const semantics::Scope &child : scope->children()) collectScopes(&child); }; - const parser::CharBlock *source = - clauses.empty() ? getSource(semaCtx, eval) : &clauses.front().source; + parser::CharBlock source = + clauses.empty() ? getSource(semaCtx, eval) : clauses.front().source; const semantics::Scope *curScope = nullptr; - if (source && !source->empty()) { - curScope = &semaCtx.FindScope(*source); + if (!source.empty()) { + curScope = &semaCtx.FindScope(source); collectScopes(curScope); } // Collect all symbols referenced in the evaluation being processed,