@@ -1602,6 +1602,14 @@ static inline constexpr auto IsMemberOf(const DirectiveSet &dirs) {
16021602 };
16031603}
16041604
1605+ constexpr auto validEPC{//
1606+ predicated(executionPartConstruct, [](auto &epc) {
1607+ return !Unwrap<OpenMPMisplacedEndDirective>(epc) &&
1608+ !Unwrap<OpenMPMisplacedEndDirective>(epc);
1609+ })};
1610+
1611+ constexpr auto validBlock{many(validEPC)};
1612+
16051613TYPE_PARSER(sourced(construct<OmpDirectiveName>(OmpDirectiveNameParser{})))
16061614
16071615OmpDirectiveSpecification static makeFlushFromOldSyntax(Verbatim &&text,
@@ -1659,7 +1667,7 @@ struct StrictlyStructuredBlockParser {
16591667 std::optional<resultType> Parse(ParseState &state) const {
16601668 // Detect BLOCK construct without parsing the entire thing.
16611669 if (lookAhead(skipStuffBeforeStatement >> "BLOCK"_tok).Parse(state)) {
1662- if (auto epc{Parser<ExecutionPartConstruct>{} .Parse(state)}) {
1670+ if (auto && epc{executionPartConstruct .Parse(state)}) {
16631671 if (GetFortranBlockConstruct(*epc) != nullptr) {
16641672 Block body;
16651673 body.emplace_back(std::move(*epc));
@@ -1679,7 +1687,7 @@ struct LooselyStructuredBlockParser {
16791687 if (lookAhead(skipStuffBeforeStatement >> "BLOCK"_tok).Parse(state)) {
16801688 return std::nullopt;
16811689 }
1682- if (auto &&body{block .Parse(state)}) {
1690+ if (auto &&body{validBlock .Parse(state)}) {
16831691 // Empty body is ok.
16841692 return std::move(body);
16851693 }
@@ -1718,7 +1726,7 @@ struct NonBlockDoConstructParser {
17181726
17191727 if (auto &&nbd{nonBlockDo.Parse(state)}) {
17201728 processEpc(std::move(*nbd));
1721- while (auto &&epc{attempt(executionPartConstruct ).Parse(state)}) {
1729+ while (auto &&epc{attempt(validEPC ).Parse(state)}) {
17221730 processEpc(std::move(*epc));
17231731 if (labels.empty()) {
17241732 break;
@@ -1840,7 +1848,7 @@ struct OmpStatementConstructParser {
18401848 std::optional<resultType> Parse(ParseState &state) const {
18411849 if (auto begin{OmpBeginDirectiveParser(dir_).Parse(state)}) {
18421850 Block body;
1843- if (auto stmt{attempt(Parser<ExecutionPartConstruct>{} ).Parse(state)}) {
1851+ if (auto stmt{attempt(validEPC ).Parse(state)}) {
18441852 body.emplace_back(std::move(*stmt));
18451853 }
18461854 // Allow empty block. Check for this in semantics.
@@ -1924,7 +1932,7 @@ struct OmpLoopConstructParser {
19241932 }
19251933 } else if (assoc == llvm::omp::Association::LoopSeq) {
19261934 // Parse loop sequence as a block.
1927- if (auto &&body{block .Parse(state)}) {
1935+ if (auto &&body{validBlock .Parse(state)}) {
19281936 auto end{maybe(OmpEndDirectiveParser{loopDir}).Parse(state)};
19291937 return OpenMPLoopConstruct{OmpBeginLoopDirective(std::move(*begin)),
19301938 std::move(*body),
@@ -2021,11 +2029,9 @@ struct OmpAtomicConstructParser {
20212029 return std::nullopt;
20222030 }
20232031
2024- auto exec{Parser<ExecutionPartConstruct>{}};
2025- auto end{OmpEndDirectiveParser{llvm::omp::Directive::OMPD_atomic}};
20262032 TailType tail;
20272033
2028- if (ParseOne(exec, end, tail, state)) {
2034+ if (ParseOne(tail, state)) {
20292035 if (!tail.first.empty()) {
20302036 if (auto &&rest{attempt(LimitedTailParser(BodyLimit)).Parse(state)}) {
20312037 for (auto &&s : rest->first) {
@@ -2052,13 +2058,12 @@ struct OmpAtomicConstructParser {
20522058
20532059 // Parse either an ExecutionPartConstruct, or atomic end-directive. When
20542060 // successful, record the result in the "tail" provided, otherwise fail.
2055- static std::optional<Success> ParseOne( //
2056- Parser<ExecutionPartConstruct> &exec, OmpEndDirectiveParser &end,
2057- TailType &tail, ParseState &state) {
2058- auto isRecovery{[](const ExecutionPartConstruct &e) {
2059- return std::holds_alternative<ErrorRecovery>(e.u);
2061+ static std::optional<Success> ParseOne(TailType &tail, ParseState &state) {
2062+ auto isUsable{[](const std::optional<ExecutionPartConstruct> &e) {
2063+ return e && !std::holds_alternative<ErrorRecovery>(e->u);
20602064 }};
2061- if (auto &&stmt{attempt(exec).Parse(state)}; stmt && !isRecovery(*stmt)) {
2065+ auto end{OmpEndDirectiveParser{llvm::omp::Directive::OMPD_atomic}};
2066+ if (auto &&stmt{attempt(validEPC).Parse(state)}; isUsable(stmt)) {
20622067 tail.first.emplace_back(std::move(*stmt));
20632068 } else if (auto &&dir{attempt(end).Parse(state)}) {
20642069 tail.second = std::move(*dir);
@@ -2074,12 +2079,10 @@ struct OmpAtomicConstructParser {
20742079 constexpr LimitedTailParser(size_t count) : count_(count) {}
20752080
20762081 std::optional<resultType> Parse(ParseState &state) const {
2077- auto exec{Parser<ExecutionPartConstruct>{}};
2078- auto end{OmpEndDirectiveParser{llvm::omp::Directive::OMPD_atomic}};
20792082 TailType tail;
20802083
20812084 for (size_t i{0}; i != count_; ++i) {
2082- if (ParseOne(exec, end, tail, state)) {
2085+ if (ParseOne(tail, state)) {
20832086 if (tail.second) {
20842087 // Return when the end-directive was parsed.
20852088 return std::move(tail);
@@ -2351,9 +2354,9 @@ TYPE_PARSER(sourced(construct<OpenMPSectionsConstruct>(
23512354 Parser<OmpBeginSectionsDirective>{} / endOmpLine,
23522355 cons( //
23532356 construct<OpenMPConstruct>(sourced(
2354- construct<OpenMPSectionConstruct>(maybe(sectionDir), block ))),
2355- many(construct<OpenMPConstruct>(
2356- sourced( construct<OpenMPSectionConstruct>(sectionDir, block ))))),
2357+ construct<OpenMPSectionConstruct>(maybe(sectionDir), validBlock ))),
2358+ many(construct<OpenMPConstruct>(sourced(
2359+ construct<OpenMPSectionConstruct>(sectionDir, validBlock ))))),
23572360 maybe(Parser<OmpEndSectionsDirective>{} / endOmpLine))))
23582361
23592362static bool IsExecutionPart(const OmpDirectiveName &name) {
@@ -2429,4 +2432,14 @@ static constexpr DirectiveSet GetLoopDirectives() {
24292432TYPE_PARSER(sourced(construct<OpenMPLoopConstruct>(
24302433 OmpLoopConstructParser(GetLoopDirectives()))))
24312434
2435+ static constexpr DirectiveSet GetAllDirectives() { //
2436+ return ~DirectiveSet{};
2437+ }
2438+
2439+ TYPE_PARSER(construct<OpenMPMisplacedEndDirective>(
2440+ OmpEndDirectiveParser{GetAllDirectives()}))
2441+
2442+ TYPE_PARSER( //
2443+ startOmpLine >> sourced(construct<OpenMPInvalidDirective>(
2444+ !OmpDirectiveNameParser{} >> SkipTo<'\n'>{})))
24322445} // namespace Fortran::parser
0 commit comments