aboutsummaryrefslogtreecommitdiff
path: root/flang/lib/Parser/openmp-parsers.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'flang/lib/Parser/openmp-parsers.cpp')
-rw-r--r--flang/lib/Parser/openmp-parsers.cpp78
1 files changed, 70 insertions, 8 deletions
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index d349d8c..1c62614 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1208,6 +1208,61 @@ TYPE_PARSER(sourced(
maybe(Parser<OmpClauseList>{}),
pure(OmpDirectiveSpecification::Flags::None))))
+static bool IsFortranBlockConstruct(const ExecutionPartConstruct &epc) {
+ // ExecutionPartConstruct -> ExecutableConstruct
+ // -> Indirection<BlockConstruct>
+ if (auto *ec{std::get_if<ExecutableConstruct>(&epc.u)}) {
+ return std::holds_alternative<common::Indirection<BlockConstruct>>(ec->u);
+ } else {
+ return false;
+ }
+}
+
+struct StrictlyStructuredBlockParser {
+ using resultType = Block;
+
+ std::optional<resultType> Parse(ParseState &state) const {
+ // Detect BLOCK construct without parsing the entire thing.
+ if (lookAhead(skipStuffBeforeStatement >> "BLOCK"_tok).Parse(state)) {
+ if (auto epc{Parser<ExecutionPartConstruct>{}.Parse(state)}) {
+ if (IsFortranBlockConstruct(*epc)) {
+ Block block;
+ block.emplace_back(std::move(*epc));
+ return std::move(block);
+ }
+ }
+ }
+ return std::nullopt;
+ }
+};
+
+struct LooselyStructuredBlockParser {
+ using resultType = Block;
+
+ std::optional<resultType> Parse(ParseState &state) const {
+ // Detect BLOCK construct without parsing the entire thing.
+ if (lookAhead(skipStuffBeforeStatement >> "BLOCK"_tok).Parse(state)) {
+ return std::nullopt;
+ }
+ Block body;
+ if (auto epc{attempt(Parser<ExecutionPartConstruct>{}).Parse(state)}) {
+ if (!IsFortranBlockConstruct(*epc)) {
+ body.emplace_back(std::move(*epc));
+ if (auto &&blk{attempt(block).Parse(state)}) {
+ for (auto &&s : *blk) {
+ body.emplace_back(std::move(s));
+ }
+ }
+ } else {
+ // Fail if the first construct is BLOCK.
+ return std::nullopt;
+ }
+ }
+ // Empty body is ok.
+ return std::move(body);
+ }
+};
+
TYPE_PARSER(sourced(construct<OmpNothingDirective>("NOTHING" >> ok)))
TYPE_PARSER(sourced(construct<OpenMPUtilityConstruct>(
@@ -1570,12 +1625,16 @@ TYPE_PARSER(
Parser<OpenMPInteropConstruct>{})) /
endOfLine)
+// Directive names (of non-block constructs) whose prefix is a name of
+// a block-associated construct. We need to exclude them from the block
+// directive parser below to avoid parsing parts of them.
+static constexpr auto StandaloneDirectiveLookahead{//
+ "TARGET ENTER DATA"_sptok || "TARGET_ENTER_DATA"_sptok || //
+ "TARGET EXIT DATA"_sptok || "TARGET_EXIT"_sptok || //
+ "TARGET UPDATE"_sptok || "TARGET_UPDATE"_sptok};
+
// Directives enclosing structured-block
-TYPE_PARSER(
- // In this context "TARGET UPDATE" can be parsed as a TARGET directive
- // followed by an UPDATE clause. This is the only combination at the
- // moment, exclude it explicitly.
- (!("TARGET UPDATE"_sptok || "TARGET_UPDATE"_sptok)) >=
+TYPE_PARSER((!StandaloneDirectiveLookahead) >=
construct<OmpBlockDirective>(first(
"MASKED" >> pure(llvm::omp::Directive::OMPD_masked),
"MASTER" >> pure(llvm::omp::Directive::OMPD_master),
@@ -1749,9 +1808,12 @@ TYPE_PARSER(sourced(
block, maybe(Parser<OmpEndAssumeDirective>{} / endOmpLine))))
// Block Construct
-TYPE_PARSER(construct<OpenMPBlockConstruct>(
- Parser<OmpBeginBlockDirective>{} / endOmpLine, block,
- Parser<OmpEndBlockDirective>{} / endOmpLine))
+TYPE_PARSER( //
+ construct<OpenMPBlockConstruct>(Parser<OmpBeginBlockDirective>{},
+ StrictlyStructuredBlockParser{},
+ maybe(Parser<OmpEndBlockDirective>{})) ||
+ construct<OpenMPBlockConstruct>(Parser<OmpBeginBlockDirective>{},
+ LooselyStructuredBlockParser{}, Parser<OmpEndBlockDirective>{}))
// OMP SECTIONS Directive
TYPE_PARSER(construct<OmpSectionsDirective>(first(