[llvm-branch-commits] [flang] [flang][OpenMP] Make all block constructs share the same structure (PR #150956)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Jul 28 07:15:33 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-parser
Author: Krzysztof Parzyszek (kparzysz)
<details>
<summary>Changes</summary>
The structure is
- OmpBeginDirective (aka OmpDirectiveSpecification)
- Block
- optional<OmpEndDirective> (aka optional<OmpDirectiveSpecification>)
The OmpBeginDirective and OmpEndDirective are effectively different names for OmpDirectiveSpecification. They exist to allow the semantic analyses to distinguish between the beginning and the ending of a block construct without maintaining additional context.
The actual changes are in the parser: parse-tree.h and openmp-parser.cpp in particular. The rest is simply changing the way the directive/clause information is accessed (typically for the simpler).
All standalone and block constructs now use OmpDirectiveSpecification to store the directive/clause information.
---
Patch is 108.91 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/150956.diff
38 Files Affected:
- (modified) flang/examples/FeatureList/FeatureList.cpp (+2-3)
- (modified) flang/include/flang/Parser/dump-parse-tree.h (+2-3)
- (modified) flang/include/flang/Parser/openmp-utils.h (+2-9)
- (modified) flang/include/flang/Parser/parse-tree.h (+43-40)
- (modified) flang/lib/Lower/OpenMP/Atomic.cpp (+1-1)
- (modified) flang/lib/Lower/OpenMP/OpenMP.cpp (+14-35)
- (modified) flang/lib/Parser/openmp-parsers.cpp (+100-92)
- (modified) flang/lib/Parser/parse-tree.cpp (+3-3)
- (modified) flang/lib/Parser/unparse.cpp (+20-80)
- (modified) flang/lib/Semantics/check-omp-atomic.cpp (+3-5)
- (modified) flang/lib/Semantics/check-omp-loop.cpp (+5-9)
- (modified) flang/lib/Semantics/check-omp-structure.cpp (+50-65)
- (modified) flang/lib/Semantics/check-omp-structure.h (+3-3)
- (modified) flang/lib/Semantics/resolve-directives.cpp (+21-13)
- (modified) flang/lib/Semantics/resolve-names.cpp (+5-7)
- (modified) flang/test/Parser/OpenMP/affinity-clause.f90 (+6-6)
- (modified) flang/test/Parser/OpenMP/allocators-unparse.f90 (+4-4)
- (modified) flang/test/Parser/OpenMP/atomic-compare.f90 (+9-9)
- (modified) flang/test/Parser/OpenMP/atomic-end.f90 (+4-4)
- (modified) flang/test/Parser/OpenMP/block-construct.f90 (+10-10)
- (modified) flang/test/Parser/OpenMP/construct-prefix-conflict.f90 (+20-20)
- (modified) flang/test/Parser/OpenMP/defaultmap-clause.f90 (+12-12)
- (modified) flang/test/Parser/OpenMP/defaultmap-unparse.f90 (+18-18)
- (modified) flang/test/Parser/OpenMP/dispatch.f90 (+4-4)
- (modified) flang/test/Parser/OpenMP/if-clause.f90 (+2-2)
- (modified) flang/test/Parser/OpenMP/in-reduction-clause.f90 (+6-6)
- (modified) flang/test/Parser/OpenMP/map-modifiers-v60.f90 (+10-10)
- (modified) flang/test/Parser/OpenMP/map-modifiers.f90 (+23-23)
- (modified) flang/test/Parser/OpenMP/masked-unparse.f90 (+6-6)
- (modified) flang/test/Parser/OpenMP/master-unparse.f90 (+4-4)
- (modified) flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 (+6-6)
- (modified) flang/test/Parser/OpenMP/proc-bind.f90 (+2-2)
- (modified) flang/test/Parser/OpenMP/scope.f90 (+4-4)
- (modified) flang/test/Parser/OpenMP/target_device_parse.f90 (+32-32)
- (modified) flang/test/Parser/OpenMP/task-reduction-clause.f90 (+2-2)
- (modified) flang/test/Parser/OpenMP/task.f90 (+1-1)
- (modified) flang/test/Semantics/OpenMP/clause-validity01.f90 (+1-2)
- (modified) flang/test/Semantics/OpenMP/symbol08.f90 (+1-2)
``````````diff
diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp
index 64b57b633feaf..0b8066e36312b 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -445,10 +445,9 @@ struct NodeVisitor {
READ_FEATURE(ObjectDecl)
READ_FEATURE(OldParameterStmt)
READ_FEATURE(OmpAlignedClause)
- READ_FEATURE(OmpBeginBlockDirective)
+ READ_FEATURE(OmpBeginDirective)
READ_FEATURE(OmpBeginLoopDirective)
READ_FEATURE(OmpBeginSectionsDirective)
- READ_FEATURE(OmpBlockDirective)
READ_FEATURE(OmpClause)
READ_FEATURE(OmpClauseList)
READ_FEATURE(OmpCriticalDirective)
@@ -472,7 +471,7 @@ struct NodeVisitor {
READ_FEATURE(OmpIteration)
READ_FEATURE(OmpIterationOffset)
READ_FEATURE(OmpIterationVector)
- READ_FEATURE(OmpEndBlockDirective)
+ READ_FEATURE(OmpEndDirective)
READ_FEATURE(OmpEndCriticalDirective)
READ_FEATURE(OmpEndLoopDirective)
READ_FEATURE(OmpEndSectionsDirective)
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index ebac54f6e29ba..b09dd32a90b98 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -534,10 +534,8 @@ class ParseTreeDumper {
NODE(parser, OmpAtClause)
NODE_ENUM(OmpAtClause, ActionTime)
NODE_ENUM(OmpSeverityClause, Severity)
- NODE(parser, OmpBeginBlockDirective)
NODE(parser, OmpBeginLoopDirective)
NODE(parser, OmpBeginSectionsDirective)
- NODE(parser, OmpBlockDirective)
static std::string GetNodeName(const llvm::omp::Directive &x) {
return llvm::Twine("llvm::omp::Directive = ",
llvm::omp::getOpenMPDirectiveName(x, llvm::omp::FallbackVersion))
@@ -584,7 +582,6 @@ class ParseTreeDumper {
NODE(parser, OmpDetachClause)
NODE(parser, OmpDoacrossClause)
NODE(parser, OmpDestroyClause)
- NODE(parser, OmpEndBlockDirective)
NODE(parser, OmpEndCriticalDirective)
NODE(parser, OmpEndLoopDirective)
NODE(parser, OmpEndSectionsDirective)
@@ -704,6 +701,8 @@ class ParseTreeDumper {
NODE(parser, OpenMPDeclarativeAssumes)
NODE(parser, OmpAssumeDirective)
NODE(parser, OmpEndAssumeDirective)
+ NODE(parser, OmpBeginDirective)
+ NODE(parser, OmpEndDirective)
NODE(parser, OpenMPAtomicConstruct)
NODE(parser, OpenMPBlockConstruct)
NODE(parser, OpenMPCancelConstruct)
diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h
index 41c04424e91c6..fa0f7656cd5d8 100644
--- a/flang/include/flang/Parser/openmp-utils.h
+++ b/flang/include/flang/Parser/openmp-utils.h
@@ -68,11 +68,6 @@ struct DirectiveNameScope {
return MakeName(x.source, llvm::omp::Directive::OMPD_nothing);
}
- static OmpDirectiveName GetOmpDirectiveName(const OmpBeginBlockDirective &x) {
- auto &dir{std::get<OmpBlockDirective>(x.t)};
- return MakeName(dir.source, dir.v);
- }
-
static OmpDirectiveName GetOmpDirectiveName(const OmpBeginLoopDirective &x) {
auto &dir{std::get<OmpLoopDirective>(x.t)};
return MakeName(dir.source, dir.v);
@@ -106,10 +101,8 @@ struct DirectiveNameScope {
return GetOmpDirectiveName(x.v);
}
} else if constexpr (TupleTrait<T>) {
- if constexpr (std::is_same_v<T, OpenMPAllocatorsConstruct> ||
- std::is_same_v<T, OpenMPAtomicConstruct> ||
- std::is_same_v<T, OpenMPDispatchConstruct>) {
- return std::get<OmpDirectiveSpecification>(x.t).DirName();
+ if constexpr (std::is_base_of_v<OmpBlockConstruct, T>) {
+ return std::get<OmpBeginDirective>(x.t).DirName();
} else if constexpr (std::is_same_v<T, OmpAssumeDirective> ||
std::is_same_v<T, OmpCriticalDirective> ||
std::is_same_v<T, OmpDeclareVariantDirective> ||
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index da0a3632b8a63..7ba5fe964f7a1 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3469,6 +3469,13 @@ WRAPPER_CLASS(PauseStmt, std::optional<StopCode>);
// --- Common definitions
+#define INHERITED_TUPLE_CLASS_BOILERPLATE(classname, basename) \
+ template <typename... Ts, typename = common::NoLvalue<Ts...>> \
+ classname(Ts &&...args) : basename(std::move(args)...) {} \
+ classname(basename &&b) : basename(std::move(b)) {} \
+ using TupleTrait = std::true_type; \
+ BOILERPLATE(classname)
+
#define INHERITED_WRAPPER_CLASS_BOILERPLATE(classname, basename) \
BOILERPLATE(classname); \
classname(decltype(basename::v) &&x) : basename(std::move(x)) {} \
@@ -4729,6 +4736,33 @@ struct OmpDirectiveSpecification {
t;
};
+// OmpBeginDirective and OmpEndDirective are needed for semantic analysis,
+// where some checks are done specifically for either the begin or the end
+// directive. The structure of both is identical, but the diffent types
+// allow to distinguish them in the type-based parse-tree visitor.
+struct OmpBeginDirective : public OmpDirectiveSpecification {
+ INHERITED_TUPLE_CLASS_BOILERPLATE(
+ OmpBeginDirective, OmpDirectiveSpecification);
+};
+
+struct OmpEndDirective : public OmpDirectiveSpecification {
+ INHERITED_TUPLE_CLASS_BOILERPLATE(OmpEndDirective, OmpDirectiveSpecification);
+};
+
+// Common base class for block-associated constructs.
+struct OmpBlockConstruct {
+ TUPLE_CLASS_BOILERPLATE(OmpBlockConstruct);
+ const OmpBeginDirective &BeginDir() const {
+ return std::get<OmpBeginDirective>(t);
+ }
+ const std::optional<OmpEndDirective> &EndDir() const {
+ return std::get<std::optional<OmpEndDirective>>(t);
+ }
+
+ CharBlock source;
+ std::tuple<OmpBeginDirective, Block, std::optional<OmpEndDirective>> t;
+};
+
struct OmpMetadirectiveDirective {
TUPLE_CLASS_BOILERPLATE(OmpMetadirectiveDirective);
std::tuple<Verbatim, OmpClauseList> t;
@@ -4833,12 +4867,6 @@ struct OpenMPSectionsConstruct {
t;
};
-// OpenMP directive beginning or ending a block
-struct OmpBlockDirective {
- WRAPPER_CLASS_BOILERPLATE(OmpBlockDirective, llvm::omp::Directive);
- CharBlock source;
-};
-
struct OmpDeclareVariantDirective {
TUPLE_CLASS_BOILERPLATE(OmpDeclareVariantDirective);
CharBlock source;
@@ -4963,12 +4991,9 @@ struct OpenMPExecutableAllocate {
// ALLOCATORS [allocate-clause...]
// block
// [END ALLOCATORS]
-struct OpenMPAllocatorsConstruct {
- TUPLE_CLASS_BOILERPLATE(OpenMPAllocatorsConstruct);
- CharBlock source;
- std::tuple<OmpDirectiveSpecification, Block,
- std::optional<OmpDirectiveSpecification>>
- t;
+struct OpenMPAllocatorsConstruct : public OmpBlockConstruct {
+ INHERITED_TUPLE_CLASS_BOILERPLATE(
+ OpenMPAllocatorsConstruct, OmpBlockConstruct);
};
// 2.17.7 Atomic construct/2.17.8 Flush construct [OpenMP 5.0]
@@ -4982,15 +5007,11 @@ struct OmpMemoryOrderClause {
CharBlock source;
};
-struct OpenMPAtomicConstruct {
+struct OpenMPAtomicConstruct : public OmpBlockConstruct {
llvm::omp::Clause GetKind() const;
bool IsCapture() const;
bool IsCompare() const;
- TUPLE_CLASS_BOILERPLATE(OpenMPAtomicConstruct);
- CharBlock source;
- std::tuple<OmpDirectiveSpecification, Block,
- std::optional<OmpDirectiveSpecification>>
- t;
+ INHERITED_TUPLE_CLASS_BOILERPLATE(OpenMPAtomicConstruct, OmpBlockConstruct);
// Information filled out during semantic checks to avoid duplication
// of analyses.
@@ -5054,12 +5075,8 @@ struct OpenMPDepobjConstruct {
// nocontext-clause |
// novariants-clause |
// nowait-clause
-struct OpenMPDispatchConstruct {
- TUPLE_CLASS_BOILERPLATE(OpenMPDispatchConstruct);
- CharBlock source;
- std::tuple<OmpDirectiveSpecification, Block,
- std::optional<OmpDirectiveSpecification>>
- t;
+struct OpenMPDispatchConstruct : public OmpBlockConstruct {
+ INHERITED_TUPLE_CLASS_BOILERPLATE(OpenMPDispatchConstruct, OmpBlockConstruct);
};
// [4.5:162-165], [5.0:242-246], [5.1:275-279], [5.2:315-316], [6.0:498-500]
@@ -5114,22 +5131,8 @@ struct OmpEndLoopDirective {
CharBlock source;
};
-struct OmpBeginBlockDirective {
- TUPLE_CLASS_BOILERPLATE(OmpBeginBlockDirective);
- std::tuple<OmpBlockDirective, OmpClauseList> t;
- CharBlock source;
-};
-
-struct OmpEndBlockDirective {
- TUPLE_CLASS_BOILERPLATE(OmpEndBlockDirective);
- std::tuple<OmpBlockDirective, OmpClauseList> t;
- CharBlock source;
-};
-
-struct OpenMPBlockConstruct {
- TUPLE_CLASS_BOILERPLATE(OpenMPBlockConstruct);
- std::tuple<OmpBeginBlockDirective, Block, std::optional<OmpEndBlockDirective>>
- t;
+struct OpenMPBlockConstruct : public OmpBlockConstruct {
+ INHERITED_TUPLE_CLASS_BOILERPLATE(OpenMPBlockConstruct, OmpBlockConstruct);
};
// OpenMP directives enclosing do loop
diff --git a/flang/lib/Lower/OpenMP/Atomic.cpp b/flang/lib/Lower/OpenMP/Atomic.cpp
index 9a233d2d8cb08..623a9370aa00d 100644
--- a/flang/lib/Lower/OpenMP/Atomic.cpp
+++ b/flang/lib/Lower/OpenMP/Atomic.cpp
@@ -699,7 +699,7 @@ void Fortran::lower::omp::lowerAtomic(
};
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
- auto &dirSpec = std::get<parser::OmpDirectiveSpecification>(construct.t);
+ const parser::OmpDirectiveSpecification &dirSpec = construct.BeginDir();
omp::List<omp::Clause> clauses = makeClauses(dirSpec.Clauses(), semaCtx);
lower::StatementContext stmtCtx;
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 6dd4b16a1fb55..68ebb66309f99 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -407,16 +407,9 @@ static void processHostEvalClauses(lower::AbstractConverter &converter,
common::visit(
common::visitors{
[&](const parser::OpenMPBlockConstruct &ompConstruct) {
- const auto &beginDirective =
- std::get<parser::OmpBeginBlockDirective>(ompConstruct.t);
- beginClauseList =
- &std::get<parser::OmpClauseList>(beginDirective.t);
- if (auto &endDirective =
- std::get<std::optional<parser::OmpEndBlockDirective>>(
- ompConstruct.t)) {
- endClauseList =
- &std::get<parser::OmpClauseList>(endDirective->t);
- }
+ beginClauseList = &ompConstruct.BeginDir().Clauses();
+ if (auto &endSpec = ompConstruct.EndDir())
+ endClauseList = &endSpec->Clauses();
},
[&](const parser::OpenMPLoopConstruct &ompConstruct) {
const auto &beginDirective =
@@ -3716,25 +3709,16 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
const parser::OpenMPBlockConstruct &blockConstruct) {
- const auto &beginBlockDirective =
- std::get<parser::OmpBeginBlockDirective>(blockConstruct.t);
- mlir::Location currentLocation =
- converter.genLocation(beginBlockDirective.source);
- const auto origDirective =
- std::get<parser::OmpBlockDirective>(beginBlockDirective.t).v;
- List<Clause> clauses = makeClauses(
- std::get<parser::OmpClauseList>(beginBlockDirective.t), semaCtx);
-
- if (const auto &endBlockDirective =
- std::get<std::optional<parser::OmpEndBlockDirective>>(
- blockConstruct.t)) {
- clauses.append(makeClauses(
- std::get<parser::OmpClauseList>(endBlockDirective->t), semaCtx));
- }
-
- assert(llvm::omp::blockConstructSet.test(origDirective) &&
+ const parser::OmpDirectiveSpecification &beginSpec =
+ blockConstruct.BeginDir();
+ List<Clause> clauses = makeClauses(beginSpec.Clauses(), semaCtx);
+ if (auto &endSpec = blockConstruct.EndDir())
+ clauses.append(makeClauses(endSpec->Clauses(), semaCtx));
+
+ llvm::omp::Directive directive = beginSpec.DirId();
+ assert(llvm::omp::blockConstructSet.test(directive) &&
"Expected block construct");
- (void)origDirective;
+ mlir::Location currentLocation = converter.genLocation(beginSpec.source);
for (const Clause &clause : clauses) {
mlir::Location clauseLocation = converter.genLocation(clause.source);
@@ -3777,13 +3761,9 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
}
}
- llvm::omp::Directive directive =
- std::get<parser::OmpBlockDirective>(beginBlockDirective.t).v;
- const parser::CharBlock &source =
- std::get<parser::OmpBlockDirective>(beginBlockDirective.t).source;
ConstructQueue queue{
buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx,
- eval, source, directive, clauses)};
+ eval, beginSpec.source, directive, clauses)};
genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue,
queue.begin());
}
@@ -4071,8 +4051,7 @@ bool Fortran::lower::isOpenMPTargetConstruct(
const parser::OpenMPConstruct &omp) {
llvm::omp::Directive dir = llvm::omp::Directive::OMPD_unknown;
if (const auto *block = std::get_if<parser::OpenMPBlockConstruct>(&omp.u)) {
- const auto &begin = std::get<parser::OmpBeginBlockDirective>(block->t);
- dir = std::get<parser::OmpBlockDirective>(begin.t).v;
+ dir = block->BeginDir().DirId();
} else if (const auto *loop =
std::get_if<parser::OpenMPLoopConstruct>(&omp.u)) {
const auto &begin = std::get<parser::OmpBeginLoopDirective>(loop->t);
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 8c780388b9cb1..c2c1921f446c7 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1371,16 +1371,41 @@ TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
TYPE_PARSER(sourced(construct<OmpBeginLoopDirective>(
sourced(Parser<OmpLoopDirective>{}), Parser<OmpClauseList>{})))
+static inline constexpr auto IsDirective(llvm::omp::Directive dir) {
+ return [dir](const OmpDirectiveName &name) -> bool { return dir == name.v; };
+}
+
+struct OmpBeginDirectiveParser {
+ using resultType = OmpDirectiveSpecification;
+
+ constexpr OmpBeginDirectiveParser(llvm::omp::Directive dir) : dir_(dir) {}
+
+ std::optional<resultType> Parse(ParseState &state) const {
+ auto &&p{predicated(Parser<OmpDirectiveName>{}, IsDirective(dir_)) >=
+ Parser<OmpDirectiveSpecification>{}};
+ return p.Parse(state);
+ }
+
+private:
+ llvm::omp::Directive dir_;
+};
+
struct OmpEndDirectiveParser {
using resultType = OmpDirectiveSpecification;
constexpr OmpEndDirectiveParser(llvm::omp::Directive dir) : dir_(dir) {}
std::optional<resultType> Parse(ParseState &state) const {
- if ((startOmpLine >> "END"_sptok).Parse(state)) {
- auto &&dirSpec{Parser<OmpDirectiveSpecification>{}.Parse(state)};
- if (dirSpec && dirSpec->DirId() == dir_) {
- return std::move(dirSpec);
+ if (startOmpLine.Parse(state)) {
+ if (auto endToken{verbatim("END"_sptok).Parse(state)}) {
+ if (auto &&dirSpec{OmpBeginDirectiveParser(dir_).Parse(state)}) {
+ // Extend the "source" on both the OmpDirectiveName and the
+ // OmpDirectiveNameSpecification.
+ CharBlock &nameSource{std::get<OmpDirectiveName>(dirSpec->t).source};
+ nameSource.ExtendToCover(endToken->source);
+ dirSpec->source.ExtendToCover(endToken->source);
+ return std::move(*dirSpec);
+ }
}
}
return std::nullopt;
@@ -1390,57 +1415,67 @@ struct OmpEndDirectiveParser {
llvm::omp::Directive dir_;
};
-struct OmpAllocatorsConstructParser {
- using resultType = OpenMPAllocatorsConstruct;
+struct OmpStatementConstructParser {
+ using resultType = OmpBlockConstruct;
+
+ constexpr OmpStatementConstructParser(llvm::omp::Directive dir) : dir_(dir) {}
std::optional<resultType> Parse(ParseState &state) const {
- auto dirSpec{Parser<OmpDirectiveSpecification>{}.Parse(state)};
- if (!dirSpec || dirSpec->DirId() != llvm::omp::Directive::OMPD_allocators) {
- return std::nullopt;
- }
+ if (auto begin{OmpBeginDirectiveParser(dir_).Parse(state)}) {
+ Block body;
+ if (auto stmt{attempt(Parser<ExecutionPartConstruct>{}).Parse(state)}) {
+ body.emplace_back(std::move(*stmt));
+ }
+ // Allow empty block. Check for this in semantics.
- // This should be an allocate-stmt. That will be checked in semantics.
- Block block;
- if (auto stmt{attempt(Parser<ExecutionPartConstruct>{}).Parse(state)}) {
- block.emplace_back(std::move(*stmt));
+ auto end{maybe(OmpEndDirectiveParser{dir_}).Parse(state)};
+ return OmpBlockConstruct{OmpBeginDirective(std::move(*begin)),
+ std::move(body),
+ llvm::transformOptional(std::move(*end),
+ [](auto &&s) { return OmpEndDirective(std::move(s)); })};
}
- // Allow empty block. Check for this in semantics.
-
- auto end{OmpEndDirectiveParser{llvm::omp::Directive::OMPD_allocators}};
- return OpenMPAllocatorsConstruct{
- std::move(*dirSpec), std::move(block), *maybe(end).Parse(state)};
+ return std::nullopt;
}
+
+private:
+ llvm::omp::Directive dir_;
};
-TYPE_PARSER(sourced( //
- construct<OpenMPAllocatorsConstruct>(
- "ALLOCATORS"_tok >= OmpAllocatorsConstructParser{})))
+struct OmpBlockConstructParser {
+ using resultType = OmpBlockConstruct;
-struct OmpDispatchConstructParser {
- using resultType = OpenMPDispatchConstruct;
+ constexpr OmpBlockConstructParser(llvm::omp::Directive dir) : dir_(dir) {}
std::optional<resultType> Parse(ParseState &state) const {
- auto dirSpec{Parser<OmpDirectiveSpecification>{}.Parse(state)};
- if (!dirSpec || dirSpec->DirId() != llvm::omp::Directive::OMPD_dispatch) {
- return std::nullopt;
- }
-
- // This should be a function call. That will be checked in semantics.
- Block block;
- if (auto stmt{attempt(Parser<ExecutionPartConstruct>{}).Parse(state)}) {
- block.emplace_back(std::move(*stmt));
+ if (auto &&begin{OmpBeginDirectiveParser(dir_).Parse(state)}) {
+ if (auto &&body{attempt(StrictlyStructuredBlockParser{}).Parse(state)}) {
+ // Try strictly-structured block with an optional end-directive
+ auto end{maybe(OmpEndDirectiveParser{dir_}).Parse(state)};
+ return OmpBlockConstruct{OmpBeginDirective(std::move(*begin)),
+ std::move(*body),
+ llvm::transformOptional(std::move(*end),
+ [](auto &&s) { return OmpEndDirective(std::move(s)); })};
+ } else if (auto &&body{
+ attempt(LooselyStructuredBlockParser{}).Parse(state)}) {
+ // Try loosely-structured block with a mandatory end-directive
+ if (auto end{OmpEndDirectiveParser{dir_}.Parse(state)}) {
+ return OmpBlockConstruct{OmpBeginDirective(std::move(*begin)),
+ std::move(*body), OmpEndDirective{std::move(*end)}};
+ }
+ }
}
- // Allow empty block. Check for this in semantics.
-
- auto end{OmpEndDirectiveParser{llvm::omp::Directive::OMPD_dispatch}};
- return OpenMPDispatchConstruct{
- std::move(*dirSpec), std::move(block), *maybe(end).Parse(state)};
+ return std::nullopt;
}
+
+private:
+ llvm::omp::Directive dir_;
};
-TYPE_PARSER(sourced( //
- construct<OpenMPDispatchConstruct>(
- "DISPATCH"_tok >= OmpDispatchConstructParser{})))
+TYPE_PARSER(sourced(construct<OpenMPAllocatorsConstruct>(
+ OmpStatementConstructParser{llvm::omp::Directive::OMPD_allocators})))
+
+TYPE_PARSER(sourced(construct<OpenMPDispatchConstruct>(
+ OmpStatementConstructParser{llvm::omp::Directive::OMPD_dispatch})))
// Parser for an arbitrary OpenMP ATOMIC construct.
//
@@ -1505,8 +1540,10 @@ struct OmpAtomicConstructParser {
}
}
recursing_ = false;
- return OpenMPAtomicConstruct{
- std::move(*dirSpec), std::move(tail.first), std::move(tail.second)};
+ return OpenMPAtomicConstruct{OmpBeginDirective(std::move(*dirSpec)),
+ std::move(tail.first),
+ llvm::transformOptional(std::move(tail.second),
+ [](auto &&s) { return OmpEndDirective(std::move(s)); })};
}
recursing_ = false;
@@ -1607,10 +1644,6 @@ TYPE_PARSER(sourced( //
predicated(OmpDirectiveName...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/150956
More information about the llvm-branch-commits
mailing list