[flang-commits] [flang] [llvm] [flang][OpenMP] Apply modifier representation to semantic checks (PR #116658)
Krzysztof Parzyszek via flang-commits
flang-commits at lists.llvm.org
Wed Nov 20 09:01:55 PST 2024
https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/116658
>From 2ab3e2955f2b86e33354c5d9f0d724eba580cb6d Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 7 Nov 2024 17:38:50 -0600
Subject: [PATCH 1/8] [flang][OpenMP] Normalize clause modifiers that exist on
their own
This is the first part of the effort to make parsing of clause modifiers
more uniform and robust. Currently, when multiple modifiers are allowed,
the parser will expect them to appear in a hard-coded order.
Additionally, modifier properties (such as "ultimate") are checked
separately for each case.
The overall plan is
1. Extract all modifiers into their own top-level classes, and then equip
them with sets of common properties that will allow performing the property
checks generically, without refering to the specific kind of the modifier.
2. Define a parser (as a separate class) for each modifier.
3. For each clause define a union (std::variant) of all allowable
modifiers, and parse the modifiers as a list of these unions.
The intent is also to isolate parts of the code that could eventually
be auto-generated.
OpenMP modifier overhaul: #1/3
---
flang/include/flang/Parser/dump-parse-tree.h | 10 +-
flang/include/flang/Parser/parse-tree.h | 113 +++++++++++-------
flang/lib/Lower/OpenMP/Clauses.cpp | 44 ++++---
flang/lib/Parser/openmp-parsers.cpp | 72 +++++------
flang/lib/Parser/parse-tree.cpp | 8 +-
flang/lib/Parser/unparse.cpp | 20 ++--
flang/lib/Semantics/check-omp-structure.cpp | 40 +++----
flang/lib/Semantics/check-omp-structure.h | 6 +-
flang/lib/Semantics/resolve-directives.cpp | 4 +-
flang/test/Parser/OpenMP/affinity-clause.f90 | 2 +-
flang/test/Parser/OpenMP/depobj-construct.f90 | 4 +-
flang/test/Parser/OpenMP/from-clause.f90 | 4 +-
.../Parser/OpenMP/in-reduction-clause.f90 | 6 +-
flang/test/Parser/OpenMP/map-modifiers.f90 | 8 +-
.../test/Parser/OpenMP/reduction-modifier.f90 | 2 +-
.../Parser/OpenMP/target-update-to-clause.f90 | 4 +-
16 files changed, 188 insertions(+), 159 deletions(-)
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 5886e384b986b6..df5bf1d8d3200e 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -477,7 +477,7 @@ class ParseTreeDumper {
NODE(parser, ObjectDecl)
NODE(parser, OldParameterStmt)
NODE(parser, OmpIteratorSpecifier)
- NODE(parser, OmpIteratorModifier)
+ NODE(parser, OmpIterator)
NODE(parser, OmpAffinityClause)
NODE(parser, OmpAlignedClause)
NODE(parser, OmpAtomic)
@@ -513,9 +513,9 @@ class ParseTreeDumper {
NODE_ENUM(OmpDefaultmapClause, ImplicitBehavior)
NODE_ENUM(OmpDefaultmapClause, VariableCategory)
NODE(parser, OmpDependenceType)
- NODE_ENUM(OmpDependenceType, Type)
+ NODE_ENUM(OmpDependenceType, Value)
NODE(parser, OmpTaskDependenceType)
- NODE_ENUM(OmpTaskDependenceType, Type)
+ NODE_ENUM(OmpTaskDependenceType, Value)
NODE(parser, OmpIterationOffset)
NODE(parser, OmpIteration)
NODE(parser, OmpIterationVector)
@@ -543,7 +543,7 @@ class ParseTreeDumper {
NODE(OmpLinearClause, WithModifier)
NODE(OmpLinearClause, WithoutModifier)
NODE(parser, OmpLinearModifier)
- NODE_ENUM(OmpLinearModifier, Type)
+ NODE_ENUM(OmpLinearModifier, Value)
NODE(parser, OmpLoopDirective)
NODE(parser, OmpMapClause)
NODE_ENUM(OmpMapClause, TypeModifier)
@@ -573,7 +573,7 @@ class ParseTreeDumper {
NODE(parser, OmpReductionCombiner)
NODE(OmpReductionCombiner, FunctionCombiner)
NODE(parser, OmpReductionInitializerClause)
- NODE(parser, OmpReductionOperator)
+ NODE(parser, OmpReductionIdentifier)
NODE(parser, OmpAllocateClause)
NODE(OmpAllocateClause, AllocateModifier)
NODE(OmpAllocateClause::AllocateModifier, Allocator)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 8f50809599a589..ef49a36578270e 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3440,13 +3440,33 @@ struct OmpObject {
WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
+inline namespace modifier {
+// For uniformity, in all keyword modifiers the name of the type defined
+// by ENUM_CLASS is "Value", e.g.
+// struct Foo {
+// ENUM_CLASS(Value, Keyword1, Keyword2);
+// };
+
+// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
+//
+// iterator-specifier ->
+// [iterator-type] iterator-identifier
+// = range-specification | // since 5.0
+// [iterator-type ::] iterator-identifier
+// = range-specification // since 5.2
+struct OmpIteratorSpecifier {
+ TUPLE_CLASS_BOILERPLATE(OmpIteratorSpecifier);
+ CharBlock source;
+ std::tuple<TypeDeclarationStmt, SubscriptTriplet> t;
+};
+
// Ref: [4.5:169-170], [5.0:255-256], [5.1:288-289]
//
// dependence-type ->
-// SINK | SOURCE | // since 4.5
-// IN | OUT | INOUT | // since 4.5, until 5.1
-// MUTEXINOUTSET | DEPOBJ | // since 5.0, until 5.1
-// INOUTSET // since 5.1, until 5.1
+// SINK | SOURCE | // since 4.5
+// IN | OUT | INOUT | // since 4.5, until 5.1
+// MUTEXINOUTSET | DEPOBJ | // since 5.0, until 5.1
+// INOUTSET // since 5.1, until 5.1
//
// All of these, except SINK and SOURCE became task-dependence-type in 5.2.
//
@@ -3457,45 +3477,59 @@ WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
// vector). This would accept the vector "i, j, k" (although interpreted
// incorrectly), while flagging a syntax error for "i+1, j, k".
struct OmpDependenceType {
- ENUM_CLASS(Type, Sink, Source);
- WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Type);
+ ENUM_CLASS(Value, Sink, Source);
+ WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Value);
};
-// Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321]
+// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
//
-// task-dependence-type -> // "dependence-type" in 5.1 and before
-// IN | OUT | INOUT | // since 4.5
-// MUTEXINOUTSET | DEPOBJ | // since 5.0
-// INOUTSET // since 5.2
-struct OmpTaskDependenceType {
- ENUM_CLASS(Type, In, Out, Inout, Inoutset, Mutexinoutset, Depobj)
- WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Type);
+// iterator-modifier ->
+// ITERATOR(iterator-specifier [, ...]) // since 5.0
+struct OmpIterator {
+ WRAPPER_CLASS_BOILERPLATE(OmpIterator, std::list<OmpIteratorSpecifier>);
};
-// [5.0] 2.1.6 iterator-specifier -> type-declaration-stmt = subscript-triple
-// iterator-modifier -> iterator-specifier-list
-struct OmpIteratorSpecifier {
- TUPLE_CLASS_BOILERPLATE(OmpIteratorSpecifier);
- CharBlock source;
- std::tuple<TypeDeclarationStmt, SubscriptTriplet> t;
+// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
+//
+// linear-modifier ->
+// REF | UVAL | VAL // since 4.5
+struct OmpLinearModifier {
+ ENUM_CLASS(Value, Ref, Uval, Val);
+ WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Value);
};
-WRAPPER_CLASS(OmpIteratorModifier, std::list<OmpIteratorSpecifier>);
-
-// 2.15.3.6 reduction-identifier -> + | - | * | .AND. | .OR. | .EQV. | .NEQV. |
-// MAX | MIN | IAND | IOR | IEOR
-struct OmpReductionOperator {
- UNION_CLASS_BOILERPLATE(OmpReductionOperator);
+// Ref: [4.5:201-207], [5.0:293-299], [5.1:325-331], [5.2:124]
+//
+// reduction-identifier ->
+// base-language-identifier | // since 4.5
+// - | // since 4.5, until 5.2
+// + | * | .AND. | .OR. | .EQV. | .NEQV. | // since 4.5
+// MIN | MAX | IAND | IOR | IEOR // since 4.5
+//
+struct OmpReductionIdentifier {
+ UNION_CLASS_BOILERPLATE(OmpReductionIdentifier);
std::variant<DefinedOperator, ProcedureDesignator> u;
};
+// Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321]
+//
+// task-dependence-type -> // "dependence-type" in 5.1 and before
+// IN | OUT | INOUT | // since 4.5
+// MUTEXINOUTSET | DEPOBJ | // since 5.0
+// INOUTSET // since 5.2
+struct OmpTaskDependenceType {
+ ENUM_CLASS(Value, In, Out, Inout, Inoutset, Mutexinoutset, Depobj)
+ WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Value);
+};
+} // namespace modifier
+
// --- Clauses
// OMP 5.0 2.10.1 affinity([aff-modifier:] locator-list)
// aff-modifier: interator-modifier
struct OmpAffinityClause {
TUPLE_CLASS_BOILERPLATE(OmpAffinityClause);
- std::tuple<std::optional<OmpIteratorModifier>, OmpObjectList> t;
+ std::tuple<std::optional<OmpIterator>, OmpObjectList> t;
};
// 2.8.1 aligned-clause -> ALIGNED (variable-name-list[ : scalar-constant])
@@ -3566,7 +3600,7 @@ WRAPPER_CLASS(OmpIterationVector, std::list<OmpIteration>);
// OmpDoacrossClause), so that the context in TYPE_CONTEXT_PARSER can be set
// separately for OmpDependClause and OmpDoacrossClause.
struct OmpDoacross {
- OmpDependenceType::Type GetDepType() const;
+ OmpDependenceType::Value GetDepType() const;
WRAPPER_CLASS(Sink, OmpIterationVector);
EMPTY_CLASS(Source);
@@ -3586,10 +3620,9 @@ struct OmpDoacross {
struct OmpDependClause {
UNION_CLASS_BOILERPLATE(OmpDependClause);
struct TaskDep {
- OmpTaskDependenceType::Type GetTaskDepType() const;
+ OmpTaskDependenceType::Value GetTaskDepType() const;
TUPLE_CLASS_BOILERPLATE(TaskDep);
- std::tuple<std::optional<OmpIteratorModifier>, OmpTaskDependenceType,
- OmpObjectList>
+ std::tuple<std::optional<OmpIterator>, OmpTaskDependenceType, OmpObjectList>
t;
};
std::variant<TaskDep, OmpDoacross> u;
@@ -3632,7 +3665,7 @@ struct OmpFromClause {
// As in the case of MAP, modifiers are parsed as lists, even if they
// are unique. These restrictions will be checked in semantic checks.
std::tuple<std::optional<std::list<Expectation>>,
- std::optional<std::list<OmpIteratorModifier>>, OmpObjectList,
+ std::optional<std::list<OmpIterator>>, OmpObjectList,
bool> // were the modifiers comma-separated?
t;
};
@@ -3661,7 +3694,7 @@ struct OmpDetachClause {
// variable-name-list)
struct OmpInReductionClause {
TUPLE_CLASS_BOILERPLATE(OmpInReductionClause);
- std::tuple<OmpReductionOperator, OmpObjectList> t;
+ std::tuple<OmpReductionIdentifier, OmpObjectList> t;
};
// OMP 5.0 2.19.4.5 lastprivate-clause ->
@@ -3673,12 +3706,6 @@ struct OmpLastprivateClause {
std::tuple<std::optional<LastprivateModifier>, OmpObjectList> t;
};
-// 2.15.3.7 linear-modifier -> REF | VAL | UVAL
-struct OmpLinearModifier {
- ENUM_CLASS(Type, Ref, Val, Uval)
- WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Type);
-};
-
// 2.15.3.7 linear-clause -> LINEAR (linear-list[ : linear-step])
// linear-list -> list | linear-modifier(list)
struct OmpLinearClause {
@@ -3719,7 +3746,7 @@ struct OmpMapClause {
// In OpenMP 5.2 the non-comma syntax has been deprecated: keep the
// information about separator presence to emit a diagnostic if needed.
std::tuple<std::optional<std::list<TypeModifier>>,
- std::optional<std::list<OmpIteratorModifier>>, // unique
+ std::optional<std::list<OmpIterator>>, // unique
std::optional<std::list<Type>>, // unique
OmpObjectList,
bool> // were the modifiers comma-separated?
@@ -3749,7 +3776,7 @@ struct OmpProcBindClause {
struct OmpReductionClause {
TUPLE_CLASS_BOILERPLATE(OmpReductionClause);
ENUM_CLASS(ReductionModifier, Inscan, Task, Default)
- std::tuple<std::optional<ReductionModifier>, OmpReductionOperator,
+ std::tuple<std::optional<ReductionModifier>, OmpReductionIdentifier,
OmpObjectList>
t;
};
@@ -3794,7 +3821,7 @@ struct OmpToClause {
// As in the case of MAP, modifiers are parsed as lists, even if they
// are unique. These restrictions will be checked in semantic checks.
std::tuple<std::optional<std::list<Expectation>>,
- std::optional<std::list<OmpIteratorModifier>>, OmpObjectList,
+ std::optional<std::list<OmpIterator>>, OmpObjectList,
bool> // were the modifiers comma-separated?
t;
};
@@ -3942,7 +3969,7 @@ WRAPPER_CLASS(OmpReductionInitializerClause, Expr);
struct OpenMPDeclareReductionConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct);
CharBlock source;
- std::tuple<Verbatim, OmpReductionOperator, std::list<DeclarationTypeSpec>,
+ std::tuple<Verbatim, OmpReductionIdentifier, std::list<DeclarationTypeSpec>,
OmpReductionCombiner, std::optional<OmpReductionInitializerClause>>
t;
};
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index f897022ef9512b..5e514b4ba9f0da 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -264,7 +264,7 @@ makeIteratorSpecifiers(const parser::OmpIteratorSpecifier &inp,
return specifiers;
}
-Iterator makeIterator(const parser::OmpIteratorModifier &inp,
+Iterator makeIterator(const parser::OmpIterator &inp,
semantics::SemanticsContext &semaCtx) {
Iterator iterator;
for (auto &&spec : inp.v)
@@ -324,8 +324,9 @@ makeProcedureDesignator(const parser::ProcedureDesignator &inp,
inp.u)};
}
-ReductionOperator makeReductionOperator(const parser::OmpReductionOperator &inp,
- semantics::SemanticsContext &semaCtx) {
+ReductionOperator
+makeReductionOperator(const parser::OmpReductionIdentifier &inp,
+ semantics::SemanticsContext &semaCtx) {
return Fortran::common::visit(
common::visitors{
[&](const parser::DefinedOperator &s) {
@@ -340,9 +341,9 @@ ReductionOperator makeReductionOperator(const parser::OmpReductionOperator &inp,
clause::DependenceType makeDepType(const parser::OmpDependenceType &inp) {
switch (inp.v) {
- case parser::OmpDependenceType::Type::Sink:
+ case parser::OmpDependenceType::Value::Sink:
return clause::DependenceType::Sink;
- case parser::OmpDependenceType::Type::Source:
+ case parser::OmpDependenceType::Value::Source:
return clause::DependenceType::Source;
}
llvm_unreachable("Unexpected dependence type");
@@ -350,17 +351,17 @@ clause::DependenceType makeDepType(const parser::OmpDependenceType &inp) {
clause::DependenceType makeDepType(const parser::OmpTaskDependenceType &inp) {
switch (inp.v) {
- case parser::OmpTaskDependenceType::Type::Depobj:
+ case parser::OmpTaskDependenceType::Value::Depobj:
return clause::DependenceType::Depobj;
- case parser::OmpTaskDependenceType::Type::In:
+ case parser::OmpTaskDependenceType::Value::In:
return clause::DependenceType::In;
- case parser::OmpTaskDependenceType::Type::Inout:
+ case parser::OmpTaskDependenceType::Value::Inout:
return clause::DependenceType::Inout;
- case parser::OmpTaskDependenceType::Type::Inoutset:
+ case parser::OmpTaskDependenceType::Value::Inoutset:
return clause::DependenceType::Inoutset;
- case parser::OmpTaskDependenceType::Type::Mutexinoutset:
+ case parser::OmpTaskDependenceType::Value::Mutexinoutset:
return clause::DependenceType::Mutexinoutset;
- case parser::OmpTaskDependenceType::Type::Out:
+ case parser::OmpTaskDependenceType::Value::Out:
return clause::DependenceType::Out;
}
llvm_unreachable("Unexpected task dependence type");
@@ -381,7 +382,7 @@ Absent make(const parser::OmpClause::Absent &inp,
Affinity make(const parser::OmpClause::Affinity &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpAffinityClause
- auto &t0 = std::get<std::optional<parser::OmpIteratorModifier>>(inp.v.t);
+ auto &t0 = std::get<std::optional<parser::OmpIterator>>(inp.v.t);
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
auto &&maybeIter =
@@ -626,7 +627,7 @@ Depend make(const parser::OmpClause::Depend &inp,
using Variant = decltype(Depend::u);
auto visitTaskDep = [&](const wrapped::TaskDep &s) -> Variant {
- auto &t0 = std::get<std::optional<parser::OmpIteratorModifier>>(s.t);
+ auto &t0 = std::get<std::optional<parser::OmpIterator>>(s.t);
auto &t1 = std::get<parser::OmpTaskDependenceType>(s.t);
auto &t2 = std::get<parser::OmpObjectList>(s.t);
@@ -769,8 +770,7 @@ From make(const parser::OmpClause::From &inp,
);
auto &t0 = std::get<std::optional<std::list<wrapped::Expectation>>>(inp.v.t);
- auto &t1 =
- std::get<std::optional<std::list<parser::OmpIteratorModifier>>>(inp.v.t);
+ auto &t1 = std::get<std::optional<std::list<parser::OmpIterator>>>(inp.v.t);
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
assert((!t0 || t0->size() == 1) && "Only one expectation modifier allowed");
@@ -881,7 +881,7 @@ Init make(const parser::OmpClause::Init &inp,
InReduction make(const parser::OmpClause::InReduction &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpInReductionClause
- auto &t0 = std::get<parser::OmpReductionOperator>(inp.v.t);
+ auto &t0 = std::get<parser::OmpReductionIdentifier>(inp.v.t);
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
return InReduction{
{/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)},
@@ -920,7 +920,7 @@ Linear make(const parser::OmpClause::Linear &inp,
using wrapped = parser::OmpLinearClause;
CLAUSET_ENUM_CONVERT( //
- convert, parser::OmpLinearModifier::Type, Linear::LinearModifier,
+ convert, parser::OmpLinearModifier::Value, Linear::LinearModifier,
// clang-format off
MS(Ref, Ref)
MS(Val, Val)
@@ -984,8 +984,7 @@ Map make(const parser::OmpClause::Map &inp,
);
auto &t0 = std::get<std::optional<std::list<wrapped::TypeModifier>>>(inp.v.t);
- auto &t1 =
- std::get<std::optional<std::list<parser::OmpIteratorModifier>>>(inp.v.t);
+ auto &t1 = std::get<std::optional<std::list<parser::OmpIterator>>>(inp.v.t);
auto &t2 = std::get<std::optional<std::list<wrapped::Type>>>(inp.v.t);
auto &t3 = std::get<parser::OmpObjectList>(inp.v.t);
@@ -1188,7 +1187,7 @@ Reduction make(const parser::OmpClause::Reduction &inp,
auto &t0 =
std::get<std::optional<parser::OmpReductionClause::ReductionModifier>>(
inp.v.t);
- auto &t1 = std::get<parser::OmpReductionOperator>(inp.v.t);
+ auto &t1 = std::get<parser::OmpReductionIdentifier>(inp.v.t);
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
return Reduction{
{/*ReductionModifier=*/t0
@@ -1315,7 +1314,7 @@ Permutation make(const parser::OmpClause::Permutation &inp,
TaskReduction make(const parser::OmpClause::TaskReduction &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpReductionClause
- auto &t0 = std::get<parser::OmpReductionOperator>(inp.v.t);
+ auto &t0 = std::get<parser::OmpReductionIdentifier>(inp.v.t);
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
return TaskReduction{
{/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)},
@@ -1344,8 +1343,7 @@ To make(const parser::OmpClause::To &inp,
);
auto &t0 = std::get<std::optional<std::list<wrapped::Expectation>>>(inp.v.t);
- auto &t1 =
- std::get<std::optional<std::list<parser::OmpIteratorModifier>>>(inp.v.t);
+ auto &t1 = std::get<std::optional<std::list<parser::OmpIterator>>>(inp.v.t);
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
assert((!t0 || t0->size() == 1) && "Only one expectation modifier allowed");
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 5ead9a48fa8969..b4d45873abb3ec 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -97,7 +97,7 @@ template <typename Separator> struct MapModifiers {
// Parsing of mappers is not supported yet.
using TypeModParser = Parser<OmpMapClause::TypeModifier>;
- using IterParser = Parser<OmpIteratorModifier>;
+ using IterParser = Parser<OmpIterator>;
using TypeParser = Parser<OmpMapClause::Type>;
using ModParser =
ConcatSeparated<Separator, TypeModParser, IterParser, TypeParser>;
@@ -133,7 +133,7 @@ template <typename Separator> struct MotionModifiers {
// Parsing of mappers if not implemented yet.
using ExpParser = Parser<OmpFromClause::Expectation>;
- using IterParser = Parser<OmpIteratorModifier>;
+ using IterParser = Parser<OmpIterator>;
using ModParser = ConcatSeparated<Separator, ExpParser, IterParser>;
using resultType = typename ModParser::resultType;
@@ -191,6 +191,8 @@ static TypeDeclarationStmt makeIterSpecDecl(std::list<ObjectName> &&names) {
makeEntityList(std::move(names)));
}
+// --- Parsers for clause modifiers -----------------------------------
+
TYPE_PARSER(construct<OmpIteratorSpecifier>(
// Using Parser<TypeDeclarationStmt> or Parser<EntityDecl> has the problem
// that they will attempt to treat what follows the '=' as initialization.
@@ -207,14 +209,40 @@ TYPE_PARSER(construct<OmpIteratorSpecifier>(
makeIterSpecDecl, nonemptyList(Parser<ObjectName>{}) / "="_tok)),
subscriptTriplet))
+TYPE_PARSER(construct<OmpDependenceType>(
+ "SINK" >> pure(OmpDependenceType::Value::Sink) ||
+ "SOURCE" >> pure(OmpDependenceType::Value::Source)))
+
// [5.0] 2.1.6 iterator -> iterator-specifier-list
-TYPE_PARSER(construct<OmpIteratorModifier>("ITERATOR" >>
+TYPE_PARSER(construct<OmpIterator>("ITERATOR" >>
parenthesized(nonemptyList(sourced(Parser<OmpIteratorSpecifier>{})))))
+// 2.15.3.7 LINEAR (linear-list: linear-step)
+// linear-list -> list | modifier(list)
+// linear-modifier -> REF | VAL | UVAL
+TYPE_PARSER(construct<OmpLinearModifier>( //
+ "REF" >> pure(OmpLinearModifier::Value::Ref) ||
+ "VAL" >> pure(OmpLinearModifier::Value::Val) ||
+ "UVAL" >> pure(OmpLinearModifier::Value::Uval)))
+
+// 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list)
+TYPE_PARSER(construct<OmpReductionIdentifier>(Parser<DefinedOperator>{}) ||
+ construct<OmpReductionIdentifier>(Parser<ProcedureDesignator>{}))
+
+TYPE_PARSER(construct<OmpTaskDependenceType>(
+ "DEPOBJ" >> pure(OmpTaskDependenceType::Value::Depobj) ||
+ "IN"_id >> pure(OmpTaskDependenceType::Value::In) ||
+ "INOUT"_id >> pure(OmpTaskDependenceType::Value::Inout) ||
+ "INOUTSET"_id >> pure(OmpTaskDependenceType::Value::Inoutset) ||
+ "MUTEXINOUTSET" >> pure(OmpTaskDependenceType::Value::Mutexinoutset) ||
+ "OUT" >> pure(OmpTaskDependenceType::Value::Out)))
+
+// --- Parsers for clauses --------------------------------------------
+
// [5.0] 2.10.1 affinity([aff-modifier:] locator-list)
// aff-modifier: interator-modifier
TYPE_PARSER(construct<OmpAffinityClause>(
- maybe(Parser<OmpIteratorModifier>{} / ":"), Parser<OmpObjectList>{}))
+ maybe(Parser<OmpIterator>{} / ":"), Parser<OmpObjectList>{}))
// 2.15.3.1 DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE)
TYPE_PARSER(construct<OmpDefaultClause>(
@@ -252,7 +280,7 @@ TYPE_PARSER(
template <bool CommasEverywhere>
static inline OmpMapClause makeMapClause(
std::tuple<std::optional<std::list<OmpMapClause::TypeModifier>>,
- std::optional<std::list<OmpIteratorModifier>>,
+ std::optional<std::list<OmpIterator>>,
std::optional<std::list<OmpMapClause::Type>>> &&mods,
OmpObjectList &&objs) {
auto &&[tm, it, ty] = std::move(mods);
@@ -346,21 +374,17 @@ TYPE_PARSER(construct<OmpIfClause>(
":"),
scalarLogicalExpr))
-// 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list)
-TYPE_PARSER(construct<OmpReductionOperator>(Parser<DefinedOperator>{}) ||
- construct<OmpReductionOperator>(Parser<ProcedureDesignator>{}))
-
TYPE_PARSER(construct<OmpReductionClause>(
maybe(
("INSCAN" >> pure(OmpReductionClause::ReductionModifier::Inscan) ||
"TASK" >> pure(OmpReductionClause::ReductionModifier::Task) ||
"DEFAULT" >> pure(OmpReductionClause::ReductionModifier::Default)) /
","),
- Parser<OmpReductionOperator>{} / ":", Parser<OmpObjectList>{}))
+ Parser<OmpReductionIdentifier>{} / ":", Parser<OmpObjectList>{}))
// OMP 5.0 2.19.5.6 IN_REDUCTION (reduction-identifier: variable-name-list)
TYPE_PARSER(construct<OmpInReductionClause>(
- Parser<OmpReductionOperator>{} / ":", Parser<OmpObjectList>{}))
+ Parser<OmpReductionIdentifier>{} / ":", Parser<OmpObjectList>{}))
// OMP 5.0 2.11.4 allocate-clause -> ALLOCATE ([allocator:] variable-name-list)
// OMP 5.2 2.13.4 allocate-clause -> ALLOCATE ([allocate-modifier
@@ -393,18 +417,6 @@ TYPE_PARSER(construct<OmpAllocateClause>(
":"),
Parser<OmpObjectList>{}))
-TYPE_PARSER(construct<OmpDependenceType>(
- "SINK" >> pure(OmpDependenceType::Type::Sink) ||
- "SOURCE" >> pure(OmpDependenceType::Type::Source)))
-
-TYPE_PARSER(construct<OmpTaskDependenceType>(
- "DEPOBJ" >> pure(OmpTaskDependenceType::Type::Depobj) ||
- "IN"_id >> pure(OmpTaskDependenceType::Type::In) ||
- "INOUT"_id >> pure(OmpTaskDependenceType::Type::Inout) ||
- "INOUTSET"_id >> pure(OmpTaskDependenceType::Type::Inoutset) ||
- "MUTEXINOUTSET" >> pure(OmpTaskDependenceType::Type::Mutexinoutset) ||
- "OUT" >> pure(OmpTaskDependenceType::Type::Out)))
-
// iteration-offset -> +/- non-negative-constant-expr
TYPE_PARSER(construct<OmpIterationOffset>(
Parser<DefinedOperator>{}, scalarIntConstantExpr))
@@ -422,7 +434,7 @@ TYPE_PARSER(construct<OmpDoacross>(
TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US,
construct<OmpDependClause>(
construct<OmpDependClause>(construct<OmpDependClause::TaskDep>(
- maybe(Parser<OmpIteratorModifier>{} / ","_tok),
+ maybe(Parser<OmpIterator>{} / ","_tok),
Parser<OmpTaskDependenceType>{} / ":", Parser<OmpObjectList>{})) ||
construct<OmpDependClause>(Parser<OmpDoacross>{})))
@@ -435,7 +447,7 @@ TYPE_PARSER(construct<OmpFromClause::Expectation>(
template <typename MotionClause, bool CommasEverywhere>
static inline MotionClause makeMotionClause(
std::tuple<std::optional<std::list<typename MotionClause::Expectation>>,
- std::optional<std::list<OmpIteratorModifier>>> &&mods,
+ std::optional<std::list<OmpIterator>>> &&mods,
OmpObjectList &&objs) {
auto &&[exp, iter] = std::move(mods);
return MotionClause(
@@ -454,14 +466,6 @@ TYPE_PARSER(construct<OmpToClause>(
applyFunction<OmpToClause>(makeMotionClause<OmpToClause, false>,
MotionModifiers(maybe(","_tok)), Parser<OmpObjectList>{})))
-// 2.15.3.7 LINEAR (linear-list: linear-step)
-// linear-list -> list | modifier(list)
-// linear-modifier -> REF | VAL | UVAL
-TYPE_PARSER(
- construct<OmpLinearModifier>("REF" >> pure(OmpLinearModifier::Type::Ref) ||
- "VAL" >> pure(OmpLinearModifier::Type::Val) ||
- "UVAL" >> pure(OmpLinearModifier::Type::Uval)))
-
TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US,
construct<OmpLinearClause>(
construct<OmpLinearClause>(construct<OmpLinearClause::WithModifier>(
@@ -844,7 +848,7 @@ TYPE_PARSER(construct<OmpReductionInitializerClause>(
// 2.16 Declare Reduction Construct
TYPE_PARSER(sourced(construct<OpenMPDeclareReductionConstruct>(
verbatim("DECLARE REDUCTION"_tok),
- "(" >> Parser<OmpReductionOperator>{} / ":",
+ "(" >> Parser<OmpReductionIdentifier>{} / ":",
nonemptyList(Parser<DeclarationTypeSpec>{}) / ":",
Parser<OmpReductionCombiner>{} / ")",
maybe(Parser<OmpReductionInitializerClause>{}))))
diff --git a/flang/lib/Parser/parse-tree.cpp b/flang/lib/Parser/parse-tree.cpp
index 574e5fd84862e7..24b2902f286f4b 100644
--- a/flang/lib/Parser/parse-tree.cpp
+++ b/flang/lib/Parser/parse-tree.cpp
@@ -253,20 +253,20 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Name &x) {
return os << x.ToString();
}
-OmpDependenceType::Type OmpDoacross::GetDepType() const {
+OmpDependenceType::Value OmpDoacross::GetDepType() const {
return common::visit( //
common::visitors{
[](const OmpDoacross::Sink &) {
- return OmpDependenceType::Type::Sink;
+ return OmpDependenceType::Value::Sink;
},
[](const OmpDoacross::Source &) {
- return OmpDependenceType::Type::Source;
+ return OmpDependenceType::Value::Source;
},
},
u);
}
-OmpTaskDependenceType::Type OmpDependClause::TaskDep::GetTaskDepType() const {
+OmpTaskDependenceType::Value OmpDependClause::TaskDep::GetTaskDepType() const {
return std::get<parser::OmpTaskDependenceType>(t).v;
}
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index a782dfb8d767a5..b2a0256cb58d0c 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2079,7 +2079,7 @@ class UnparseVisitor {
Put(" = ");
Walk(std::get<SubscriptTriplet>(x.t));
}
- void Unparse(const OmpIteratorModifier &x) {
+ void Unparse(const OmpIterator &x) {
Word("ITERATOR(");
Walk(x.v);
Put(")");
@@ -2093,7 +2093,7 @@ class UnparseVisitor {
void Unparse(const OmpMapClause &x) {
auto &typeMod =
std::get<std::optional<std::list<OmpMapClause::TypeModifier>>>(x.t);
- auto &iter = std::get<std::optional<std::list<OmpIteratorModifier>>>(x.t);
+ auto &iter = std::get<std::optional<std::list<OmpIterator>>>(x.t);
auto &type = std::get<std::optional<std::list<OmpMapClause::Type>>>(x.t);
// For a given list of items, if the item has a value, then walk it.
@@ -2137,7 +2137,7 @@ class UnparseVisitor {
Walk(std::get<ScalarIntExpr>(x.t));
}
void Unparse(const OmpAffinityClause &x) {
- Walk(std::get<std::optional<OmpIteratorModifier>>(x.t), ":");
+ Walk(std::get<std::optional<OmpIterator>>(x.t), ":");
Walk(std::get<OmpObjectList>(x.t));
}
void Unparse(const OmpAlignedClause &x) {
@@ -2148,7 +2148,7 @@ class UnparseVisitor {
void Unparse(const OmpFromClause &x) {
auto &expect{
std::get<std::optional<std::list<OmpFromClause::Expectation>>>(x.t)};
- auto &iter{std::get<std::optional<std::list<OmpIteratorModifier>>>(x.t)};
+ auto &iter{std::get<std::optional<std::list<OmpIterator>>>(x.t)};
bool needComma{false};
if (expect) {
Walk(*expect);
@@ -2181,13 +2181,13 @@ class UnparseVisitor {
void Unparse(const OmpReductionClause &x) {
Walk(std::get<std::optional<OmpReductionClause::ReductionModifier>>(x.t),
",");
- Walk(std::get<OmpReductionOperator>(x.t));
+ Walk(std::get<OmpReductionIdentifier>(x.t));
Put(":");
Walk(std::get<OmpObjectList>(x.t));
}
void Unparse(const OmpDetachClause &x) { Walk(x.v); }
void Unparse(const OmpInReductionClause &x) {
- Walk(std::get<OmpReductionOperator>(x.t));
+ Walk(std::get<OmpReductionIdentifier>(x.t));
Put(":");
Walk(std::get<OmpObjectList>(x.t));
}
@@ -2253,7 +2253,7 @@ class UnparseVisitor {
void Unparse(const OmpToClause &x) {
auto &expect{
std::get<std::optional<std::list<OmpToClause::Expectation>>>(x.t)};
- auto &iter{std::get<std::optional<std::list<OmpIteratorModifier>>>(x.t)};
+ auto &iter{std::get<std::optional<std::list<OmpIterator>>>(x.t)};
bool needComma{false};
if (expect) {
Walk(*expect);
@@ -2635,7 +2635,7 @@ class UnparseVisitor {
}
void Unparse(const OpenMPDeclareReductionConstruct &x) {
Put("(");
- Walk(std::get<OmpReductionOperator>(x.t)), Put(" : ");
+ Walk(std::get<OmpReductionIdentifier>(x.t)), Put(" : ");
Walk(std::get<std::list<DeclarationTypeSpec>>(x.t), ","), Put(" : ");
Walk(std::get<OmpReductionCombiner>(x.t));
Put(")");
@@ -2900,8 +2900,8 @@ class UnparseVisitor {
WALK_NESTED_ENUM(
OmpLastprivateClause, LastprivateModifier) // OMP lastprivate-modifier
WALK_NESTED_ENUM(OmpScheduleModifierType, ModType) // OMP schedule-modifier
- WALK_NESTED_ENUM(OmpLinearModifier, Type) // OMP linear-modifier
- WALK_NESTED_ENUM(OmpTaskDependenceType, Type) // OMP task-dependence-type
+ WALK_NESTED_ENUM(OmpLinearModifier, Value) // OMP linear-modifier
+ WALK_NESTED_ENUM(OmpTaskDependenceType, Value) // OMP task-dependence-type
WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType) // OMP schedule-type
WALK_NESTED_ENUM(OmpDeviceClause, DeviceModifier) // OMP device modifier
WALK_NESTED_ENUM(OmpDeviceTypeClause, Type) // OMP DEVICE_TYPE
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 0b64a4a9801ccd..9cac652216fcf2 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -683,8 +683,7 @@ void OmpStructureChecker::CheckIteratorRange(
}
}
-void OmpStructureChecker::CheckIteratorModifier(
- const parser::OmpIteratorModifier &x) {
+void OmpStructureChecker::CheckIteratorModifier(const parser::OmpIterator &x) {
// Check if all iterator variables have integer type.
for (auto &&iterSpec : x.v) {
bool isInteger{true};
@@ -1859,21 +1858,21 @@ void OmpStructureChecker::CheckTargetUpdate() {
}
void OmpStructureChecker::CheckTaskDependenceType(
- const parser::OmpTaskDependenceType::Type &x) {
+ const parser::OmpTaskDependenceType::Value &x) {
// Common checks for task-dependence-type (DEPEND and UPDATE clauses).
unsigned version{context_.langOptions().OpenMPVersion};
unsigned since{0};
switch (x) {
- case parser::OmpTaskDependenceType::Type::In:
- case parser::OmpTaskDependenceType::Type::Out:
- case parser::OmpTaskDependenceType::Type::Inout:
+ case parser::OmpTaskDependenceType::Value::In:
+ case parser::OmpTaskDependenceType::Value::Out:
+ case parser::OmpTaskDependenceType::Value::Inout:
break;
- case parser::OmpTaskDependenceType::Type::Mutexinoutset:
- case parser::OmpTaskDependenceType::Type::Depobj:
+ case parser::OmpTaskDependenceType::Value::Mutexinoutset:
+ case parser::OmpTaskDependenceType::Value::Depobj:
since = 50;
break;
- case parser::OmpTaskDependenceType::Type::Inoutset:
+ case parser::OmpTaskDependenceType::Value::Inoutset:
since = 52;
break;
}
@@ -1888,14 +1887,14 @@ void OmpStructureChecker::CheckTaskDependenceType(
}
void OmpStructureChecker::CheckDependenceType(
- const parser::OmpDependenceType::Type &x) {
+ const parser::OmpDependenceType::Value &x) {
// Common checks for dependence-type (DEPEND and UPDATE clauses).
unsigned version{context_.langOptions().OpenMPVersion};
unsigned deprecatedIn{~0u};
switch (x) {
- case parser::OmpDependenceType::Type::Source:
- case parser::OmpDependenceType::Type::Sink:
+ case parser::OmpDependenceType::Value::Source:
+ case parser::OmpDependenceType::Value::Sink:
deprecatedIn = 52;
break;
}
@@ -2864,7 +2863,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) {
bool OmpStructureChecker::CheckReductionOperators(
const parser::OmpClause::Reduction &x) {
- const auto &definedOp{std::get<parser::OmpReductionOperator>(x.v.t)};
+ const auto &definedOp{std::get<parser::OmpReductionIdentifier>(x.v.t)};
bool ok = false;
common::visit(
common::visitors{
@@ -2929,7 +2928,7 @@ bool OmpStructureChecker::CheckIntrinsicOperator(
static bool IsReductionAllowedForType(
const parser::OmpClause::Reduction &x, const DeclTypeSpec &type) {
- const auto &definedOp{std::get<parser::OmpReductionOperator>(x.v.t)};
+ const auto &definedOp{std::get<parser::OmpReductionIdentifier>(x.v.t)};
// TODO: user defined reduction operators. Just allow everything for now.
bool ok{true};
@@ -3484,7 +3483,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_map);
using TypeMod = parser::OmpMapClause::TypeModifier;
using Type = parser::OmpMapClause::Type;
- using IterMod = parser::OmpIteratorModifier;
+ using IterMod = parser::OmpIterator;
unsigned version{context_.langOptions().OpenMPVersion};
if (auto commas{std::get<bool>(x.v.t)}; !commas && version >= 52) {
@@ -3637,7 +3636,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
if (taskDep) {
if (version == 50) {
invalidDep = taskDep->GetTaskDepType() ==
- parser::OmpTaskDependenceType::Type::Depobj;
+ parser::OmpTaskDependenceType::Value::Depobj;
}
} else {
invalidDep = true;
@@ -3684,7 +3683,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
}
}
}
- if (std::get<std::optional<parser::OmpIteratorModifier>>(taskDep->t)) {
+ if (std::get<std::optional<parser::OmpIterator>>(taskDep->t)) {
unsigned allowedInVersion{50};
if (version < allowedInVersion) {
context_.Say(GetContext().clauseSource,
@@ -3923,7 +3922,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Update &x) {
if (version >= 51) {
bool invalidDep{false};
if (taskType) {
- invalidDep = taskType->v == parser::OmpTaskDependenceType::Type::Depobj;
+ invalidDep =
+ taskType->v == parser::OmpTaskDependenceType::Value::Depobj;
} else {
invalidDep = true;
}
@@ -4058,7 +4058,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::From &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_from);
unsigned version{context_.langOptions().OpenMPVersion};
using ExpMod = parser::OmpFromClause::Expectation;
- using IterMod = parser::OmpIteratorModifier;
+ using IterMod = parser::OmpIterator;
if (auto &expMod{std::get<std::optional<std::list<ExpMod>>>(x.v.t)}) {
unsigned allowedInVersion{51};
@@ -4122,7 +4122,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::To &x) {
}
assert(GetContext().directive == llvm::omp::OMPD_target_update);
using ExpMod = parser::OmpFromClause::Expectation;
- using IterMod = parser::OmpIteratorModifier;
+ using IterMod = parser::OmpIterator;
if (auto &expMod{std::get<std::optional<std::list<ExpMod>>>(x.v.t)}) {
unsigned allowedInVersion{51};
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 429e451c463e42..df21ebac0f6d76 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -202,7 +202,7 @@ class OmpStructureChecker
void CheckWorkshareBlockStmts(const parser::Block &, parser::CharBlock);
void CheckIteratorRange(const parser::OmpIteratorSpecifier &x);
- void CheckIteratorModifier(const parser::OmpIteratorModifier &x);
+ void CheckIteratorModifier(const parser::OmpIterator &x);
void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct &x);
void CheckDoWhile(const parser::OpenMPLoopConstruct &x);
void CheckAssociatedLoopConstraints(const parser::OpenMPLoopConstruct &x);
@@ -218,8 +218,8 @@ class OmpStructureChecker
void CheckSIMDNest(const parser::OpenMPConstruct &x);
void CheckTargetNest(const parser::OpenMPConstruct &x);
void CheckTargetUpdate();
- void CheckDependenceType(const parser::OmpDependenceType::Type &x);
- void CheckTaskDependenceType(const parser::OmpTaskDependenceType::Type &x);
+ void CheckDependenceType(const parser::OmpDependenceType::Value &x);
+ void CheckTaskDependenceType(const parser::OmpTaskDependenceType::Value &x);
void CheckCancellationNest(
const parser::CharBlock &source, const parser::OmpCancelType::Type &type);
std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index a2059a1123b5e1..80e238f3476ac8 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -518,8 +518,8 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
}
bool Pre(const parser::OmpClause::Reduction &x) {
- const parser::OmpReductionOperator &opr{
- std::get<parser::OmpReductionOperator>(x.v.t)};
+ const parser::OmpReductionIdentifier &opr{
+ std::get<parser::OmpReductionIdentifier>(x.v.t)};
auto createDummyProcSymbol = [&](const parser::Name *name) {
// If name resolution failed, create a dummy symbol
const auto namePair{
diff --git a/flang/test/Parser/OpenMP/affinity-clause.f90 b/flang/test/Parser/OpenMP/affinity-clause.f90
index 804723cad7b2b3..5e9e0a2194babd 100644
--- a/flang/test/Parser/OpenMP/affinity-clause.f90
+++ b/flang/test/Parser/OpenMP/affinity-clause.f90
@@ -63,7 +63,7 @@ subroutine f02(x)
!PARSE-TREE: OmpBeginBlockDirective
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = task
!PARSE-TREE: | OmpClauseList -> OmpClause -> Affinity -> OmpAffinityClause
-!PARSE-TREE: | | OmpIteratorModifier -> OmpIteratorSpecifier
+!PARSE-TREE: | | OmpIterator -> OmpIteratorSpecifier
!PARSE-TREE: | | | TypeDeclarationStmt
!PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
!PARSE-TREE: | | | | EntityDecl
diff --git a/flang/test/Parser/OpenMP/depobj-construct.f90 b/flang/test/Parser/OpenMP/depobj-construct.f90
index 3de190c95bb734..51726a5adf99ec 100644
--- a/flang/test/Parser/OpenMP/depobj-construct.f90
+++ b/flang/test/Parser/OpenMP/depobj-construct.f90
@@ -15,7 +15,7 @@ subroutine f00
!PARSE-TREE: | Verbatim
!PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | OmpClause -> Depend -> OmpDependClause -> TaskDep
-!PARSE-TREE: | | OmpTaskDependenceType -> Type = In
+!PARSE-TREE: | | OmpTaskDependenceType -> Value = In
!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'y'
subroutine f01
@@ -31,7 +31,7 @@ subroutine f01
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct
!PARSE-TREE: | Verbatim
!PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'x'
-!PARSE-TREE: | OmpClause -> Update -> OmpUpdateClause -> OmpTaskDependenceType -> Type = Out
+!PARSE-TREE: | OmpClause -> Update -> OmpUpdateClause -> OmpTaskDependenceType -> Value = Out
subroutine f02
integer :: x
diff --git a/flang/test/Parser/OpenMP/from-clause.f90 b/flang/test/Parser/OpenMP/from-clause.f90
index 1dcca0b611dfb2..cff9c077c0a947 100644
--- a/flang/test/Parser/OpenMP/from-clause.f90
+++ b/flang/test/Parser/OpenMP/from-clause.f90
@@ -45,7 +45,7 @@ subroutine f02(x)
!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update
!PARSE-TREE: OmpClauseList -> OmpClause -> From -> OmpFromClause
!PARSE-TREE: | Expectation = Present
-!PARSE-TREE: | OmpIteratorModifier -> OmpIteratorSpecifier
+!PARSE-TREE: | OmpIterator -> OmpIteratorSpecifier
!PARSE-TREE: | | TypeDeclarationStmt
!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
!PARSE-TREE: | | | EntityDecl
@@ -74,7 +74,7 @@ subroutine f03(x)
!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update
!PARSE-TREE: OmpClauseList -> OmpClause -> From -> OmpFromClause
!PARSE-TREE: | Expectation = Present
-!PARSE-TREE: | OmpIteratorModifier -> OmpIteratorSpecifier
+!PARSE-TREE: | OmpIterator -> OmpIteratorSpecifier
!PARSE-TREE: | | TypeDeclarationStmt
!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
!PARSE-TREE: | | | EntityDecl
diff --git a/flang/test/Parser/OpenMP/in-reduction-clause.f90 b/flang/test/Parser/OpenMP/in-reduction-clause.f90
index 776ead3824b715..ab26ca2d9300fc 100644
--- a/flang/test/Parser/OpenMP/in-reduction-clause.f90
+++ b/flang/test/Parser/OpenMP/in-reduction-clause.f90
@@ -37,14 +37,14 @@ end subroutine omp_in_reduction_taskgroup
!PARSE-TREE-NEXT: OmpBeginBlockDirective
!PARSE-TREE-NEXT: OmpBlockDirective -> llvm::omp::Directive = task
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> InReduction -> OmpInReductionClause
-!PARSE-TREE-NEXT: OmpReductionOperator -> DefinedOperator -> IntrinsicOperator = Add
+!PARSE-TREE-NEXT: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add
!PARSE-TREE-NEXT: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'z'
!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = taskloop
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> InReduction -> OmpInReductionClause
-!PARSE-TREE-NEXT: OmpReductionOperator -> DefinedOperator -> IntrinsicOperator = Add
+!PARSE-TREE-NEXT: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add
!PARSE-TREE-NEXT: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'z'
subroutine omp_in_reduction_parallel()
@@ -74,6 +74,6 @@ end subroutine omp_in_reduction_parallel
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = taskloop simd
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> InReduction -> OmpInReductionClause
-!PARSE-TREE-NEXT: OmpReductionOperator -> DefinedOperator -> IntrinsicOperator = Add
+!PARSE-TREE-NEXT: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add
!PASRE-TREE-NEXT: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'z'
diff --git a/flang/test/Parser/OpenMP/map-modifiers.f90 b/flang/test/Parser/OpenMP/map-modifiers.f90
index 0c95f21c5e6a53..80c107c8c46fca 100644
--- a/flang/test/Parser/OpenMP/map-modifiers.f90
+++ b/flang/test/Parser/OpenMP/map-modifiers.f90
@@ -159,7 +159,7 @@ subroutine f10(x)
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
!PARSE-TREE: | | TypeModifier = Present
-!PARSE-TREE: | | OmpIteratorModifier -> OmpIteratorSpecifier
+!PARSE-TREE: | | OmpIterator -> OmpIteratorSpecifier
!PARSE-TREE: | | | TypeDeclarationStmt
!PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
!PARSE-TREE: | | | | EntityDecl
@@ -194,7 +194,7 @@ subroutine f11(x)
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
!PARSE-TREE: | | TypeModifier = Present
-!PARSE-TREE: | | OmpIteratorModifier -> OmpIteratorSpecifier
+!PARSE-TREE: | | OmpIterator -> OmpIteratorSpecifier
!PARSE-TREE: | | | TypeDeclarationStmt
!PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
!PARSE-TREE: | | | | EntityDecl
@@ -229,7 +229,7 @@ subroutine f12(x)
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
!PARSE-TREE: | | TypeModifier = Present
-!PARSE-TREE: | | OmpIteratorModifier -> OmpIteratorSpecifier
+!PARSE-TREE: | | OmpIterator -> OmpIteratorSpecifier
!PARSE-TREE: | | | TypeDeclarationStmt
!PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
!PARSE-TREE: | | | | EntityDecl
@@ -287,7 +287,7 @@ subroutine f90(x, y)
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
!PARSE-TREE: | | TypeModifier = Present
-!PARSE-TREE: | | OmpIteratorModifier -> OmpIteratorSpecifier
+!PARSE-TREE: | | OmpIterator -> OmpIteratorSpecifier
!PARSE-TREE: | | | TypeDeclarationStmt
!PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
!PARSE-TREE: | | | | EntityDecl
diff --git a/flang/test/Parser/OpenMP/reduction-modifier.f90 b/flang/test/Parser/OpenMP/reduction-modifier.f90
index d46aa709595925..4bba23bcf06118 100644
--- a/flang/test/Parser/OpenMP/reduction-modifier.f90
+++ b/flang/test/Parser/OpenMP/reduction-modifier.f90
@@ -10,7 +10,7 @@ subroutine foo()
! PARSE-TREE: | | | | OmpLoopDirective -> llvm::omp::Directive = do
! PARSE-TREE: | | | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause
! PARSE-TREE: | | | | | ReductionModifier = Task
-! PARSE-TREE: | | | | | OmpReductionOperator -> DefinedOperator -> IntrinsicOperator = Multiply
+! PARSE-TREE: | | | | | OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Multiply
! PARSE-TREE: | | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'j
!$omp do reduction (task, *: j)
do i = 1, 10
diff --git a/flang/test/Parser/OpenMP/target-update-to-clause.f90 b/flang/test/Parser/OpenMP/target-update-to-clause.f90
index 2702575847924b..bb57270fc0bf9c 100644
--- a/flang/test/Parser/OpenMP/target-update-to-clause.f90
+++ b/flang/test/Parser/OpenMP/target-update-to-clause.f90
@@ -45,7 +45,7 @@ subroutine f02(x)
!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update
!PARSE-TREE: OmpClauseList -> OmpClause -> To -> OmpToClause
!PARSE-TREE: | Expectation = Present
-!PARSE-TREE: | OmpIteratorModifier -> OmpIteratorSpecifier
+!PARSE-TREE: | OmpIterator -> OmpIteratorSpecifier
!PARSE-TREE: | | TypeDeclarationStmt
!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
!PARSE-TREE: | | | EntityDecl
@@ -74,7 +74,7 @@ subroutine f03(x)
!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update
!PARSE-TREE: OmpClauseList -> OmpClause -> To -> OmpToClause
!PARSE-TREE: | Expectation = Present
-!PARSE-TREE: | OmpIteratorModifier -> OmpIteratorSpecifier
+!PARSE-TREE: | OmpIterator -> OmpIteratorSpecifier
!PARSE-TREE: | | TypeDeclarationStmt
!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
!PARSE-TREE: | | | EntityDecl
>From e8bbc26e136993758c3a3197eed6b1924c6531d0 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 18 Nov 2024 08:47:24 -0600
Subject: [PATCH 2/8] [flang][OpenMP] Change clause modifier representation in
parser
The main issue to solve is that OpenMP modifiers can be specified
in any order, so the parser cannot expect any specific modifier at
a given position. To solve that, define modifier to be a union of
all allowable specific modifiers for a given clause.
Additionally, implement modifier descriptors: for each modifier the
corresponding descriptor contains a set of properties of the modifier
that allow a common set of semantic checks. Start with the syntactic
properties defined in the spec: Required, Unique, Exclusive, Ultimate,
and implement common checks to verify each of them.
OpenMP modifier overhaul: #2/3
---
.../flang/Semantics/openmp-modifiers.h | 391 ++++++++++++++++++
flang/lib/Semantics/CMakeLists.txt | 1 +
flang/lib/Semantics/openmp-modifiers.cpp | 146 +++++++
llvm/include/llvm/Frontend/OpenMP/OMP.h | 2 +
llvm/lib/Frontend/OpenMP/OMP.cpp | 5 +
5 files changed, 545 insertions(+)
create mode 100644 flang/include/flang/Semantics/openmp-modifiers.h
create mode 100644 flang/lib/Semantics/openmp-modifiers.cpp
diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h
new file mode 100644
index 00000000000000..6be582761ed687
--- /dev/null
+++ b/flang/include/flang/Semantics/openmp-modifiers.h
@@ -0,0 +1,391 @@
+//===-- flang/lib/Semantics/openmp-modifiers.h ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_SEMANTICS_OPENMP_MODIFIERS_H_
+#define FORTRAN_SEMANTICS_OPENMP_MODIFIERS_H_
+
+#include "flang/Common/enum-set.h"
+#include "flang/Parser/parse-tree.h"
+#include "flang/Semantics/semantics.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Frontend/OpenMP/OMP.h"
+
+#include <cassert>
+#include <map>
+#include <optional>
+#include <variant>
+
+namespace Fortran::semantics {
+
+// Ref: [5.2:58]
+//
+// Syntactic properties for Clauses, Arguments and Modifiers
+//
+// Inverse properties:
+// not Required -> Optional
+// not Unique -> Repeatable
+// not Exclusive -> Compatible
+// not Ultimate -> Free
+//
+// Clause defaults: Optional, Repeatable, Compatible, Free
+// Argument defaults: Required, Unique, Compatible, Free
+// Modifier defaults: Optional, Unique, Compatible, Free
+//
+// ---
+// Each modifier is used as either pre-modifier (i.e. modifier: item),
+// or post-modifier (i.e. item: modifier). The default is pre-.
+// Add an additional property that reflects the type of modifier.
+
+ENUM_CLASS(OmpProperty, Required, Unique, Exclusive, Ultimate, Post);
+using OmpProperties = common::EnumSet<OmpProperty, OmpProperty_enumSize>;
+using OmpClauses =
+ common::EnumSet<llvm::omp::Clause, llvm::omp::Clause_enumSize>;
+
+struct OmpModifierDescriptor {
+ // Modifier name for use in diagnostic messages.
+ const OmpProperties &props(unsigned version) const;
+ const OmpClauses &clauses(unsigned version) const;
+
+ const llvm::StringRef name;
+ // Version-dependent properties of the modifier.
+ const std::map<unsigned, OmpProperties> props_;
+ // Version-dependent set of clauses to which the modifier can apply.
+ const std::map<unsigned, OmpClauses> clauses_;
+};
+
+template <typename SpecificTy> const OmpModifierDescriptor &OmpGetDescriptor();
+
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDependenceType>();
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpIterator>();
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpLinearModifier>();
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpReductionIdentifier>();
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpTaskDependenceType>();
+
+// Explanation of terminology:
+//
+// A typical clause with modifier[s] looks like this (with parts that are
+// not relevant here removed):
+// struct OmpSomeClause {
+// struct Modifier {
+// using Variant = std::variant<Specific1, Specific2...>;
+// Variant u;
+// };
+// std::tuple<std::optional<std::list<Modifier>>, ...> t;
+// };
+//
+// The Speficic1, etc. refer to parser classes that represent modifiers,
+// e.g. OmpIterator or OmpTaskDependenceType. The Variant type contains
+// all modifiers that are allowed for a given clause. The Modifier class
+// is there to wrap the variant into the form that the parse tree visitor
+// expects, i.e. with traits, member "u", etc.
+//
+// To avoid ambiguities with the word "modifier" (e.g. is it "any modifier",
+// or "this specific modifier"?), the following code uses different terms:
+//
+// - UnionTy: refers to the nested "Modifier" class, i.e.
+// "OmpSomeClause::Modifier" in the example above.
+// - SpecificTy: refers to any of the alternatives, i.e. "Specific1" or
+// "Specific2".
+
+template <typename UnionTy>
+const OmpModifierDescriptor &OmpGetDescriptor(const UnionTy &modifier) {
+ return common::visit(
+ [](auto &&m) -> decltype(auto) {
+ using SpecificTy = llvm::remove_cvref_t<decltype(m)>;
+ return OmpGetDescriptor<SpecificTy>();
+ },
+ modifier.u);
+}
+
+/// Return the optional list of modifiers for a given `Omp[...]Clause`.
+/// Specifically, the parameter type `ClauseTy` is the class that OmpClause::v
+/// holds.
+template <typename ClauseTy>
+const std::optional<std::list<typename ClauseTy::Modifier>> &OmpGetModifiers(
+ const ClauseTy &clause) {
+ using UnionTy = typename ClauseTy::Modifier;
+ return std::get<std::optional<std::list<UnionTy>>>(clause.t);
+}
+
+namespace detail {
+/// Finds the first entry in the iterator range that holds the `SpecificTy`
+/// alternative, or the end iterator if it does not exist.
+/// The `SpecificTy` should be provided, the `UnionTy` is expected to be
+/// auto-deduced, e.g.
+/// const std::optional<std::list<X>> &modifiers = ...
+/// ... = findInRange<OmpIterator>(modifiers->begin(), modifiers->end());
+template <typename SpecificTy, typename UnionTy>
+typename std::list<UnionTy>::const_iterator findInRange(
+ typename std::list<UnionTy>::const_iterator begin,
+ typename std::list<UnionTy>::const_iterator end) {
+ for (auto it{begin}; it != end; ++it) {
+ if (std::holds_alternative<SpecificTy>(it->u)) {
+ return it;
+ }
+ }
+ return end;
+}
+} // namespace detail
+
+/// Finds the entry in the list that holds the `SpecificTy` alternative,
+/// and returns the pointer to that alternative. If such an entry does not
+/// exist, it returns nullptr.
+/// The list is assumed to contain at most one such item, with a check
+/// whether the condition is met.
+/// This function should only be called after the verification of modifier
+/// properties has been performed, since it will assert if multiple items
+/// are found.
+template <typename SpecificTy, typename UnionTy>
+const SpecificTy *OmpGetUniqueModifier(
+ const std::optional<std::list<UnionTy>> &modifiers) {
+ const SpecificTy *found{nullptr};
+ if (modifiers) {
+ auto end{modifiers->cend()};
+ // typename std::list<UnionTy>::iterator end{modifiers->end()};
+ auto at{detail::findInRange<SpecificTy, UnionTy>(modifiers->cbegin(), end)};
+ if (at != end) {
+ found = &std::get<SpecificTy>(at->u);
+#ifndef NDEBUG
+ auto another{
+ detail::findInRange<SpecificTy, UnionTy>(std::next(at), end)};
+ assert(another == end && "repeated modifier");
+#endif
+ }
+ }
+ return found;
+}
+
+namespace detail {
+template <typename T> constexpr const T *make_nullptr() {
+ return static_cast<const T *>(nullptr);
+}
+
+/// Helper function for verifying the Required property:
+/// For a specific SpecificTy, if SpecificTy is has the Required property,
+/// check if the list has an item that holds SpecificTy as an alternative.
+/// If SpecificTy does not have the Required property, ignore it.
+template <typename SpecificTy, typename UnionTy>
+bool verifyIfRequired(const SpecificTy *,
+ const std::optional<std::list<UnionTy>> &modifiers,
+ parser::CharBlock clauseSource, SemanticsContext &semaCtx) {
+ unsigned version{semaCtx.langOptions().OpenMPVersion};
+ const OmpModifierDescriptor &desc{OmpGetDescriptor<SpecificTy>()};
+ if (!desc.props(version).test(OmpProperty::Required)) {
+ // If the modifier is not required, there is nothing to do.
+ return true;
+ }
+ bool present{modifiers.has_value()};
+ present = present && llvm::any_of(*modifiers, [](auto &&m) {
+ return std::holds_alternative<SpecificTy>(m.u);
+ });
+ if (!present) {
+ semaCtx.Say(
+ clauseSource, "A %s modifier is required"_err_en_US, desc.name.str());
+ }
+ return present;
+}
+
+/// Helper function for verifying the Required property:
+/// Visit all specific types in UnionTy, and verify the Required property
+/// for each one of them.
+template <typename UnionTy, size_t... Idxs>
+bool verifyRequiredPack(const std::optional<std::list<UnionTy>> &modifiers,
+ parser::CharBlock clauseSource, SemanticsContext &semaCtx,
+ std::integer_sequence<size_t, Idxs...>) {
+ using VariantTy = typename UnionTy::Variant;
+ return (verifyIfRequired(
+ make_nullptr<std::variant_alternative_t<Idxs, VariantTy>>(),
+ modifiers, clauseSource, semaCtx) &&
+ ...);
+}
+
+/// Verify the Required property for the given list. Return true if the
+/// list is valid, or false otherwise.
+template <typename UnionTy>
+bool verifyRequired(const std::optional<std::list<UnionTy>> &modifiers,
+ parser::CharBlock clauseSource, SemanticsContext &semaCtx) {
+ using VariantTy = typename UnionTy::Variant;
+ return verifyRequiredPack(modifiers, clauseSource, semaCtx,
+ std::make_index_sequence<std::variant_size_v<VariantTy>>{});
+}
+
+/// Helper function to verify the Unique property.
+/// If SpecificTy has the Unique property, and an item is found holding
+/// it as the alternative, verify that none of the elements that follow
+/// hold SpecificTy as the alternative.
+template <typename UnionTy, typename SpecificTy>
+bool verifyIfUnique(const SpecificTy *,
+ typename std::list<UnionTy>::const_iterator specific,
+ typename std::list<UnionTy>::const_iterator end,
+ SemanticsContext &semaCtx) {
+ // `specific` is the location of the modifier of type SpecificTy.
+ assert(specific != end && "`specific` must be a valid location");
+
+ unsigned version{semaCtx.langOptions().OpenMPVersion};
+ const OmpModifierDescriptor &desc{OmpGetDescriptor<SpecificTy>()};
+ // Ultimate implies Unique.
+ if (!desc.props(version).test(OmpProperty::Unique) &&
+ !desc.props(version).test(OmpProperty::Ultimate)) {
+ return true;
+ }
+ if (std::next(specific) != end) {
+ auto next{
+ detail::findInRange<SpecificTy, UnionTy>(std::next(specific), end)};
+ if (next != end) {
+ semaCtx.Say(next->source, "A %s cannot occur multiple times"_err_en_US,
+ desc.name.str());
+ }
+ }
+ return true;
+}
+
+/// Verify the Unique property for the given list. Return true if the
+/// list is valid, or false otherwise.
+template <typename UnionTy>
+bool verifyUnique(const std::optional<std::list<UnionTy>> &modifiers,
+ parser::CharBlock clauseSource, SemanticsContext &semaCtx) {
+ if (!modifiers) {
+ return true;
+ }
+ bool result{true};
+ for (auto it{modifiers->cbegin()}, end{modifiers->cend()}; it != end; ++it) {
+ result = common::visit(
+ [&](auto &&m) {
+ return verifyIfUnique<UnionTy>(&m, it, end, semaCtx);
+ },
+ it->u) &&
+ result;
+ }
+ return result;
+}
+
+/// Verify the Ultimate property for the given list. Return true if the
+/// list is valid, or false otherwise.
+template <typename UnionTy>
+bool verifyUltimate(const std::optional<std::list<UnionTy>> &modifiers,
+ parser::CharBlock clauseSource, SemanticsContext &semaCtx) {
+ if (!modifiers || modifiers->size() <= 1) {
+ return true;
+ }
+ unsigned version{semaCtx.langOptions().OpenMPVersion};
+ bool result{true};
+ auto first{modifiers->cbegin()};
+ auto last{std::prev(modifiers->cend())};
+
+ // Any item that has the Ultimate property has to be either at the back
+ // or at the front of the list (depending on whether it's a pre- or a post-
+ // modifier).
+ // Walk over the list, and if a given item has the Ultimate property but is
+ // not at the right position, mark it as an error.
+ for (auto it{first}, end{modifiers->cend()}; it != end; ++it) {
+ result =
+ common::visit(
+ [&](auto &&m) {
+ using SpecificTy = llvm::remove_cvref_t<decltype(m)>;
+ const OmpModifierDescriptor &desc{OmpGetDescriptor<SpecificTy>()};
+ auto &props{desc.props(version)};
+
+ if (props.test(OmpProperty::Ultimate)) {
+ bool isPre = !props.test(OmpProperty::Post);
+ if (it == (isPre ? last : first)) {
+ // Skip, since this is the correct place for this modifier.
+ return true;
+ }
+ llvm::StringRef where{isPre ? "last" : "first"};
+ semaCtx.Say(it->source,
+ "The %s should be the %s modifier"_err_en_US,
+ desc.name.str(), where.str());
+ return false;
+ }
+ return true;
+ },
+ it->u) &&
+ result;
+ }
+ return result;
+}
+
+/// Verify the Exclusive property for the given list. Return true if the
+/// list is valid, or false otherwise.
+template <typename UnionTy>
+bool verifyExclusive(const std::optional<std::list<UnionTy>> &modifiers,
+ parser::CharBlock clauseSource, SemanticsContext &semaCtx) {
+ if (!modifiers || modifiers->size() <= 1) {
+ return true;
+ }
+ unsigned version{semaCtx.langOptions().OpenMPVersion};
+ const UnionTy &front{modifiers->front()};
+ const OmpModifierDescriptor &frontDesc{OmpGetDescriptor(front)};
+
+ auto second{std::next(modifiers->cbegin())};
+ auto end{modifiers->end()};
+
+ auto emitErrorMessage{[&](const UnionTy &excl, const UnionTy &other) {
+ const OmpModifierDescriptor &descExcl{OmpGetDescriptor(excl)};
+ const OmpModifierDescriptor &descOther{OmpGetDescriptor(other)};
+ parser::MessageFormattedText txt(
+ "An exclusive %s cannot be specified together with a modifier of a different type"_err_en_US,
+ descExcl.name.str());
+ parser::Message message(excl.source, txt);
+ message.Attach(
+ other.source, "%s provided here"_en_US, descOther.name.str());
+ semaCtx.Say(std::move(message));
+ }};
+
+ if (frontDesc.props(version).test(OmpProperty::Exclusive)) {
+ // If the first item has the Exclusive property, then check if there is
+ // another item in the rest of the list with a different SpecificTy as
+ // the alternative, and mark it as an error. This allows multiple Exclusive
+ // items to coexist as long as they hold the same SpecificTy.
+ bool result{true};
+ size_t frontIndex{front.u.index()};
+ for (auto it{second}; it != end; ++it) {
+ if (it->u.index() != frontIndex) {
+ emitErrorMessage(front, *it);
+ result = false;
+ break;
+ }
+ }
+ return result;
+ } else {
+ // If the first item does not have the Exclusive property, then check
+ // if there is an item in the rest of the list that is Exclusive, and
+ // mark it as an error if so.
+ bool result{true};
+ for (auto it{second}; it != end; ++it) {
+ const OmpModifierDescriptor &desc{OmpGetDescriptor(*it)};
+ if (desc.props(version).test(OmpProperty::Exclusive)) {
+ emitErrorMessage(*it, front);
+ result = false;
+ break;
+ }
+ }
+ return result;
+ }
+}
+} // namespace detail
+
+template <typename ClauseTy>
+bool OmpVerifyModifiers(const ClauseTy &clause, parser::CharBlock clauseSource,
+ SemanticsContext &semaCtx) {
+ auto &modifiers{OmpGetModifiers(clause)};
+ bool result{detail::verifyRequired(modifiers, clauseSource, semaCtx)};
+ result = detail::verifyUnique(modifiers, clauseSource, semaCtx) && result;
+ result = detail::verifyUltimate(modifiers, clauseSource, semaCtx) && result;
+ result = detail::verifyExclusive(modifiers, clauseSource, semaCtx) && result;
+ return result;
+}
+} // namespace Fortran::semantics
+
+#endif // FORTRAN_SEMANTICS_OPENMP_MODIFIERS_H_
diff --git a/flang/lib/Semantics/CMakeLists.txt b/flang/lib/Semantics/CMakeLists.txt
index 41406ecf50e004..7855ae7eed1387 100644
--- a/flang/lib/Semantics/CMakeLists.txt
+++ b/flang/lib/Semantics/CMakeLists.txt
@@ -31,6 +31,7 @@ add_flang_library(FortranSemantics
definable.cpp
expression.cpp
mod-file.cpp
+ openmp-modifiers.cpp
pointer-assignment.cpp
program-tree.cpp
resolve-labels.cpp
diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp
new file mode 100644
index 00000000000000..70ca988cddce59
--- /dev/null
+++ b/flang/lib/Semantics/openmp-modifiers.cpp
@@ -0,0 +1,146 @@
+//===-- flang/lib/Semantics/openmp-modifiers.cpp --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Semantics/openmp-modifiers.h"
+
+#include "flang/Parser/parse-tree.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Frontend/OpenMP/OMP.h"
+
+#include <algorithm>
+#include <cassert>
+#include <map>
+
+namespace Fortran::semantics {
+using namespace llvm::omp;
+
+/// Find the highest version that exists as a key in the given map,
+/// and is less than or equal to `version`.
+/// Account for "version" not being a value from getOpenMPVersions().
+template <typename ValueTy>
+static unsigned findVersion(
+ unsigned version, const std::map<unsigned, ValueTy> &map) {
+ llvm::ArrayRef<unsigned> versions{llvm::omp::getOpenMPVersions()};
+ assert(!versions.empty() && "getOpenMPVersions returned empty list");
+ version = std::clamp(version, versions.front(), versions.back());
+
+ // std::map is sorted with respect to keys, by default in the ascending
+ // order.
+ unsigned found{0};
+ for (auto &[v, _] : map) {
+ if (v <= version) {
+ found = v;
+ } else {
+ break;
+ }
+ }
+
+ assert(found != 0 && "cannot locate entry for version in map");
+ return found;
+}
+
+const OmpProperties &OmpModifierDescriptor::props(unsigned version) const {
+ return props_.at(findVersion(version, props_));
+}
+
+const OmpClauses &OmpModifierDescriptor::clauses(unsigned version) const {
+ return clauses_.at(findVersion(version, clauses_));
+}
+
+// Note: The intent for these functions is to have them be automatically-
+// generated in the future.
+
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDependenceType>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"dependence-type",
+ /*props=*/
+ {
+ {45, {OmpProperty::Required, OmpProperty::Ultimate}},
+ },
+ /*clauses=*/
+ {
+ {45, {Clause::OMPC_depend}},
+ {51, {Clause::OMPC_depend, Clause::OMPC_update}},
+ {52, {Clause::OMPC_doacross}},
+ },
+ };
+ return desc;
+}
+
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpIterator>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"iterator",
+ /*props=*/
+ {
+ {50, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {50, {Clause::OMPC_affinity, Clause::OMPC_depend}},
+ {51,
+ {Clause::OMPC_affinity, Clause::OMPC_depend, Clause::OMPC_from,
+ Clause::OMPC_map, Clause::OMPC_to}},
+ },
+ };
+ return desc;
+}
+
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpLinearModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"linear-modifier",
+ /*props=*/
+ {
+ {45, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {45, {Clause::OMPC_linear}},
+ },
+ };
+ return desc;
+}
+
+template <>
+const OmpModifierDescriptor &
+OmpGetDescriptor<parser::OmpReductionIdentifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"reduction-identifier",
+ /*props=*/
+ {
+ {45, {OmpProperty::Required, OmpProperty::Ultimate}},
+ },
+ /*clauses=*/
+ {
+ {45, {Clause::OMPC_reduction}},
+ {50,
+ {Clause::OMPC_in_reduction, Clause::OMPC_reduction,
+ Clause::OMPC_task_reduction}},
+ },
+ };
+ return desc;
+}
+
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpTaskDependenceType>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"task-dependence-type",
+ /*props=*/
+ {
+ {52, {OmpProperty::Required, OmpProperty::Ultimate}},
+ },
+ /*clauses=*/
+ {
+ {52, {Clause::OMPC_depend, Clause::OMPC_update}},
+ },
+ };
+ return desc;
+}
+} // namespace Fortran::semantics
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.h b/llvm/include/llvm/Frontend/OpenMP/OMP.h
index 0d79c071ecd30d..dd771ac3b416fb 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.h
@@ -47,6 +47,8 @@ static constexpr inline bool canHaveIterator(Clause C) {
}
}
+ArrayRef<unsigned> getOpenMPVersions();
+
/// Create a nicer version of a function name for humans to look at.
std::string prettifyFunctionName(StringRef FunctionName);
diff --git a/llvm/lib/Frontend/OpenMP/OMP.cpp b/llvm/lib/Frontend/OpenMP/OMP.cpp
index fdb09678d7a4cc..66e02b6ab58591 100644
--- a/llvm/lib/Frontend/OpenMP/OMP.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMP.cpp
@@ -193,6 +193,11 @@ bool isCombinedConstruct(Directive D) {
return !getLeafConstructs(D).empty() && !isCompositeConstruct(D);
}
+ArrayRef<unsigned> getOpenMPVersions() {
+ static unsigned Versions[]{45, 50, 51, 52, 60};
+ return Versions;
+}
+
std::string prettifyFunctionName(StringRef FunctionName) {
// Internalized functions have the right name, but simply a suffix.
if (FunctionName.ends_with(".internalized"))
>From fac6a8594643811418f37ee42fc1ac35bcc2a244 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 14 Nov 2024 07:29:59 -0600
Subject: [PATCH 3/8] [flang][OpenMP] Apply modifier representation to semantic
checks
Also, define helper macros in parse-tree.h.
Apply the new modifier representation to the DEFAULTMAP and REDUCTION
clauses, with testcases utilizing the new modifier validation.
OpenMP modifier overhaul: #3/3
---
flang/include/flang/Parser/dump-parse-tree.h | 8 +-
flang/include/flang/Parser/parse-tree.h | 49 +++++++++--
.../flang/Semantics/openmp-modifiers.h | 4 +
flang/lib/Lower/OpenMP/Clauses.cpp | 33 ++++----
flang/lib/Parser/openmp-parsers.cpp | 40 +++++----
flang/lib/Parser/unparse.cpp | 15 ++--
flang/lib/Semantics/check-omp-structure.cpp | 83 +++++++++++--------
flang/lib/Semantics/check-omp-structure.h | 3 +-
flang/lib/Semantics/openmp-modifiers.cpp | 33 ++++++++
flang/lib/Semantics/resolve-directives.cpp | 52 +++++++-----
.../test/Parser/OpenMP/defaultmap-clause.f90 | 8 +-
.../test/Parser/OpenMP/defaultmap-unparse.f90 | 16 ++--
.../test/Parser/OpenMP/reduction-modifier.f90 | 6 +-
.../Semantics/OpenMP/combined-constructs.f90 | 12 +--
.../OpenMP/defaultmap-clause-v45.f90 | 2 +-
15 files changed, 236 insertions(+), 128 deletions(-)
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index df5bf1d8d3200e..9c59ce520a31aa 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -509,9 +509,11 @@ class ParseTreeDumper {
NODE(parser, OmpDeclareMapperSpecifier)
NODE(parser, OmpDefaultClause)
NODE_ENUM(OmpDefaultClause, Type)
+ NODE(parser, OmpVariableCategory)
+ NODE_ENUM(OmpVariableCategory, Value)
NODE(parser, OmpDefaultmapClause)
NODE_ENUM(OmpDefaultmapClause, ImplicitBehavior)
- NODE_ENUM(OmpDefaultmapClause, VariableCategory)
+ NODE(OmpDefaultmapClause, Modifier)
NODE(parser, OmpDependenceType)
NODE_ENUM(OmpDependenceType, Value)
NODE(parser, OmpTaskDependenceType)
@@ -567,8 +569,10 @@ class ParseTreeDumper {
NODE_ENUM(OmpBindClause, Type)
NODE(parser, OmpProcBindClause)
NODE_ENUM(OmpProcBindClause, Type)
- NODE_ENUM(OmpReductionClause, ReductionModifier)
+ NODE(parser, OmpReductionModifier)
+ NODE_ENUM(OmpReductionModifier, Value)
NODE(parser, OmpReductionClause)
+ NODE(OmpReductionClause, Modifier)
NODE(parser, OmpInReductionClause)
NODE(parser, OmpReductionCombiner)
NODE(OmpReductionCombiner, FunctionCombiner)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index ef49a36578270e..5b28bcd4e21b80 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3440,6 +3440,16 @@ struct OmpObject {
WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
+#define MODIFIER_BOILERPLATE(...) \
+ struct Modifier { \
+ using Variant = std::variant<__VA_ARGS__>; \
+ UNION_CLASS_BOILERPLATE(Modifier); \
+ CharBlock source; \
+ Variant u; \
+ }
+
+#define MODIFIERS() std::optional<std::list<Modifier>>
+
inline namespace modifier {
// For uniformity, in all keyword modifiers the name of the type defined
// by ENUM_CLASS is "Value", e.g.
@@ -3505,12 +3515,20 @@ struct OmpLinearModifier {
// - | // since 4.5, until 5.2
// + | * | .AND. | .OR. | .EQV. | .NEQV. | // since 4.5
// MIN | MAX | IAND | IOR | IEOR // since 4.5
-//
struct OmpReductionIdentifier {
UNION_CLASS_BOILERPLATE(OmpReductionIdentifier);
std::variant<DefinedOperator, ProcedureDesignator> u;
};
+// Ref: [5.0:300-302], [5.1:332-334], [5.2:134-137]
+//
+// reduction-modifier ->
+// DEFAULT | INSCAN | TASK // since 5.0
+struct OmpReductionModifier {
+ ENUM_CLASS(Value, Default, Inscan, Task);
+ WRAPPER_CLASS_BOILERPLATE(OmpReductionModifier, Value);
+};
+
// Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321]
//
// task-dependence-type -> // "dependence-type" in 5.1 and before
@@ -3521,6 +3539,17 @@ struct OmpTaskDependenceType {
ENUM_CLASS(Value, In, Out, Inout, Inoutset, Mutexinoutset, Depobj)
WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Value);
};
+
+// Ref: [4.5:229-230], [5.0:324-325], [5.1:357-358], [5.2:161-162]
+//
+// variable-category ->
+// SCALAR | // since 4.5
+// AGGREGATE | ALLOCATABLE | POINTER | // since 5.0
+// ALL // since 5.2
+struct OmpVariableCategory {
+ ENUM_CLASS(Value, Aggregate, All, Allocatable, Pointer, Scalar)
+ WRAPPER_CLASS_BOILERPLATE(OmpVariableCategory, Value);
+};
} // namespace modifier
// --- Clauses
@@ -3578,8 +3607,8 @@ struct OmpDefaultmapClause {
TUPLE_CLASS_BOILERPLATE(OmpDefaultmapClause);
ENUM_CLASS(
ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None, Default)
- ENUM_CLASS(VariableCategory, All, Scalar, Aggregate, Allocatable, Pointer)
- std::tuple<ImplicitBehavior, std::optional<VariableCategory>> t;
+ MODIFIER_BOILERPLATE(OmpVariableCategory);
+ std::tuple<ImplicitBehavior, MODIFIERS()> t;
};
// 2.13.9 iteration-offset -> +/- non-negative-constant
@@ -3771,14 +3800,16 @@ struct OmpProcBindClause {
WRAPPER_CLASS_BOILERPLATE(OmpProcBindClause, Type);
};
-// 2.15.3.6 reduction-clause -> REDUCTION (reduction-identifier:
-// variable-name-list)
+// Ref: [4.5:201-207], [5.0:300-302], [5.1:332-334], [5.2:134-137]
+//
+// reduction-clause ->
+// REDUCTION(reduction-identifier: list) | // since 4.5
+// REDUCTION([reduction-modifier,]
+// reduction-identifier: list) // since 5.0
struct OmpReductionClause {
TUPLE_CLASS_BOILERPLATE(OmpReductionClause);
- ENUM_CLASS(ReductionModifier, Inscan, Task, Default)
- std::tuple<std::optional<ReductionModifier>, OmpReductionIdentifier,
- OmpObjectList>
- t;
+ MODIFIER_BOILERPLATE(OmpReductionModifier, OmpReductionIdentifier);
+ std::tuple<MODIFIERS(), OmpObjectList> t;
};
// 2.7.1 sched-modifier -> MONOTONIC | NONMONOTONIC | SIMD
diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h
index 6be582761ed687..28fec7314cd8b5 100644
--- a/flang/include/flang/Semantics/openmp-modifiers.h
+++ b/flang/include/flang/Semantics/openmp-modifiers.h
@@ -70,7 +70,11 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpLinearModifier>();
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpReductionIdentifier>();
template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpReductionModifier>();
+template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpTaskDependenceType>();
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpVariableCategory>();
// Explanation of terminology:
//
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 5e514b4ba9f0da..3e0a11bc785e33 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -12,6 +12,7 @@
#include "flang/Evaluate/expression.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Semantics/expression.h"
+#include "flang/Semantics/openmp-modifiers.h"
#include "flang/Semantics/symbol.h"
#include "llvm/Frontend/OpenMP/OMPConstants.h"
@@ -571,7 +572,8 @@ Defaultmap make(const parser::OmpClause::Defaultmap &inp,
);
CLAUSET_ENUM_CONVERT( //
- convert2, wrapped::VariableCategory, Defaultmap::VariableCategory,
+ convert2, parser::OmpVariableCategory::Value,
+ Defaultmap::VariableCategory,
// clang-format off
MS(Aggregate, Aggregate)
MS(All, All)
@@ -581,10 +583,11 @@ Defaultmap make(const parser::OmpClause::Defaultmap &inp,
// clang-format on
);
+ auto &mods{semantics::OmpGetModifiers(inp.v)};
auto &t0 = std::get<wrapped::ImplicitBehavior>(inp.v.t);
- auto &t1 = std::get<std::optional<wrapped::VariableCategory>>(inp.v.t);
+ auto *t1 = semantics::OmpGetUniqueModifier<parser::OmpVariableCategory>(mods);
- auto category = t1 ? convert2(*t1) : Defaultmap::VariableCategory::All;
+ auto category = t1 ? convert2(t1->v) : Defaultmap::VariableCategory::All;
return Defaultmap{{/*ImplicitBehavior=*/convert1(t0),
/*VariableCategory=*/category}};
}
@@ -1173,10 +1176,9 @@ ProcBind make(const parser::OmpClause::ProcBind &inp,
Reduction make(const parser::OmpClause::Reduction &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpReductionClause
- using wrapped = parser::OmpReductionClause;
-
CLAUSET_ENUM_CONVERT( //
- convert, wrapped::ReductionModifier, Reduction::ReductionModifier,
+ convert, parser::OmpReductionModifier::Value,
+ Reduction::ReductionModifier,
// clang-format off
MS(Inscan, Inscan)
MS(Task, Task)
@@ -1184,16 +1186,17 @@ Reduction make(const parser::OmpClause::Reduction &inp,
// clang-format on
);
- auto &t0 =
- std::get<std::optional<parser::OmpReductionClause::ReductionModifier>>(
- inp.v.t);
- auto &t1 = std::get<parser::OmpReductionIdentifier>(inp.v.t);
+ auto &mods = semantics::OmpGetModifiers(inp.v);
+ auto *t0 =
+ semantics::OmpGetUniqueModifier<parser::OmpReductionModifier>(mods);
+ auto *t1 =
+ semantics::OmpGetUniqueModifier<parser::OmpReductionIdentifier>(mods);
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
return Reduction{
{/*ReductionModifier=*/t0
- ? std::make_optional<Reduction::ReductionModifier>(convert(*t0))
+ ? std::make_optional<Reduction::ReductionModifier>(convert(t0->v))
: std::nullopt,
- /*ReductionIdentifiers=*/{makeReductionOperator(t1, semaCtx)},
+ /*ReductionIdentifiers=*/{makeReductionOperator(*t1, semaCtx)},
/*List=*/makeObjects(t2, semaCtx)}};
}
@@ -1314,10 +1317,12 @@ Permutation make(const parser::OmpClause::Permutation &inp,
TaskReduction make(const parser::OmpClause::TaskReduction &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpReductionClause
- auto &t0 = std::get<parser::OmpReductionIdentifier>(inp.v.t);
+ auto &mods = semantics::OmpGetModifiers(inp.v);
+ auto *t0 =
+ semantics::OmpGetUniqueModifier<parser::OmpReductionIdentifier>(mods);
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
return TaskReduction{
- {/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)},
+ {/*ReductionIdentifiers=*/{makeReductionOperator(*t0, semaCtx)},
/*List=*/makeObjects(t1, semaCtx)}};
}
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index b4d45873abb3ec..063201fc86ca41 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -229,6 +229,11 @@ TYPE_PARSER(construct<OmpLinearModifier>( //
TYPE_PARSER(construct<OmpReductionIdentifier>(Parser<DefinedOperator>{}) ||
construct<OmpReductionIdentifier>(Parser<ProcedureDesignator>{}))
+TYPE_PARSER(construct<OmpReductionModifier>(
+ "INSCAN" >> pure(OmpReductionModifier::Value::Inscan) ||
+ "TASK" >> pure(OmpReductionModifier::Value::Task) ||
+ "DEFAULT" >> pure(OmpReductionModifier::Value::Default)))
+
TYPE_PARSER(construct<OmpTaskDependenceType>(
"DEPOBJ" >> pure(OmpTaskDependenceType::Value::Depobj) ||
"IN"_id >> pure(OmpTaskDependenceType::Value::In) ||
@@ -237,6 +242,22 @@ TYPE_PARSER(construct<OmpTaskDependenceType>(
"MUTEXINOUTSET" >> pure(OmpTaskDependenceType::Value::Mutexinoutset) ||
"OUT" >> pure(OmpTaskDependenceType::Value::Out)))
+// This could be auto-generated.
+TYPE_PARSER(sourced(construct<OmpReductionClause::Modifier>(sourced(
+ construct<OmpReductionClause::Modifier>(Parser<OmpReductionModifier>{}) ||
+ construct<OmpReductionClause::Modifier>(
+ Parser<OmpReductionIdentifier>{})))))
+
+TYPE_PARSER(construct<OmpVariableCategory>(
+ "AGGREGATE" >> pure(OmpVariableCategory::Value::Aggregate) ||
+ "ALL"_id >> pure(OmpVariableCategory::Value::All) ||
+ "ALLOCATABLE" >> pure(OmpVariableCategory::Value::Allocatable) ||
+ "POINTER" >> pure(OmpVariableCategory::Value::Pointer) ||
+ "SCALAR" >> pure(OmpVariableCategory::Value::Scalar)))
+
+TYPE_PARSER(sourced(construct<OmpDefaultmapClause::Modifier>(
+ Parser<OmpVariableCategory>{})))
+
// --- Parsers for clauses --------------------------------------------
// [5.0] 2.10.1 affinity([aff-modifier:] locator-list)
@@ -309,16 +330,7 @@ TYPE_PARSER(construct<OmpDefaultmapClause>(
pure(OmpDefaultmapClause::ImplicitBehavior::Firstprivate) ||
"NONE" >> pure(OmpDefaultmapClause::ImplicitBehavior::None) ||
"DEFAULT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Default)),
- maybe(":" >>
- construct<OmpDefaultmapClause::VariableCategory>(
- "ALL"_id >> pure(OmpDefaultmapClause::VariableCategory::All) ||
- "SCALAR" >> pure(OmpDefaultmapClause::VariableCategory::Scalar) ||
- "AGGREGATE" >>
- pure(OmpDefaultmapClause::VariableCategory::Aggregate) ||
- "ALLOCATABLE" >>
- pure(OmpDefaultmapClause::VariableCategory::Allocatable) ||
- "POINTER" >>
- pure(OmpDefaultmapClause::VariableCategory::Pointer)))))
+ maybe(":" >> nonemptyList(Parser<OmpDefaultmapClause::Modifier>{}))))
// 2.7.1 SCHEDULE ([modifier1 [, modifier2]:]kind[, chunk_size])
// Modifier -> MONITONIC | NONMONOTONIC | SIMD
@@ -375,12 +387,8 @@ TYPE_PARSER(construct<OmpIfClause>(
scalarLogicalExpr))
TYPE_PARSER(construct<OmpReductionClause>(
- maybe(
- ("INSCAN" >> pure(OmpReductionClause::ReductionModifier::Inscan) ||
- "TASK" >> pure(OmpReductionClause::ReductionModifier::Task) ||
- "DEFAULT" >> pure(OmpReductionClause::ReductionModifier::Default)) /
- ","),
- Parser<OmpReductionIdentifier>{} / ":", Parser<OmpObjectList>{}))
+ maybe(nonemptyList(Parser<OmpReductionClause::Modifier>{}) / ":"),
+ Parser<OmpObjectList>{}))
// OMP 5.0 2.19.5.6 IN_REDUCTION (reduction-identifier: variable-name-list)
TYPE_PARSER(construct<OmpInReductionClause>(
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index b2a0256cb58d0c..e06f4dea80f488 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2179,10 +2179,8 @@ class UnparseVisitor {
Walk(":", x.step);
}
void Unparse(const OmpReductionClause &x) {
- Walk(std::get<std::optional<OmpReductionClause::ReductionModifier>>(x.t),
- ",");
- Walk(std::get<OmpReductionIdentifier>(x.t));
- Put(":");
+ using Modifier = OmpReductionClause::Modifier;
+ Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ":");
Walk(std::get<OmpObjectList>(x.t));
}
void Unparse(const OmpDetachClause &x) { Walk(x.v); }
@@ -2246,9 +2244,9 @@ class UnparseVisitor {
Walk(std::get<OmpObjectList>(x.t));
}
void Unparse(const OmpDefaultmapClause &x) {
+ using Modifier = OmpDefaultmapClause::Modifier;
Walk(std::get<OmpDefaultmapClause::ImplicitBehavior>(x.t));
- Walk(":",
- std::get<std::optional<OmpDefaultmapClause::VariableCategory>>(x.t));
+ Walk(":", std::get<std::optional<std::list<Modifier>>>(x.t));
}
void Unparse(const OmpToClause &x) {
auto &expect{
@@ -2896,7 +2894,7 @@ class UnparseVisitor {
WALK_NESTED_ENUM(OmpProcBindClause, Type) // OMP PROC_BIND
WALK_NESTED_ENUM(OmpDefaultClause, Type) // OMP DEFAULT
WALK_NESTED_ENUM(OmpDefaultmapClause, ImplicitBehavior) // OMP DEFAULTMAP
- WALK_NESTED_ENUM(OmpDefaultmapClause, VariableCategory) // OMP DEFAULTMAP
+ WALK_NESTED_ENUM(OmpVariableCategory, Value) // OMP variable-category
WALK_NESTED_ENUM(
OmpLastprivateClause, LastprivateModifier) // OMP lastprivate-modifier
WALK_NESTED_ENUM(OmpScheduleModifierType, ModType) // OMP schedule-modifier
@@ -2905,8 +2903,7 @@ class UnparseVisitor {
WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType) // OMP schedule-type
WALK_NESTED_ENUM(OmpDeviceClause, DeviceModifier) // OMP device modifier
WALK_NESTED_ENUM(OmpDeviceTypeClause, Type) // OMP DEVICE_TYPE
- WALK_NESTED_ENUM(
- OmpReductionClause, ReductionModifier) // OMP reduction-modifier
+ WALK_NESTED_ENUM(OmpReductionModifier, Value) // OMP reduction-modifier
WALK_NESTED_ENUM(OmpFromClause, Expectation) // OMP motion-expectation
WALK_NESTED_ENUM(OmpIfClause, DirectiveNameModifier) // OMP directive-modifier
WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 9cac652216fcf2..079d0fd17bfac1 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -11,6 +11,7 @@
#include "flang/Evaluate/check-expression.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Semantics/expression.h"
+#include "flang/Semantics/openmp-modifiers.h"
#include "flang/Semantics/tools.h"
#include <variant>
@@ -195,7 +196,7 @@ bool OmpStructureChecker::CheckAllowedClause(llvmOmpClause clause) {
if (!llvm::omp::isAllowedClauseForDirective(dir, clause, version)) {
unsigned allowedInVersion{[&] {
- for (unsigned v : {45, 50, 51, 52, 60}) {
+ for (unsigned v : llvm::omp::getOpenMPVersions()) {
if (v <= version) {
continue;
}
@@ -979,12 +980,14 @@ void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &x) {
// constructs inside LOOP may add the relevant information. Scan reduction is
// supported only in loop constructs, so same checks are not applicable to
// other directives.
+ using ReductionModifier = parser::OmpReductionModifier;
for (const auto &clause : clauseList.v) {
if (const auto *reductionClause{
std::get_if<parser::OmpClause::Reduction>(&clause.u)}) {
- const auto &maybeModifier{
- std::get<std::optional<ReductionModifier>>(reductionClause->v.t)};
- if (maybeModifier && *maybeModifier == ReductionModifier::Inscan) {
+ auto &modifiers{OmpGetModifiers(reductionClause->v)};
+ auto *maybeModifier{OmpGetUniqueModifier<ReductionModifier>(modifiers)};
+ if (maybeModifier &&
+ maybeModifier->v == ReductionModifier::Value::Inscan) {
const auto &objectList{
std::get<parser::OmpObjectList>(reductionClause->v.t)};
auto checkReductionSymbolInScan = [&](const parser::Name *name) {
@@ -2850,20 +2853,27 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Destroy &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_reduction);
- if (CheckReductionOperators(x)) {
- CheckReductionTypeList(x);
- }
- if (const auto &maybeModifier{
- std::get<std::optional<ReductionModifier>>(x.v.t)}) {
- const ReductionModifier modifier{*maybeModifier};
- CheckReductionModifier(modifier);
+ if (OmpVerifyModifiers(x.v, GetContext().clauseSource, context_)) {
+ if (CheckReductionOperators(x)) {
+ CheckReductionTypeList(x);
+ }
+ auto &modifiers{OmpGetModifiers(x.v)};
+ using ReductionModifier = parser::OmpReductionModifier;
+ if (auto *maybeModifier{
+ OmpGetUniqueModifier<ReductionModifier>(modifiers)}) {
+ CheckReductionModifier(*maybeModifier);
+ }
}
}
bool OmpStructureChecker::CheckReductionOperators(
const parser::OmpClause::Reduction &x) {
-
- const auto &definedOp{std::get<parser::OmpReductionIdentifier>(x.v.t)};
+ auto &modifiers{OmpGetModifiers(x.v)};
+ const auto *definedOp{
+ OmpGetUniqueModifier<parser::OmpReductionIdentifier>(modifiers)};
+ if (!definedOp) {
+ return false;
+ }
bool ok = false;
common::visit(
common::visitors{
@@ -2896,7 +2906,7 @@ bool OmpStructureChecker::CheckReductionOperators(
}
},
},
- definedOp.u);
+ definedOp->u);
return ok;
}
@@ -2928,7 +2938,12 @@ bool OmpStructureChecker::CheckIntrinsicOperator(
static bool IsReductionAllowedForType(
const parser::OmpClause::Reduction &x, const DeclTypeSpec &type) {
- const auto &definedOp{std::get<parser::OmpReductionIdentifier>(x.v.t)};
+ auto &modifiers{OmpGetModifiers(x.v)};
+ const auto *definedOp{
+ OmpGetUniqueModifier<parser::OmpReductionIdentifier>(modifiers)};
+ if (!definedOp) {
+ return false;
+ }
// TODO: user defined reduction operators. Just allow everything for now.
bool ok{true};
@@ -3002,7 +3017,7 @@ static bool IsReductionAllowedForType(
}
},
},
- definedOp.u);
+ definedOp->u);
return ok;
}
@@ -3035,8 +3050,9 @@ void OmpStructureChecker::CheckReductionTypeList(
}
void OmpStructureChecker::CheckReductionModifier(
- const ReductionModifier &modifier) {
- if (modifier == ReductionModifier::Default) {
+ const parser::OmpReductionModifier &modifier) {
+ using ReductionModifier = parser::OmpReductionModifier;
+ if (modifier.v == ReductionModifier::Value::Default) {
// The default one is always ok.
return;
}
@@ -3049,7 +3065,7 @@ void OmpStructureChecker::CheckReductionModifier(
context_.Say(GetContext().clauseSource,
"REDUCTION modifier on LOOP directive must be DEFAULT"_err_en_US);
}
- if (modifier == ReductionModifier::Task) {
+ if (modifier.v == ReductionModifier::Value::Task) {
// "Task" is only allowed on worksharing or "parallel" directive.
static llvm::omp::Directive worksharing[]{
llvm::omp::Directive::OMPD_do, llvm::omp::Directive::OMPD_scope,
@@ -3065,7 +3081,7 @@ void OmpStructureChecker::CheckReductionModifier(
"Modifier 'TASK' on REDUCTION clause is only allowed with "
"PARALLEL or worksharing directive"_err_en_US);
}
- } else if (modifier == ReductionModifier::Inscan) {
+ } else if (modifier.v == ReductionModifier::Value::Inscan) {
// "Inscan" is only allowed on worksharing-loop, worksharing-loop simd,
// or "simd" directive.
// The worksharing-loop directives are OMPD_do and OMPD_for. Only the
@@ -3382,28 +3398,27 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) {
ThisVersion(version), TryVersion(50));
}
}
- using VariableCategory = parser::OmpDefaultmapClause::VariableCategory;
- auto maybeCategory{std::get<std::optional<VariableCategory>>(x.v.t)};
- if (!maybeCategory) {
- if (version <= 45) {
- context_.Say(GetContext().clauseSource,
- "The DEFAULTMAP clause requires a variable-category SCALAR in %s, %s"_warn_en_US,
- ThisVersion(version), TryVersion(50));
- }
- } else {
- VariableCategory category{*maybeCategory};
+ if (!OmpVerifyModifiers(x.v, GetContext().clauseSource, context_)) {
+ // If modifier verification fails, return early.
+ return;
+ }
+ auto &modifiers{OmpGetModifiers(x.v)};
+ auto *maybeCategory{
+ OmpGetUniqueModifier<parser::OmpVariableCategory>(modifiers)};
+ if (maybeCategory) {
+ using VariableCategory = parser::OmpVariableCategory;
+ VariableCategory::Value category{maybeCategory->v};
unsigned tryVersion{0};
- if (version <= 45 && category != VariableCategory::Scalar) {
+ if (version <= 45 && category != VariableCategory::Value::Scalar) {
tryVersion = 50;
}
- if (version < 52 && category == VariableCategory::All) {
+ if (version < 52 && category == VariableCategory::Value::All) {
tryVersion = 52;
}
if (tryVersion) {
context_.Say(GetContext().clauseSource,
"%s is not allowed in %s, %s"_warn_en_US,
- parser::ToUpperCaseLetters(
- parser::OmpDefaultmapClause::EnumToString(category)),
+ parser::ToUpperCaseLetters(VariableCategory::EnumToString(category)),
ThisVersion(version), TryVersion(tryVersion));
}
}
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index df21ebac0f6d76..af61215ecc403d 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -70,7 +70,6 @@ class OmpStructureChecker
) {
}
using llvmOmpClause = const llvm::omp::Clause;
- using ReductionModifier = parser::OmpReductionClause::ReductionModifier;
void Enter(const parser::OpenMPConstruct &);
void Leave(const parser::OpenMPConstruct &);
@@ -227,7 +226,7 @@ class OmpStructureChecker
bool CheckIntrinsicOperator(
const parser::DefinedOperator::IntrinsicOperator &);
void CheckReductionTypeList(const parser::OmpClause::Reduction &);
- void CheckReductionModifier(const ReductionModifier &);
+ void CheckReductionModifier(const parser::OmpReductionModifier &);
void CheckMasterNesting(const parser::OpenMPBlockConstruct &x);
void ChecksOnOrderedAsBlock();
void CheckBarrierNesting(const parser::OpenMPSimpleStandaloneConstruct &x);
diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp
index 70ca988cddce59..a425eec76a36d8 100644
--- a/flang/lib/Semantics/openmp-modifiers.cpp
+++ b/flang/lib/Semantics/openmp-modifiers.cpp
@@ -128,6 +128,22 @@ OmpGetDescriptor<parser::OmpReductionIdentifier>() {
return desc;
}
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpReductionModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"reduction-modifier",
+ /*props=*/
+ {
+ {45, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {45, {Clause::OMPC_reduction}},
+ },
+ };
+ return desc;
+}
+
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpTaskDependenceType>() {
static const OmpModifierDescriptor desc{
@@ -143,4 +159,21 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpTaskDependenceType>() {
};
return desc;
}
+
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpVariableCategory>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"variable-category",
+ /*props=*/
+ {
+ {45, {OmpProperty::Required, OmpProperty::Unique}},
+ {50, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {45, {Clause::OMPC_defaultmap}},
+ },
+ };
+ return desc;
+}
} // namespace Fortran::semantics
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 80e238f3476ac8..c75808a8963b3f 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -19,6 +19,7 @@
#include "flang/Parser/parse-tree.h"
#include "flang/Parser/tools.h"
#include "flang/Semantics/expression.h"
+#include "flang/Semantics/openmp-modifiers.h"
#include "flang/Semantics/symbol.h"
#include "flang/Semantics/tools.h"
#include <list>
@@ -518,8 +519,14 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
}
bool Pre(const parser::OmpClause::Reduction &x) {
- const parser::OmpReductionIdentifier &opr{
- std::get<parser::OmpReductionIdentifier>(x.v.t)};
+ const auto &objList{std::get<parser::OmpObjectList>(x.v.t)};
+ ResolveOmpObjectList(objList, Symbol::Flag::OmpReduction);
+
+ auto &modifiers{OmpGetModifiers(x.v)};
+ if (!modifiers) {
+ return false;
+ }
+
auto createDummyProcSymbol = [&](const parser::Name *name) {
// If name resolution failed, create a dummy symbol
const auto namePair{
@@ -530,30 +537,35 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
}
name->symbol = &newSymbol;
};
- if (const auto *procD{parser::Unwrap<parser::ProcedureDesignator>(opr.u)}) {
- if (const auto *name{parser::Unwrap<parser::Name>(procD->u)}) {
- if (!name->symbol) {
- if (!ResolveName(name)) {
- createDummyProcSymbol(name);
+
+ for (auto &mod : *modifiers) {
+ if (!std::holds_alternative<parser::OmpReductionIdentifier>(mod.u)) {
+ continue;
+ }
+ auto &opr{std::get<parser::OmpReductionIdentifier>(mod.u)};
+ if (auto *procD{parser::Unwrap<parser::ProcedureDesignator>(opr.u)}) {
+ if (auto *name{parser::Unwrap<parser::Name>(procD->u)}) {
+ if (!name->symbol) {
+ if (!ResolveName(name)) {
+ createDummyProcSymbol(name);
+ }
}
}
- }
- if (const auto *procRef{
- parser::Unwrap<parser::ProcComponentRef>(procD->u)}) {
- if (!procRef->v.thing.component.symbol) {
- if (!ResolveName(&procRef->v.thing.component)) {
- createDummyProcSymbol(&procRef->v.thing.component);
+ if (auto *procRef{parser::Unwrap<parser::ProcComponentRef>(procD->u)}) {
+ if (!procRef->v.thing.component.symbol) {
+ if (!ResolveName(&procRef->v.thing.component)) {
+ createDummyProcSymbol(&procRef->v.thing.component);
+ }
}
}
}
}
- const auto &objList{std::get<parser::OmpObjectList>(x.v.t)};
- ResolveOmpObjectList(objList, Symbol::Flag::OmpReduction);
- using ReductionModifier = parser::OmpReductionClause::ReductionModifier;
- const auto &maybeModifier{
- std::get<std::optional<ReductionModifier>>(x.v.t)};
- if (maybeModifier && *maybeModifier == ReductionModifier::Inscan) {
- ResolveOmpObjectList(objList, Symbol::Flag::OmpInScanReduction);
+ using ReductionModifier = parser::OmpReductionModifier;
+ if (auto *maybeModifier{
+ OmpGetUniqueModifier<ReductionModifier>(modifiers)}) {
+ if (maybeModifier->v == ReductionModifier::Value::Inscan) {
+ ResolveOmpObjectList(objList, Symbol::Flag::OmpInScanReduction);
+ }
}
return false;
}
diff --git a/flang/test/Parser/OpenMP/defaultmap-clause.f90 b/flang/test/Parser/OpenMP/defaultmap-clause.f90
index 6f018ffe8561cd..dc036aedcd003e 100644
--- a/flang/test/Parser/OpenMP/defaultmap-clause.f90
+++ b/flang/test/Parser/OpenMP/defaultmap-clause.f90
@@ -31,7 +31,7 @@ subroutine f01
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
!PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause
!PARSE-TREE: | | ImplicitBehavior = Firstprivate
-!PARSE-TREE: | | VariableCategory = Aggregate
+!PARSE-TREE: | | Modifier -> OmpVariableCategory -> Value = Aggregate
subroutine f02
!$omp target defaultmap(alloc: all)
@@ -47,7 +47,7 @@ subroutine f02
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
!PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause
!PARSE-TREE: | | ImplicitBehavior = Alloc
-!PARSE-TREE: | | VariableCategory = All
+!PARSE-TREE: | | Modifier -> OmpVariableCategory -> Value = All
! Both "all" and "allocatable" are valid, and "all" is a prefix of
! "allocatable". Make sure we parse this correctly.
@@ -65,7 +65,7 @@ subroutine f03
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
!PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause
!PARSE-TREE: | | ImplicitBehavior = Alloc
-!PARSE-TREE: | | VariableCategory = Allocatable
+!PARSE-TREE: | | Modifier -> OmpVariableCategory -> Value = Allocatable
subroutine f04
!$omp target defaultmap(tofrom: scalar)
@@ -81,4 +81,4 @@ subroutine f04
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
!PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause
!PARSE-TREE: | | ImplicitBehavior = Tofrom
-!PARSE-TREE: | | VariableCategory = Scalar
+!PARSE-TREE: | | Modifier -> OmpVariableCategory -> Value = Scalar
diff --git a/flang/test/Parser/OpenMP/defaultmap-unparse.f90 b/flang/test/Parser/OpenMP/defaultmap-unparse.f90
index e7333b02bc8f6b..bbbb6fc938326a 100644
--- a/flang/test/Parser/OpenMP/defaultmap-unparse.f90
+++ b/flang/test/Parser/OpenMP/defaultmap-unparse.f90
@@ -38,7 +38,7 @@ program main
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
!PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause
!PARSE-TREE: ImplicitBehavior = Tofrom
-!PARSE-TREE: VariableCategory = Scalar
+!PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Scalar
!CHECK: !$omp target defaultmap(alloc:scalar)
!$omp target defaultmap(alloc:scalar)
@@ -50,7 +50,7 @@ program main
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
!PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause
!PARSE-TREE: ImplicitBehavior = Alloc
-!PARSE-TREE: VariableCategory = Scalar
+!PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Scalar
!CHECK: !$omp target defaultmap(none)
!$omp target defaultmap(none)
@@ -73,7 +73,7 @@ program main
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
!PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause
!PARSE-TREE: ImplicitBehavior = None
-!PARSE-TREE: VariableCategory = Scalar
+!PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Scalar
!CHECK: !$omp target defaultmap(to:scalar)
!$omp target defaultmap(to:scalar)
@@ -85,7 +85,7 @@ program main
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
!PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause
!PARSE-TREE: ImplicitBehavior = To
-!PARSE-TREE: VariableCategory = Scalar
+!PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Scalar
!CHECK: !$omp target defaultmap(firstprivate:scalar)
!$omp target defaultmap(firstprivate:scalar)
@@ -97,7 +97,7 @@ program main
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
!PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause
!PARSE-TREE: ImplicitBehavior = Firstprivate
-!PARSE-TREE: VariableCategory = Scalar
+!PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Scalar
!CHECK: !$omp target defaultmap(tofrom:aggregate)
!$omp target defaultmap(tofrom:aggregate)
@@ -112,7 +112,7 @@ program main
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
!PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause
!PARSE-TREE: ImplicitBehavior = Tofrom
-!PARSE-TREE: VariableCategory = Aggregate
+!PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Aggregate
!CHECK: !$omp target defaultmap(tofrom:allocatable)
!$omp target defaultmap(tofrom:allocatable)
@@ -124,7 +124,7 @@ program main
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
!PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause
!PARSE-TREE: ImplicitBehavior = Tofrom
-!PARSE-TREE: VariableCategory = Allocatable
+!PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Allocatable
!CHECK: !$omp target defaultmap(default:pointer)
!$omp target defaultmap(default:pointer)
@@ -138,7 +138,7 @@ program main
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
!PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause
!PARSE-TREE: ImplicitBehavior = Default
-!PARSE-TREE: VariableCategory = Pointer
+!PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Pointer
end program main
!CHECK-LABEL: end program main
diff --git a/flang/test/Parser/OpenMP/reduction-modifier.f90 b/flang/test/Parser/OpenMP/reduction-modifier.f90
index 4bba23bcf06118..64cd452e839e73 100644
--- a/flang/test/Parser/OpenMP/reduction-modifier.f90
+++ b/flang/test/Parser/OpenMP/reduction-modifier.f90
@@ -4,13 +4,13 @@
subroutine foo()
integer :: i, j
j = 0
-! CHECK: !$OMP DO REDUCTION(TASK,*:j)
+! CHECK: !$OMP DO REDUCTION(TASK, *:j)
! PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct
! PARSE-TREE: | | | OmpBeginLoopDirective
! PARSE-TREE: | | | | OmpLoopDirective -> llvm::omp::Directive = do
! PARSE-TREE: | | | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause
-! PARSE-TREE: | | | | | ReductionModifier = Task
-! PARSE-TREE: | | | | | OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Multiply
+! PARSE-TREE: | | | | | Modifier -> OmpReductionModifier -> Value = Task
+! PARSE-TREE: | | | | | Modifier -> OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Multiply
! PARSE-TREE: | | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'j
!$omp do reduction (task, *: j)
do i = 1, 10
diff --git a/flang/test/Semantics/OpenMP/combined-constructs.f90 b/flang/test/Semantics/OpenMP/combined-constructs.f90
index 38b0d090e441d5..25893a47860f46 100644
--- a/flang/test/Semantics/OpenMP/combined-constructs.f90
+++ b/flang/test/Semantics/OpenMP/combined-constructs.f90
@@ -33,7 +33,7 @@ program main
enddo
!$omp end target parallel
- !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50
+ !ERROR: A variable-category modifier is required
!$omp target parallel defaultmap(tofrom)
do i = 1, N
a(i) = 3.14
@@ -80,7 +80,7 @@ program main
enddo
!$omp end target parallel do
- !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50
+ !ERROR: A variable-category modifier is required
!$omp target parallel do defaultmap(tofrom)
do i = 1, N
a(i) = 3.14
@@ -140,7 +140,7 @@ program main
enddo
!$omp end target teams
- !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50
+ !ERROR: A variable-category modifier is required
!$omp target teams defaultmap(tofrom)
do i = 1, N
a(i) = 3.14
@@ -240,7 +240,7 @@ program main
enddo
!$omp end target teams distribute
- !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50
+ !ERROR: A variable-category modifier is required
!$omp target teams distribute defaultmap(tofrom)
do i = 1, N
a(i) = 3.14
@@ -333,7 +333,7 @@ program main
enddo
!$omp end target teams distribute parallel do
- !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50
+ !ERROR: A variable-category modifier is required
!$omp target teams distribute parallel do defaultmap(tofrom)
do i = 1, N
a(i) = 3.14
@@ -433,7 +433,7 @@ program main
enddo
!$omp end target teams distribute parallel do simd
- !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50
+ !ERROR: A variable-category modifier is required
!$omp target teams distribute parallel do simd defaultmap(tofrom)
do i = 1, N
a(i) = 3.14
diff --git a/flang/test/Semantics/OpenMP/defaultmap-clause-v45.f90 b/flang/test/Semantics/OpenMP/defaultmap-clause-v45.f90
index a30d90ddce0296..9cb91a71c55351 100644
--- a/flang/test/Semantics/OpenMP/defaultmap-clause-v45.f90
+++ b/flang/test/Semantics/OpenMP/defaultmap-clause-v45.f90
@@ -1,7 +1,7 @@
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=45 -Werror
subroutine f00
-!WARNING: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v4.5, try -fopenmp-version=50
+!WARNING: A variable-category modifier is required
!$omp target defaultmap(tofrom)
!$omp end target
end
>From 8740fb763dcdae15d6ecf12d49a1930d348d2d85 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 18 Nov 2024 11:11:38 -0600
Subject: [PATCH 4/8] format
---
flang/lib/Parser/openmp-parsers.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 063201fc86ca41..3ee81596825190 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -255,8 +255,8 @@ TYPE_PARSER(construct<OmpVariableCategory>(
"POINTER" >> pure(OmpVariableCategory::Value::Pointer) ||
"SCALAR" >> pure(OmpVariableCategory::Value::Scalar)))
-TYPE_PARSER(sourced(construct<OmpDefaultmapClause::Modifier>(
- Parser<OmpVariableCategory>{})))
+TYPE_PARSER(sourced(
+ construct<OmpDefaultmapClause::Modifier>(Parser<OmpVariableCategory>{})))
// --- Parsers for clauses --------------------------------------------
>From 7c5f975f3b9528fb097f151a05d2d2d0f151e286 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 18 Nov 2024 13:36:08 -0600
Subject: [PATCH 5/8] fix example
---
flang/examples/FeatureList/FeatureList.cpp | 4 ++--
flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp | 4 ++--
flang/examples/FlangOmpReport/FlangOmpReportVisitor.h | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp
index dc68f160f5d924..00b3648dad68fd 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -475,9 +475,9 @@ struct NodeVisitor {
READ_FEATURE(OmpDoacross::Source)
READ_FEATURE(OmpDoacrossClause)
READ_FEATURE(OmpDependenceType)
- READ_FEATURE(OmpDependenceType::Type)
+ READ_FEATURE(OmpDependenceType::Value)
READ_FEATURE(OmpTaskDependenceType)
- READ_FEATURE(OmpTaskDependenceType::Type)
+ READ_FEATURE(OmpTaskDependenceType::Value)
READ_FEATURE(OmpIteration)
READ_FEATURE(OmpIterationOffset)
READ_FEATURE(OmpIterationVector)
diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
index d28ed0534d6002..c184fdafb5c330 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
+++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
@@ -218,11 +218,11 @@ void OpenMPCounterVisitor::Post(const OmpScheduleModifierType::ModType &c) {
clauseDetails +=
"modifier=" + std::string{OmpScheduleModifierType::EnumToString(c)} + ";";
}
-void OpenMPCounterVisitor::Post(const OmpLinearModifier::Type &c) {
+void OpenMPCounterVisitor::Post(const OmpLinearModifier::Value &c) {
clauseDetails +=
"modifier=" + std::string{OmpLinearModifier::EnumToString(c)} + ";";
}
-void OpenMPCounterVisitor::Post(const OmpTaskDependenceType::Type &c) {
+void OpenMPCounterVisitor::Post(const OmpTaskDependenceType::Value &c) {
clauseDetails +=
"type=" + std::string{OmpTaskDependenceType::EnumToString(c)} + ";";
}
diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
index 68c52db46e2f00..6c2d194a88e69a 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
+++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
@@ -72,8 +72,8 @@ struct OpenMPCounterVisitor {
void Post(const OmpDefaultmapClause::VariableCategory &c);
void Post(const OmpDeviceTypeClause::Type &c);
void Post(const OmpScheduleModifierType::ModType &c);
- void Post(const OmpLinearModifier::Type &c);
- void Post(const OmpTaskDependenceType::Type &c);
+ void Post(const OmpLinearModifier::Value &c);
+ void Post(const OmpTaskDependenceType::Value &c);
void Post(const OmpMapClause::Type &c);
void Post(const OmpScheduleClause::ScheduleType &c);
void Post(const OmpIfClause::DirectiveNameModifier &c);
>From 9d2e9fea80a39bf15a6aa319e75fe5b8b350fbe0 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 18 Nov 2024 14:09:56 -0600
Subject: [PATCH 6/8] more example fixing
---
flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp | 5 ++---
flang/examples/FlangOmpReport/FlangOmpReportVisitor.h | 2 +-
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
index c184fdafb5c330..a9ff163f8243ce 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
+++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
@@ -208,10 +208,9 @@ void OpenMPCounterVisitor::Post(
"implicit_behavior=" + std::string{OmpDefaultmapClause::EnumToString(c)} +
";";
}
-void OpenMPCounterVisitor::Post(
- const OmpDefaultmapClause::VariableCategory &c) {
+void OpenMPCounterVisitor::Post(const OmpVariableCategory::Value &c) {
clauseDetails +=
- "variable_category=" + std::string{OmpDefaultmapClause::EnumToString(c)} +
+ "variable_category=" + std::string{OmpVariableCategory::EnumToString(c)} +
";";
}
void OpenMPCounterVisitor::Post(const OmpScheduleModifierType::ModType &c) {
diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
index 6c2d194a88e69a..83bd3644577e1c 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
+++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
@@ -69,7 +69,7 @@ struct OpenMPCounterVisitor {
void Post(const OmpProcBindClause::Type &c);
void Post(const OmpDefaultClause::Type &c);
void Post(const OmpDefaultmapClause::ImplicitBehavior &c);
- void Post(const OmpDefaultmapClause::VariableCategory &c);
+ void Post(const OmpVariableCategory::Value &c);
void Post(const OmpDeviceTypeClause::Type &c);
void Post(const OmpScheduleModifierType::ModType &c);
void Post(const OmpLinearModifier::Value &c);
>From 72079d708c8fb2485a72fcc5ff24a0cb6398140e Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 18 Nov 2024 16:01:13 -0600
Subject: [PATCH 7/8] fix FeatureList example
---
flang/examples/FeatureList/FeatureList.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp
index 00b3648dad68fd..fe7fee97bc78e5 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -495,7 +495,7 @@ struct NodeVisitor {
READ_FEATURE(OmpLinearClause::WithModifier)
READ_FEATURE(OmpLinearClause::WithoutModifier)
READ_FEATURE(OmpLinearModifier)
- READ_FEATURE(OmpLinearModifier::Type)
+ READ_FEATURE(OmpLinearModifier::Value)
READ_FEATURE(OmpLoopDirective)
READ_FEATURE(OmpMapClause)
READ_FEATURE(OmpMapClause::TypeModifier)
@@ -515,7 +515,7 @@ struct NodeVisitor {
READ_FEATURE(OmpReductionCombiner)
READ_FEATURE(OmpReductionCombiner::FunctionCombiner)
READ_FEATURE(OmpReductionInitializerClause)
- READ_FEATURE(OmpReductionOperator)
+ READ_FEATURE(OmpReductionIdentifier)
READ_FEATURE(OmpAllocateClause)
READ_FEATURE(OmpAllocateClause::AllocateModifier)
READ_FEATURE(OmpAllocateClause::AllocateModifier::Allocator)
>From 0a4e864601c0133177f90e5fc4644b3087346418 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 18 Nov 2024 16:35:21 -0600
Subject: [PATCH 8/8] fix FeatureList example
---
flang/examples/FeatureList/FeatureList.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp
index fe7fee97bc78e5..753ecb918a9ccb 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -468,7 +468,7 @@ struct NodeVisitor {
READ_FEATURE(OmpDefaultClause::Type)
READ_FEATURE(OmpDefaultmapClause)
READ_FEATURE(OmpDefaultmapClause::ImplicitBehavior)
- READ_FEATURE(OmpDefaultmapClause::VariableCategory)
+ READ_FEATURE(OmpVariableCategory::Value)
READ_FEATURE(OmpDependClause)
READ_FEATURE(OmpDependClause::TaskDep)
READ_FEATURE(OmpDoacross::Sink)
More information about the flang-commits
mailing list