[flang-commits] [flang] 8c18932 - [flang][OpenMP] Use OmpDirectiveSpecification in SECTIONS (#159580)
via flang-commits
flang-commits at lists.llvm.org
Fri Sep 19 08:50:27 PDT 2025
Author: Krzysztof Parzyszek
Date: 2025-09-19T10:50:23-05:00
New Revision: 8c189327e5573e597b3eead418beab6aaea72ca3
URL: https://github.com/llvm/llvm-project/commit/8c189327e5573e597b3eead418beab6aaea72ca3
DIFF: https://github.com/llvm/llvm-project/commit/8c189327e5573e597b3eead418beab6aaea72ca3.diff
LOG: [flang][OpenMP] Use OmpDirectiveSpecification in SECTIONS (#159580)
Added:
Modified:
flang/examples/FeatureList/FeatureList.cpp
flang/include/flang/Parser/dump-parse-tree.h
flang/include/flang/Parser/openmp-utils.h
flang/include/flang/Parser/parse-tree.h
flang/lib/Lower/OpenMP/OpenMP.cpp
flang/lib/Parser/openmp-parsers.cpp
flang/lib/Parser/unparse.cpp
flang/lib/Semantics/check-omp-structure.cpp
flang/lib/Semantics/resolve-directives.cpp
flang/test/Parser/OpenMP/sections.f90
Removed:
################################################################################
diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp
index cb92e30051930..569d2b2307f36 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -526,7 +526,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 61a94223aabf4..c053ff1cebb2e 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -661,7 +661,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<OmpSectionsDirective>(x.t)};
- return MakeName(dir.source, dir.v);
+ return x.DirName();
}
template <typename T>
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index ff5a8b026613f..bd0debe297916 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<OmpSectionsDirective, OmpClauseList> t;
- CharBlock source;
-};
-struct OmpEndSectionsDirective {
- TUPLE_CLASS_BOILERPLATE(OmpEndSectionsDirective);
- std::tuple<OmpSectionsDirective, OmpClauseList> 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<OmpBeginSectionsDirective>(t);
+ }
+ const std::optional<OmpEndSectionsDirective> &EndDir() const {
+ return std::get<std::optional<OmpEndSectionsDirective>>(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
diff icult 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<parser::OmpBeginSectionsDirective>(sectionsConstruct.t);
- List<Clause> clauses = makeClauses(
- std::get<parser::OmpClauseList>(beginSectionsDirective.t), semaCtx);
- const auto &endSectionsDirective =
- std::get<std::optional<parser::OmpEndSectionsDirective>>(
- sectionsConstruct.t);
- assert(endSectionsDirective &&
+ const parser::OpenMPSectionsConstruct &construct) {
+ const parser::OmpDirectiveSpecification &beginSpec{construct.BeginDir()};
+ List<Clause> 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<parser::OmpClauseList>(endSectionsDirective->t), semaCtx));
+ clauses.append(makeClauses(endSpec->Clauses(), semaCtx));
mlir::Location currentLocation = converter.getCurrentLocation();
- llvm::omp::Directive directive =
- std::get<parser::OmpSectionsDirective>(beginSectionsDirective.t).v;
- const parser::CharBlock &source =
- std::get<parser::OmpSectionsDirective>(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<SectionsConstructStackFrame> 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<OmpSectionsDirective>(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<OmpBeginSectionsDirective>(
- sourced(Parser<OmpSectionsDirective>{}), Parser<OmpClauseList>{})))
-TYPE_PARSER(
- startOmpLine >> sourced(construct<OmpEndSectionsDirective>(
- sourced("END"_tok >> Parser<OmpSectionsDirective>{}),
- Parser<OmpClauseList>{})))
+TYPE_PARSER(construct<OmpBeginSectionsDirective>(
+ OmpBeginDirectiveParser(GetSectionsDirectives())))
+
+TYPE_PARSER(construct<OmpEndSectionsDirective>(
+ 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<std::optional<OmpDirectiveSpecification>>(x.t)}) {
@@ -2641,18 +2629,16 @@ class UnparseVisitor {
}
Walk(std::get<Block>(x.t), "");
}
+ void Unparse(const OmpBeginSectionsDirective &x) {
+ Unparse(static_cast<const OmpBeginDirective &>(x));
+ }
+ void Unparse(const OmpEndSectionsDirective &x) {
+ Unparse(static_cast<const OmpEndDirective &>(x));
+ }
void Unparse(const OpenMPSectionsConstruct &x) {
- BeginOpenMP();
- Word("!$OMP ");
Walk(std::get<OmpBeginSectionsDirective>(x.t));
- Put("\n");
- EndOpenMP();
Walk(std::get<std::list<OpenMPConstruct>>(x.t), "");
- BeginOpenMP();
- Word("!$OMP END ");
Walk(std::get<std::optional<OmpEndSectionsDirective>>(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 421e9e149755c..c39daef6b0ea9 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -596,10 +596,6 @@ template <typename Checker> struct DirectiveSpellingVisitor {
return std::get<parser::OmpBeginDirective>(t).DirName();
}
- bool Pre(const parser::OmpSectionsDirective &x) {
- checker_(x.source, x.v);
- return false;
- }
bool Pre(const parser::OpenMPDeclarativeAllocate &x) {
checker_(std::get<parser::Verbatim>(x.t).source, Directive::OMPD_allocate);
return false;
@@ -1150,34 +1146,30 @@ void OmpStructureChecker::Leave(const parser::OmpBeginDirective &) {
}
void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) {
- const auto &beginSectionsDir{
- std::get<parser::OmpBeginSectionsDirective>(x.t)};
- const auto &endSectionsDir{
- std::get<std::optional<parser::OmpEndSectionsDirective>>(x.t)};
- const auto &beginDir{
- std::get<parser::OmpSectionsDirective>(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<parser::OmpSectionsDirective>(endSectionsDir->t)};
- CheckMatching<parser::OmpSectionsDirective>(beginDir, endDir);
+ CheckMatching<parser::OmpDirectiveName>(beginName, endSpec->DirName());
- AddEndDirectiveClauses(std::get<parser::OmpClauseList>(endSectionsDir->t));
+ AddEndDirectiveClauses(endSpec->Clauses());
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);
+ std::get<parser::Block>(section.t), beginName.v, beginName.source);
}
HasInvalidWorksharingNesting(
- beginDir.source, llvm::omp::nestedWorkshareErrSet);
+ beginName.source, llvm::omp::nestedWorkshareErrSet);
}
void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &) {
@@ -1185,13 +1177,13 @@ void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &) {
}
void OmpStructureChecker::Enter(const parser::OmpEndSectionsDirective &x) {
- const auto &dir{std::get<parser::OmpSectionsDirective>(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
@@ -4644,12 +4636,7 @@ void OmpStructureChecker::CheckWorkshareBlockStmts(
} else if (const auto *ompSectionsConstruct{
std::get_if<parser::OpenMPSectionsConstruct>(
&ompConstruct->u)}) {
- const auto &beginSectionsDir{
- std::get<parser::OmpBeginSectionsDirective>(
- ompSectionsConstruct->t)};
- const auto &beginDir{
- std::get<parser::OmpSectionsDirective>(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<parser::OmpBeginSectionsDirective>(x.t)};
- const auto &beginDir{
- std::get<parser::OmpSectionsDirective>(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
More information about the flang-commits
mailing list