Skip to content

Commit 8c18932

Browse files
authored
[flang][OpenMP] Use OmpDirectiveSpecification in SECTIONS (llvm#159580)
1 parent 74a0d91 commit 8c18932

File tree

10 files changed

+81
-108
lines changed

10 files changed

+81
-108
lines changed

flang/examples/FeatureList/FeatureList.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,6 @@ struct NodeVisitor {
526526
READ_FEATURE(OmpChunkModifier::Value)
527527
READ_FEATURE(OmpOrderingModifier)
528528
READ_FEATURE(OmpOrderingModifier::Value)
529-
READ_FEATURE(OmpSectionsDirective)
530529
READ_FEATURE(Only)
531530
READ_FEATURE(OpenACCAtomicConstruct)
532531
READ_FEATURE(OpenACCBlockConstruct)

flang/include/flang/Parser/dump-parse-tree.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,6 @@ class ParseTreeDumper {
661661
NODE(parser, OmpScheduleClause)
662662
NODE(OmpScheduleClause, Modifier)
663663
NODE_ENUM(OmpScheduleClause, Kind)
664-
NODE(parser, OmpSectionsDirective)
665664
NODE(parser, OmpSelfModifier)
666665
NODE_ENUM(OmpSelfModifier, Value)
667666
NODE(parser, OmpSeverityClause)

flang/include/flang/Parser/openmp-utils.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ struct DirectiveNameScope {
8080

8181
static OmpDirectiveName GetOmpDirectiveName(
8282
const OmpBeginSectionsDirective &x) {
83-
auto &dir{std::get<OmpSectionsDirective>(x.t)};
84-
return MakeName(dir.source, dir.v);
83+
return x.DirName();
8584
}
8685

8786
template <typename T>

flang/include/flang/Parser/parse-tree.h

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4879,20 +4879,13 @@ struct OpenMPAssumeConstruct : public OmpBlockConstruct {
48794879

48804880
// 2.7.2 SECTIONS
48814881
// 2.11.2 PARALLEL SECTIONS
4882-
struct OmpSectionsDirective {
4883-
WRAPPER_CLASS_BOILERPLATE(OmpSectionsDirective, llvm::omp::Directive);
4884-
CharBlock source;
4882+
struct OmpBeginSectionsDirective : public OmpBeginDirective {
4883+
INHERITED_TUPLE_CLASS_BOILERPLATE(
4884+
OmpBeginSectionsDirective, OmpBeginDirective);
48854885
};
48864886

4887-
struct OmpBeginSectionsDirective {
4888-
TUPLE_CLASS_BOILERPLATE(OmpBeginSectionsDirective);
4889-
std::tuple<OmpSectionsDirective, OmpClauseList> t;
4890-
CharBlock source;
4891-
};
4892-
struct OmpEndSectionsDirective {
4893-
TUPLE_CLASS_BOILERPLATE(OmpEndSectionsDirective);
4894-
std::tuple<OmpSectionsDirective, OmpClauseList> t;
4895-
CharBlock source;
4887+
struct OmpEndSectionsDirective : public OmpEndDirective {
4888+
INHERITED_TUPLE_CLASS_BOILERPLATE(OmpEndSectionsDirective, OmpEndDirective);
48964889
};
48974890

48984891
// [!$omp section]
@@ -4909,6 +4902,12 @@ struct OpenMPSectionConstruct {
49094902
struct OpenMPSectionsConstruct {
49104903
TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct);
49114904
CharBlock source;
4905+
const OmpBeginSectionsDirective &BeginDir() const {
4906+
return std::get<OmpBeginSectionsDirective>(t);
4907+
}
4908+
const std::optional<OmpEndSectionsDirective> &EndDir() const {
4909+
return std::get<std::optional<OmpEndSectionsDirective>>(t);
4910+
}
49124911
// Each of the OpenMPConstructs in the list below contains an
49134912
// OpenMPSectionConstruct. This is guaranteed by the parser.
49144913
// The end sections directive is optional here because it is difficult to

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3858,30 +3858,22 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
38583858
static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
38593859
semantics::SemanticsContext &semaCtx,
38603860
lower::pft::Evaluation &eval,
3861-
const parser::OpenMPSectionsConstruct &sectionsConstruct) {
3862-
const auto &beginSectionsDirective =
3863-
std::get<parser::OmpBeginSectionsDirective>(sectionsConstruct.t);
3864-
List<Clause> clauses = makeClauses(
3865-
std::get<parser::OmpClauseList>(beginSectionsDirective.t), semaCtx);
3866-
const auto &endSectionsDirective =
3867-
std::get<std::optional<parser::OmpEndSectionsDirective>>(
3868-
sectionsConstruct.t);
3869-
assert(endSectionsDirective &&
3861+
const parser::OpenMPSectionsConstruct &construct) {
3862+
const parser::OmpDirectiveSpecification &beginSpec{construct.BeginDir()};
3863+
List<Clause> clauses = makeClauses(beginSpec.Clauses(), semaCtx);
3864+
const auto &endSpec{construct.EndDir()};
3865+
assert(endSpec &&
38703866
"Missing end section directive should have been handled in semantics");
3871-
clauses.append(makeClauses(
3872-
std::get<parser::OmpClauseList>(endSectionsDirective->t), semaCtx));
3867+
clauses.append(makeClauses(endSpec->Clauses(), semaCtx));
38733868
mlir::Location currentLocation = converter.getCurrentLocation();
38743869

3875-
llvm::omp::Directive directive =
3876-
std::get<parser::OmpSectionsDirective>(beginSectionsDirective.t).v;
3877-
const parser::CharBlock &source =
3878-
std::get<parser::OmpSectionsDirective>(beginSectionsDirective.t).source;
3870+
const parser::OmpDirectiveName &beginName{beginSpec.DirName()};
38793871
ConstructQueue queue{
38803872
buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx,
3881-
eval, source, directive, clauses)};
3873+
eval, beginName.source, beginName.v, clauses)};
38823874

38833875
mlir::SaveStateStack<SectionsConstructStackFrame> saveStateStack{
3884-
converter.getStateStack(), sectionsConstruct};
3876+
converter.getStateStack(), construct};
38853877
genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue,
38863878
queue.begin());
38873879
}

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1862,17 +1862,21 @@ TYPE_PARSER( //
18621862
#undef MakeBlockConstruct
18631863

18641864
// OMP SECTIONS Directive
1865-
TYPE_PARSER(construct<OmpSectionsDirective>(first(
1866-
"SECTIONS" >> pure(llvm::omp::Directive::OMPD_sections),
1867-
"PARALLEL SECTIONS" >> pure(llvm::omp::Directive::OMPD_parallel_sections))))
1865+
static constexpr DirectiveSet GetSectionsDirectives() {
1866+
using Directive = llvm::omp::Directive;
1867+
constexpr DirectiveSet sectionsDirectives{
1868+
unsigned(Directive::OMPD_sections),
1869+
unsigned(Directive::OMPD_parallel_sections),
1870+
};
1871+
return sectionsDirectives;
1872+
}
18681873

18691874
// OMP BEGIN and END SECTIONS Directive
1870-
TYPE_PARSER(sourced(construct<OmpBeginSectionsDirective>(
1871-
sourced(Parser<OmpSectionsDirective>{}), Parser<OmpClauseList>{})))
1872-
TYPE_PARSER(
1873-
startOmpLine >> sourced(construct<OmpEndSectionsDirective>(
1874-
sourced("END"_tok >> Parser<OmpSectionsDirective>{}),
1875-
Parser<OmpClauseList>{})))
1875+
TYPE_PARSER(construct<OmpBeginSectionsDirective>(
1876+
OmpBeginDirectiveParser(GetSectionsDirectives())))
1877+
1878+
TYPE_PARSER(construct<OmpEndSectionsDirective>(
1879+
OmpEndDirectiveParser(GetSectionsDirectives())))
18761880

18771881
static constexpr auto sectionDir{
18781882
startOmpLine >> (predicated(OmpDirectiveNameParser{},

flang/lib/Parser/unparse.cpp

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2618,18 +2618,6 @@ class UnparseVisitor {
26182618
Word("!$OMP NOTHING");
26192619
Put("\n");
26202620
}
2621-
void Unparse(const OmpSectionsDirective &x) {
2622-
switch (x.v) {
2623-
case llvm::omp::Directive::OMPD_sections:
2624-
Word("SECTIONS ");
2625-
break;
2626-
case llvm::omp::Directive::OMPD_parallel_sections:
2627-
Word("PARALLEL SECTIONS ");
2628-
break;
2629-
default:
2630-
break;
2631-
}
2632-
}
26332621
void Unparse(const OpenMPSectionConstruct &x) {
26342622
if (auto &&dirSpec{
26352623
std::get<std::optional<OmpDirectiveSpecification>>(x.t)}) {
@@ -2641,18 +2629,16 @@ class UnparseVisitor {
26412629
}
26422630
Walk(std::get<Block>(x.t), "");
26432631
}
2632+
void Unparse(const OmpBeginSectionsDirective &x) {
2633+
Unparse(static_cast<const OmpBeginDirective &>(x));
2634+
}
2635+
void Unparse(const OmpEndSectionsDirective &x) {
2636+
Unparse(static_cast<const OmpEndDirective &>(x));
2637+
}
26442638
void Unparse(const OpenMPSectionsConstruct &x) {
2645-
BeginOpenMP();
2646-
Word("!$OMP ");
26472639
Walk(std::get<OmpBeginSectionsDirective>(x.t));
2648-
Put("\n");
2649-
EndOpenMP();
26502640
Walk(std::get<std::list<OpenMPConstruct>>(x.t), "");
2651-
BeginOpenMP();
2652-
Word("!$OMP END ");
26532641
Walk(std::get<std::optional<OmpEndSectionsDirective>>(x.t));
2654-
Put("\n");
2655-
EndOpenMP();
26562642
}
26572643
// Clause unparsers are usually generated by tablegen in the form
26582644
// CLAUSE(VALUE). Here we only want to print VALUE so a custom unparser is

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -596,10 +596,6 @@ template <typename Checker> struct DirectiveSpellingVisitor {
596596
return std::get<parser::OmpBeginDirective>(t).DirName();
597597
}
598598

599-
bool Pre(const parser::OmpSectionsDirective &x) {
600-
checker_(x.source, x.v);
601-
return false;
602-
}
603599
bool Pre(const parser::OpenMPDeclarativeAllocate &x) {
604600
checker_(std::get<parser::Verbatim>(x.t).source, Directive::OMPD_allocate);
605601
return false;
@@ -1150,48 +1146,44 @@ void OmpStructureChecker::Leave(const parser::OmpBeginDirective &) {
11501146
}
11511147

11521148
void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) {
1153-
const auto &beginSectionsDir{
1154-
std::get<parser::OmpBeginSectionsDirective>(x.t)};
1155-
const auto &endSectionsDir{
1156-
std::get<std::optional<parser::OmpEndSectionsDirective>>(x.t)};
1157-
const auto &beginDir{
1158-
std::get<parser::OmpSectionsDirective>(beginSectionsDir.t)};
1159-
PushContextAndClauseSets(beginDir.source, beginDir.v);
1160-
1161-
if (!endSectionsDir) {
1162-
context_.Say(beginSectionsDir.source,
1163-
"Expected OpenMP END SECTIONS directive"_err_en_US);
1149+
const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()};
1150+
const parser::OmpDirectiveName &beginName{beginSpec.DirName()};
1151+
const auto &endSpec{x.EndDir()};
1152+
PushContextAndClauseSets(beginName.source, beginName.v);
1153+
1154+
if (!endSpec) {
1155+
context_.Say(
1156+
beginName.source, "Expected OpenMP END SECTIONS directive"_err_en_US);
11641157
// Following code assumes the option is present.
11651158
return;
11661159
}
11671160

1168-
const auto &endDir{std::get<parser::OmpSectionsDirective>(endSectionsDir->t)};
1169-
CheckMatching<parser::OmpSectionsDirective>(beginDir, endDir);
1161+
CheckMatching<parser::OmpDirectiveName>(beginName, endSpec->DirName());
11701162

1171-
AddEndDirectiveClauses(std::get<parser::OmpClauseList>(endSectionsDir->t));
1163+
AddEndDirectiveClauses(endSpec->Clauses());
11721164

11731165
const auto &sectionBlocks{std::get<std::list<parser::OpenMPConstruct>>(x.t)};
11741166
for (const parser::OpenMPConstruct &construct : sectionBlocks) {
11751167
auto &section{std::get<parser::OpenMPSectionConstruct>(construct.u)};
11761168
CheckNoBranching(
1177-
std::get<parser::Block>(section.t), beginDir.v, beginDir.source);
1169+
std::get<parser::Block>(section.t), beginName.v, beginName.source);
11781170
}
11791171
HasInvalidWorksharingNesting(
1180-
beginDir.source, llvm::omp::nestedWorkshareErrSet);
1172+
beginName.source, llvm::omp::nestedWorkshareErrSet);
11811173
}
11821174

11831175
void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &) {
11841176
dirContext_.pop_back();
11851177
}
11861178

11871179
void OmpStructureChecker::Enter(const parser::OmpEndSectionsDirective &x) {
1188-
const auto &dir{std::get<parser::OmpSectionsDirective>(x.t)};
1189-
ResetPartialContext(dir.source);
1190-
switch (dir.v) {
1180+
const parser::OmpDirectiveName &dirName{x.DirName()};
1181+
ResetPartialContext(dirName.source);
1182+
switch (dirName.v) {
11911183
// 2.7.2 end-sections -> END SECTIONS [nowait-clause]
11921184
case llvm::omp::Directive::OMPD_sections:
11931185
PushContextAndClauseSets(
1194-
dir.source, llvm::omp::Directive::OMPD_end_sections);
1186+
dirName.source, llvm::omp::Directive::OMPD_end_sections);
11951187
break;
11961188
default:
11971189
// no clauses are allowed
@@ -4644,12 +4636,7 @@ void OmpStructureChecker::CheckWorkshareBlockStmts(
46444636
} else if (const auto *ompSectionsConstruct{
46454637
std::get_if<parser::OpenMPSectionsConstruct>(
46464638
&ompConstruct->u)}) {
4647-
const auto &beginSectionsDir{
4648-
std::get<parser::OmpBeginSectionsDirective>(
4649-
ompSectionsConstruct->t)};
4650-
const auto &beginDir{
4651-
std::get<parser::OmpSectionsDirective>(beginSectionsDir.t)};
4652-
currentDir = beginDir.v;
4639+
currentDir = ompSectionsConstruct->BeginDir().DirId();
46534640
}
46544641

46554642
if (!llvm::omp::topParallelSet.test(currentDir)) {

flang/lib/Semantics/resolve-directives.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2278,14 +2278,12 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPGroupprivate &x) {
22782278
}
22792279

22802280
bool OmpAttributeVisitor::Pre(const parser::OpenMPSectionsConstruct &x) {
2281-
const auto &beginSectionsDir{
2282-
std::get<parser::OmpBeginSectionsDirective>(x.t)};
2283-
const auto &beginDir{
2284-
std::get<parser::OmpSectionsDirective>(beginSectionsDir.t)};
2285-
switch (beginDir.v) {
2281+
const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()};
2282+
const parser::OmpDirectiveName &beginName{beginSpec.DirName()};
2283+
switch (beginName.v) {
22862284
case llvm::omp::Directive::OMPD_parallel_sections:
22872285
case llvm::omp::Directive::OMPD_sections:
2288-
PushContext(beginDir.source, beginDir.v);
2286+
PushContext(beginName.source, beginName.v);
22892287
GetContext().withinConstruct = true;
22902288
break;
22912289
default:

flang/test/Parser/OpenMP/sections.f90

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ subroutine openmp_sections(x, y)
1515

1616
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct
1717
!PARSE-TREE: | OmpBeginSectionsDirective
18-
!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
18+
!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections
1919
!PARSE-TREE: | | OmpClauseList ->
20+
!PARSE-TREE: | | Flags = None
2021
!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct
2122
!PARSE-TREE: | | Block
2223
!PARSE-TREE: | OmpEndSectionsDirective
23-
!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
24+
!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections
2425
!PARSE-TREE: | | OmpClauseList ->
26+
!PARSE-TREE: | | Flags = None
2527

2628
!==============================================================================
2729
! single section, without `!$omp section`
@@ -35,16 +37,18 @@ subroutine openmp_sections(x, y)
3537

3638
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct
3739
!PARSE-TREE: | OmpBeginSectionsDirective
38-
!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
40+
!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections
3941
!PARSE-TREE: | | OmpClauseList ->
42+
!PARSE-TREE: | | Flags = None
4043
!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct
4144
!PARSE-TREE: | | Block
4245
!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f1()'
4346
!PARSE-TREE: | | | | Call
4447
!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f1'
4548
!PARSE-TREE: | OmpEndSectionsDirective
46-
!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
49+
!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections
4750
!PARSE-TREE: | | OmpClauseList ->
51+
!PARSE-TREE: | | Flags = None
4852

4953
!==============================================================================
5054
! single section with `!$omp section`
@@ -60,8 +64,9 @@ subroutine openmp_sections(x, y)
6064

6165
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct
6266
!PARSE-TREE: | OmpBeginSectionsDirective
63-
!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
67+
!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections
6468
!PARSE-TREE: | | OmpClauseList ->
69+
!PARSE-TREE: | | Flags = None
6570
!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct
6671
!PARSE-TREE: | | OmpDirectiveSpecification
6772
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section
@@ -72,8 +77,9 @@ subroutine openmp_sections(x, y)
7277
!PARSE-TREE: | | | | Call
7378
!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f1'
7479
!PARSE-TREE: | OmpEndSectionsDirective
75-
!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
80+
!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections
7681
!PARSE-TREE: | | OmpClauseList ->
82+
!PARSE-TREE: | | Flags = None
7783

7884
!==============================================================================
7985
! multiple sections
@@ -97,8 +103,9 @@ subroutine openmp_sections(x, y)
97103

98104
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct
99105
!PARSE-TREE: | OmpBeginSectionsDirective
100-
!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
106+
!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections
101107
!PARSE-TREE: | | OmpClauseList ->
108+
!PARSE-TREE: | | Flags = None
102109
!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct
103110
!PARSE-TREE: | | OmpDirectiveSpecification
104111
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section
@@ -127,8 +134,9 @@ subroutine openmp_sections(x, y)
127134
!PARSE-TREE: | | | | Call
128135
!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f3'
129136
!PARSE-TREE: | OmpEndSectionsDirective
130-
!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
137+
!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections
131138
!PARSE-TREE: | | OmpClauseList ->
139+
!PARSE-TREE: | | Flags = None
132140

133141
!==============================================================================
134142
! multiple sections with clauses
@@ -152,9 +160,10 @@ subroutine openmp_sections(x, y)
152160

153161
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct
154162
!PARSE-TREE: | OmpBeginSectionsDirective
155-
!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
163+
!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections
156164
!PARSE-TREE: | | OmpClauseList -> OmpClause -> Private -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
157165
!PARSE-TREE: | | OmpClause -> Firstprivate -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'y'
166+
!PARSE-TREE: | | Flags = None
158167
!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct
159168
!PARSE-TREE: | | OmpDirectiveSpecification
160169
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section
@@ -183,7 +192,8 @@ subroutine openmp_sections(x, y)
183192
!PARSE-TREE: | | | | Call
184193
!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f3'
185194
!PARSE-TREE: | OmpEndSectionsDirective
186-
!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
195+
!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections
187196
!PARSE-TREE: | | OmpClauseList -> OmpClause -> Nowait
197+
!PARSE-TREE: | | Flags = None
188198

189199
END subroutine openmp_sections

0 commit comments

Comments
 (0)