[flang-commits] [flang] [flang][OpenMP] Use GetOmpDirectiveName to find directive source loca… (PR #150955)
Krzysztof Parzyszek via flang-commits
flang-commits at lists.llvm.org
Thu Jul 31 05:52:12 PDT 2025
https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/150955
>From 66c18fa8a408d6ec0123f901566a03159d2eb593 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
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<StopCode>);
// --- 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<OmpDirectiveName>(Verbatim("<name>"))".
@@ -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<OmpDeviceModifier>(
"ANCESTOR" >> pure(OmpDeviceModifier::Value::Ancestor) ||
"DEVICE_NUM" >> pure(OmpDeviceModifier::Value::Device_Num)))
+TYPE_PARSER(construct<OmpDirectiveNameModifier>(OmpDirectiveNameParser{}))
+
TYPE_PARSER(construct<OmpExpectation>( //
"PRESENT" >> pure(OmpExpectation::Value::Present)))
@@ -609,7 +611,8 @@ TYPE_PARSER(sourced(construct<OmpFromClause::Modifier>(
TYPE_PARSER(sourced(
construct<OmpGrainsizeClause::Modifier>(Parser<OmpPrescriptiveness>{})))
-TYPE_PARSER(sourced(construct<OmpIfClause::Modifier>(OmpDirectiveNameParser{})))
+TYPE_PARSER(sourced(
+ construct<OmpIfClause::Modifier>(Parser<OmpDirectiveNameModifier>{})))
TYPE_PARSER(sourced(
construct<OmpInitClause::Modifier>(
>From 14dc21327817f681c7b62cb54fa5ceafb6ca9788 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
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 <Krzysztof.Parzyszek at amd.com>
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<OmpDirectiveName>(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<OmpDirectiveSpecification>(c.t);
- auto &dirName = std::get<OmpDirectiveName>(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<std::optional<OmpDirectiveSpecification>>(x.t)}) {
+ return spec->DirName();
+ } else {
+ return MakeName({}, llvm::omp::Directive::OMPD_section);
+ }
+ }
+
static OmpDirectiveName GetOmpDirectiveName(
const OmpBeginSectionsDirective &x) {
auto &dir{std::get<OmpSectionsDirective>(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<std::optional<OmpDirectiveSpecification>, 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<OpenMPConstruct>);
-
struct OpenMPSectionsConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct);
- std::tuple<OmpBeginSectionsDirective, OmpSectionBlocks,
+ CharBlock source;
+ // Each of the OpenMPConstructs in the list below contains an
+ // OpenMPSectionConstruct. This is guaranteed by the parser.
+ std::tuple<OmpBeginSectionsDirective, std::list<OpenMPConstruct>,
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<parser::OmpSectionBlocks>(sectionsConstruct->t);
+ std::get<std::list<parser::OpenMPConstruct>>(sectionsConstruct->t);
mlir::omp::SectionsOperands clauseOps;
llvm::SmallVector<const semantics::Symbol *> 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<parser::OpenMPSectionConstruct>(&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 <typename ParserH, typename ParserT> struct ConsParser {
+ static_assert(std::is_same_v<std::list<typename ParserH::resultType>,
+ typename ParserT::resultType>);
+
+ using resultType = typename ParserT::resultType;
+ constexpr ConsParser(ParserH h, ParserT t) : head_(h), tail_(t) {}
+
+ std::optional<resultType> 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 <typename ParserH, typename ParserT,
+ typename ValueH = typename ParserH::resultType,
+ typename ValueT = typename ParserT::resultType,
+ typename = std::enable_if_t<std::is_same_v<std::list<ValueH>, ValueT>>>
+constexpr auto cons(ParserH head, ParserT tail) {
+ return ConsParser<ParserH, ParserT>(head, tail);
+}
+
// Given a parser P for a wrapper class, invoke P, and if it succeeds return
// the wrapped object.
template <typename Parser> struct UnwrapParser {
@@ -1831,19 +1864,20 @@ TYPE_PARSER(
sourced("END"_tok >> Parser<OmpSectionsDirective>{}),
Parser<OmpClauseList>{})))
-// OMP SECTION-BLOCK
-
-TYPE_PARSER(construct<OpenMPSectionConstruct>(block))
-
-TYPE_PARSER(maybe(startOmpLine >> "SECTION"_tok / endOmpLine) >>
- construct<OmpSectionBlocks>(nonemptySeparated(
- construct<OpenMPConstruct>(sourced(Parser<OpenMPSectionConstruct>{})),
- startOmpLine >> "SECTION"_tok / endOmpLine)))
+static constexpr auto sectionDir{
+ startOmpLine >> (predicated(OmpDirectiveNameParser{},
+ IsDirective(llvm::omp::Directive::OMPD_section)) >=
+ Parser<OmpDirectiveSpecification>{})};
// OMP SECTIONS (OpenMP 5.0 - 2.8.1), PARALLEL SECTIONS (OpenMP 5.0 - 2.13.3)
-TYPE_PARSER(construct<OpenMPSectionsConstruct>(
+TYPE_PARSER(sourced(construct<OpenMPSectionsConstruct>(
Parser<OmpBeginSectionsDirective>{} / endOmpLine,
- Parser<OmpSectionBlocks>{}, Parser<OmpEndSectionsDirective>{} / endOmpLine))
+ cons( //
+ construct<OpenMPConstruct>(sourced(
+ construct<OpenMPSectionConstruct>(maybe(sectionDir), block))),
+ many(construct<OpenMPConstruct>(
+ sourced(construct<OpenMPSectionConstruct>(sectionDir, block))))),
+ Parser<OmpEndSectionsDirective>{} / 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<std::optional<OmpDirectiveSpecification>>(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<OpenMPSectionConstruct>(y.u).v, "");
}
+ Walk(std::get<Block>(x.t), "");
}
void Unparse(const OpenMPSectionsConstruct &x) {
BeginOpenMP();
@@ -2818,7 +2818,7 @@ class UnparseVisitor {
Walk(std::get<OmpBeginSectionsDirective>(x.t));
Put("\n");
EndOpenMP();
- Walk(std::get<OmpSectionBlocks>(x.t));
+ Walk(std::get<std::list<OpenMPConstruct>>(x.t), "");
BeginOpenMP();
Word("!$OMP END ");
Walk(std::get<OmpEndSectionsDirective>(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<parser::OmpClauseList>(endSectionsDir.t));
- const auto §ionBlocks{std::get<parser::OmpSectionBlocks>(x.t)};
- for (const parser::OpenMPConstruct &block : sectionBlocks.v) {
- CheckNoBranching(std::get<parser::OpenMPSectionConstruct>(block.u).v,
- beginDir.v, beginDir.source);
+ const auto §ionBlocks{std::get<std::list<parser::OpenMPConstruct>>(x.t)};
+ for (const parser::OpenMPConstruct &construct : sectionBlocks) {
+ auto §ion{std::get<parser::OpenMPSectionConstruct>(construct.u)};
+ CheckNoBranching(
+ std::get<parser::Block>(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 <Krzysztof.Parzyszek at amd.com>
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<parser::OmpDirectiveSpecification>(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,
More information about the flang-commits
mailing list