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.cpp90
1 files changed, 72 insertions, 18 deletions
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 191c555..9b73dc8 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -34,6 +34,39 @@ namespace Fortran::parser {
constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok;
constexpr auto endOmpLine = space >> endOfLine;
+// Given a parser for a single element, and a parser for a list of elements
+// of the same type, create a parser that constructs the entire list by having
+// the single element be the head of the list, and the rest be the tail.
+template <typename ParserH, typename ParserT> struct ConsParser {
+ static_assert(std::is_same_v<std::list<typename ParserH::resultType>,
+ typename ParserT::resultType>);
+
+ using resultType = typename ParserT::resultType;
+ constexpr ConsParser(ParserH h, ParserT t) : head_(h), tail_(t) {}
+
+ std::optional<resultType> Parse(ParseState &state) const {
+ if (auto &&first{head_.Parse(state)}) {
+ if (auto rest{tail_.Parse(state)}) {
+ rest->push_front(std::move(*first));
+ return std::move(*rest);
+ }
+ }
+ return std::nullopt;
+ }
+
+private:
+ const ParserH head_;
+ const ParserT tail_;
+};
+
+template <typename ParserH, typename ParserT,
+ typename ValueH = typename ParserH::resultType,
+ typename ValueT = typename ParserT::resultType,
+ typename = std::enable_if_t<std::is_same_v<std::list<ValueH>, ValueT>>>
+constexpr auto cons(ParserH head, ParserT tail) {
+ return ConsParser<ParserH, ParserT>(head, tail);
+}
+
// Given a parser P for a wrapper class, invoke P, and if it succeeds return
// the wrapped object.
template <typename Parser> struct UnwrapParser {
@@ -449,6 +482,9 @@ TYPE_PARSER(construct<OmpAllocatorSimpleModifier>(scalarIntExpr))
TYPE_PARSER(construct<OmpAlwaysModifier>( //
"ALWAYS" >> pure(OmpAlwaysModifier::Value::Always)))
+TYPE_PARSER(construct<OmpAutomapModifier>(
+ "AUTOMAP" >> pure(OmpAutomapModifier::Value::Automap)))
+
TYPE_PARSER(construct<OmpChunkModifier>( //
"SIMD" >> pure(OmpChunkModifier::Value::Simd)))
@@ -466,6 +502,8 @@ TYPE_PARSER(construct<OmpDeviceModifier>(
"ANCESTOR" >> pure(OmpDeviceModifier::Value::Ancestor) ||
"DEVICE_NUM" >> pure(OmpDeviceModifier::Value::Device_Num)))
+TYPE_PARSER(construct<OmpDirectiveNameModifier>(OmpDirectiveNameParser{}))
+
TYPE_PARSER(construct<OmpExpectation>( //
"PRESENT" >> pure(OmpExpectation::Value::Present)))
@@ -601,6 +639,9 @@ TYPE_PARSER(sourced(construct<OmpDependClause::TaskDep::Modifier>(sourced(
TYPE_PARSER(
sourced(construct<OmpDeviceClause::Modifier>(Parser<OmpDeviceModifier>{})))
+TYPE_PARSER(
+ sourced(construct<OmpEnterClause::Modifier>(Parser<OmpAutomapModifier>{})))
+
TYPE_PARSER(sourced(construct<OmpFromClause::Modifier>(
sourced(construct<OmpFromClause::Modifier>(Parser<OmpExpectation>{}) ||
construct<OmpFromClause::Modifier>(Parser<OmpMapper>{}) ||
@@ -609,7 +650,8 @@ TYPE_PARSER(sourced(construct<OmpFromClause::Modifier>(
TYPE_PARSER(sourced(
construct<OmpGrainsizeClause::Modifier>(Parser<OmpPrescriptiveness>{})))
-TYPE_PARSER(sourced(construct<OmpIfClause::Modifier>(OmpDirectiveNameParser{})))
+TYPE_PARSER(sourced(
+ construct<OmpIfClause::Modifier>(Parser<OmpDirectiveNameModifier>{})))
TYPE_PARSER(sourced(
construct<OmpInitClause::Modifier>(
@@ -735,6 +777,10 @@ TYPE_PARSER(construct<OmpDefaultClause>(
Parser<OmpDefaultClause::DataSharingAttribute>{}) ||
construct<OmpDefaultClause>(indirect(Parser<OmpDirectiveSpecification>{}))))
+TYPE_PARSER(construct<OmpEnterClause>(
+ maybe(nonemptyList(Parser<OmpEnterClause::Modifier>{}) / ":"),
+ Parser<OmpObjectList>{}))
+
TYPE_PARSER(construct<OmpFailClause>(
"ACQ_REL" >> pure(common::OmpMemoryOrderType::Acq_Rel) ||
"ACQUIRE" >> pure(common::OmpMemoryOrderType::Acquire) ||
@@ -1023,7 +1069,7 @@ TYPE_PARSER( //
"DYNAMIC_ALLOCATORS" >>
construct<OmpClause>(construct<OmpClause::DynamicAllocators>()) ||
"ENTER" >> construct<OmpClause>(construct<OmpClause::Enter>(
- parenthesized(Parser<OmpObjectList>{}))) ||
+ parenthesized(Parser<OmpEnterClause>{}))) ||
"EXCLUSIVE" >> construct<OmpClause>(construct<OmpClause::Exclusive>(
parenthesized(Parser<OmpObjectList>{}))) ||
"FAIL" >> construct<OmpClause>(construct<OmpClause::Fail>(
@@ -1222,11 +1268,14 @@ struct StrictlyStructuredBlockParser {
using resultType = Block;
std::optional<resultType> Parse(ParseState &state) const {
- if (auto epc{Parser<ExecutionPartConstruct>{}.Parse(state)}) {
- if (IsFortranBlockConstruct(*epc)) {
- Block block;
- block.emplace_back(std::move(*epc));
- return std::move(block);
+ // 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;
@@ -1237,6 +1286,10 @@ 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)) {
@@ -1627,7 +1680,7 @@ static constexpr auto StandaloneDirectiveLookahead{//
"TARGET UPDATE"_sptok || "TARGET_UPDATE"_sptok};
// Directives enclosing structured-block
-TYPE_PARSER(!StandaloneDirectiveLookahead >=
+TYPE_PARSER((!StandaloneDirectiveLookahead) >=
construct<OmpBlockDirective>(first(
"MASKED" >> pure(llvm::omp::Directive::OMPD_masked),
"MASTER" >> pure(llvm::omp::Directive::OMPD_master),
@@ -1821,19 +1874,20 @@ TYPE_PARSER(
sourced("END"_tok >> Parser<OmpSectionsDirective>{}),
Parser<OmpClauseList>{})))
-// OMP SECTION-BLOCK
-
-TYPE_PARSER(construct<OpenMPSectionConstruct>(block))
-
-TYPE_PARSER(maybe(startOmpLine >> "SECTION"_tok / endOmpLine) >>
- construct<OmpSectionBlocks>(nonemptySeparated(
- construct<OpenMPConstruct>(sourced(Parser<OpenMPSectionConstruct>{})),
- startOmpLine >> "SECTION"_tok / endOmpLine)))
+static constexpr auto sectionDir{
+ startOmpLine >> (predicated(OmpDirectiveNameParser{},
+ IsDirective(llvm::omp::Directive::OMPD_section)) >=
+ Parser<OmpDirectiveSpecification>{})};
// OMP SECTIONS (OpenMP 5.0 - 2.8.1), PARALLEL SECTIONS (OpenMP 5.0 - 2.13.3)
-TYPE_PARSER(construct<OpenMPSectionsConstruct>(
+TYPE_PARSER(sourced(construct<OpenMPSectionsConstruct>(
Parser<OmpBeginSectionsDirective>{} / endOmpLine,
- Parser<OmpSectionBlocks>{}, Parser<OmpEndSectionsDirective>{} / endOmpLine))
+ cons( //
+ construct<OpenMPConstruct>(sourced(
+ construct<OpenMPSectionConstruct>(maybe(sectionDir), block))),
+ many(construct<OpenMPConstruct>(
+ sourced(construct<OpenMPSectionConstruct>(sectionDir, block))))),
+ Parser<OmpEndSectionsDirective>{} / endOmpLine)))
static bool IsExecutionPart(const OmpDirectiveName &name) {
return name.IsExecutionPart();