[flang-commits] [flang] [flang][OpenMP] Parse OpenMP 6.0 map modifiers (PR #149134)
Krzysztof Parzyszek via flang-commits
flang-commits at lists.llvm.org
Wed Jul 16 09:29:14 PDT 2025
https://github.com/kparzysz created https://github.com/llvm/llvm-project/pull/149134
OpenMP 6.0 has changed the modifiers on the MAP clause:
- map-type-modifier has been split into individual modifiers,
- map-type "delete" has become a modifier,
- new modifiers have been added.
This patch adds parsing support for all of the OpenMP 6.0 modifiers. The old "map-type-modifier" is retained, but is no longer created in parsing. It will remain to take advantage of the preexisting modifier validation for older versions: when the OpenMP version is < 6.0, the modifiers will be rewritten back as map-type-modifiers (or map- type in case of "delete").
In this patch the modifiers will always be rewritten in the older format to isolate these changes to parsing as much as possible.
>From 0929234481b4d6d015381fda490c05bbeff1e22f Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Wed, 16 Jul 2025 08:04:17 -0500
Subject: [PATCH] [flang][OpenMP] Parse OpenMP 6.0 map modifiers
OpenMP 6.0 has changed the modifiers on the MAP clause:
- map-type-modifier has been split into individual modifiers,
- map-type "delete" has become a modifier,
- new modifiers have been added.
This patch adds parsing support for all of the OpenMP 6.0 modifiers.
The old "map-type-modifier" is retained, but is no longer created in
parsing. It will remain to take advantage of the preexisting modifier
validation for older versions: when the OpenMP version is < 6.0,
the modifiers will be rewritten back as map-type-modifiers (or map-
type in case of "delete").
In this patch the modifiers will always be rewritten in the older
format to isolate these changes to parsing as much as possible.
---
flang/include/flang/Parser/dump-parse-tree.h | 14 ++
flang/include/flang/Parser/parse-tree.h | 138 +++++++++++++++---
.../flang/Semantics/openmp-modifiers.h | 7 +
flang/lib/Parser/openmp-parsers.cpp | 53 +++++--
flang/lib/Parser/unparse.cpp | 7 +
flang/lib/Semantics/canonicalize-omp.cpp | 48 +++++-
flang/lib/Semantics/canonicalize-omp.h | 9 +-
flang/lib/Semantics/openmp-modifiers.cpp | 115 +++++++++++++++
flang/lib/Semantics/resolve-directives.cpp | 2 +
flang/lib/Semantics/semantics.cpp | 3 +-
.../test/Parser/OpenMP/map-modifiers-v60.f90 | 113 ++++++++++++++
11 files changed, 466 insertions(+), 43 deletions(-)
create mode 100644 flang/test/Parser/OpenMP/map-modifiers-v60.f90
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 32b6ca45609b6..23e35d106c077 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -529,6 +529,8 @@ class ParseTreeDumper {
NODE(parser, OmpAlignClause)
NODE(parser, OmpAlignedClause)
NODE(OmpAlignedClause, Modifier)
+ NODE(parser, OmpAlwaysModifier)
+ NODE_ENUM(OmpAlwaysModifier, Value)
NODE(parser, OmpAtClause)
NODE_ENUM(OmpAtClause, ActionTime)
NODE_ENUM(OmpSeverityClause, Severity)
@@ -546,6 +548,8 @@ class ParseTreeDumper {
#include "llvm/Frontend/OpenMP/OMP.inc"
NODE(parser, OmpClauseList)
NODE(parser, OmpCancellationConstructTypeClause)
+ NODE(parser, OmpCloseModifier)
+ NODE_ENUM(OmpCloseModifier, Value)
NODE(parser, OmpContainsClause)
NODE(parser, OmpCriticalDirective)
NODE(parser, OmpErrorDirective)
@@ -561,6 +565,8 @@ class ParseTreeDumper {
NODE(parser, OmpDefaultmapClause)
NODE_ENUM(OmpDefaultmapClause, ImplicitBehavior)
NODE(OmpDefaultmapClause, Modifier)
+ NODE(parser, OmpDeleteModifier)
+ NODE_ENUM(OmpDeleteModifier, Value)
NODE(parser, OmpDependenceType)
NODE_ENUM(OmpDependenceType, Value)
NODE(parser, OmpTaskDependenceType)
@@ -628,6 +634,8 @@ class ParseTreeDumper {
NODE(OmpNumTasksClause, Modifier)
NODE(parser, OmpBindClause)
NODE_ENUM(OmpBindClause, Binding)
+ NODE(parser, OmpPresentModifier)
+ NODE_ENUM(OmpPresentModifier, Value)
NODE(parser, OmpProcBindClause)
NODE_ENUM(OmpProcBindClause, AffinityPolicy)
NODE(parser, OmpReductionModifier)
@@ -637,6 +645,10 @@ class ParseTreeDumper {
NODE(parser, OmpInReductionClause)
NODE(OmpInReductionClause, Modifier)
NODE(parser, OmpReductionCombiner)
+ NODE(parser, OmpRefModifier)
+ NODE_ENUM(OmpRefModifier, Value)
+ NODE(parser, OmpSelfModifier)
+ NODE_ENUM(OmpSelfModifier, Value)
NODE(parser, OmpTaskReductionClause)
NODE(OmpTaskReductionClause, Modifier)
NODE(parser, OmpInitializerProc)
@@ -673,6 +685,8 @@ class ParseTreeDumper {
NODE(parser, OmpSectionsDirective)
NODE(parser, OmpToClause)
NODE(OmpToClause, Modifier)
+ NODE(parser, OmpxHoldModifier)
+ NODE_ENUM(OmpxHoldModifier, Value)
NODE(parser, Only)
NODE(parser, OpenACCAtomicConstruct)
NODE(parser, OpenACCBlockConstruct)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index cc1d032f94d4a..92a449d2f9d49 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3756,6 +3756,19 @@ struct OmpAllocatorComplexModifier {
WRAPPER_CLASS_BOILERPLATE(OmpAllocatorComplexModifier, ScalarIntExpr);
};
+// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
+// [6.0:279-288]
+//
+// always-modifier ->
+// ALWAYS // since 4.5
+//
+// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
+// map-type-modifier has been split into individual modifiers.
+struct OmpAlwaysModifier {
+ ENUM_CLASS(Value, Always)
+ WRAPPER_CLASS_BOILERPLATE(OmpAlwaysModifier, Value);
+};
+
// Ref: [5.2:252-254]
//
// chunk-modifier ->
@@ -3767,17 +3780,29 @@ struct OmpChunkModifier {
WRAPPER_CLASS_BOILERPLATE(OmpChunkModifier, Value);
};
-// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
+// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
+// [6.0:279-288]
//
-// 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;
+// close-modifier ->
+// CLOSE // since 5.0
+//
+// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
+// map-type-modifier has been split into individual modifiers.
+struct OmpCloseModifier {
+ ENUM_CLASS(Value, Close)
+ WRAPPER_CLASS_BOILERPLATE(OmpCloseModifier, Value);
+};
+
+// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
+// [6.0:279-288]
+//
+// delete-modifier ->
+// DELETE // since 6.0
+//
+// Until 5.2, it was a part of map-type.
+struct OmpDeleteModifier {
+ ENUM_CLASS(Value, Delete)
+ WRAPPER_CLASS_BOILERPLATE(OmpDeleteModifier, Value);
};
// Ref: [4.5:169-170], [5.0:255-256], [5.1:288-289]
@@ -3867,6 +3892,19 @@ struct OmpInteropType {
WRAPPER_CLASS_BOILERPLATE(OmpInteropType, Value);
};
+// 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: [5.0:47-49], [5.1:49-51], [5.2:67-69]
//
// iterator-modifier ->
@@ -3901,21 +3939,28 @@ struct OmpMapper {
WRAPPER_CLASS_BOILERPLATE(OmpMapper, Name);
};
-// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158]
+// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
+// [6.0:279-288]
//
// map-type ->
-// ALLOC | DELETE | FROM | RELEASE | TO | TOFROM // since 4.5
+// ALLOC | DELETE | RELEASE | // since 4.5, until 5.2
+// FROM | TO | TOFROM | // since 4.5
+// STORAGE // since 6.0
+//
+// Since 6.0 DELETE is a separate delete-modifier.
struct OmpMapType {
- ENUM_CLASS(Value, Alloc, Delete, From, Release, To, Tofrom);
+ ENUM_CLASS(Value, Alloc, Delete, From, Release, Storage, To, Tofrom);
WRAPPER_CLASS_BOILERPLATE(OmpMapType, Value);
};
// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158]
//
// map-type-modifier ->
-// ALWAYS | // since 4.5
-// CLOSE | // since 5.0
-// PRESENT // since 5.1
+// ALWAYS | // since 4.5, until 5.2
+// CLOSE | // since 5.0, until 5.2
+// PRESENT // since 5.1, until 5.2
+// Since 6.0 the map-type-modifier has been split into individual modifiers.
+//
struct OmpMapTypeModifier {
ENUM_CLASS(Value, Always, Close, Present, Ompx_Hold)
WRAPPER_CLASS_BOILERPLATE(OmpMapTypeModifier, Value);
@@ -3954,6 +3999,19 @@ struct OmpPrescriptiveness {
WRAPPER_CLASS_BOILERPLATE(OmpPrescriptiveness, Value);
};
+// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
+// [6.0:279-288]
+//
+// present-modifier ->
+// PRESENT // since 5.1
+//
+// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
+// map-type-modifier has been split into individual modifiers.
+struct OmpPresentModifier {
+ ENUM_CLASS(Value, Present)
+ WRAPPER_CLASS_BOILERPLATE(OmpPresentModifier, Value);
+};
+
// Ref: [5.0:300-302], [5.1:332-334], [5.2:134-137]
//
// reduction-modifier ->
@@ -3963,6 +4021,26 @@ struct OmpReductionModifier {
WRAPPER_CLASS_BOILERPLATE(OmpReductionModifier, Value);
};
+// Ref: [6.0:279-288]
+//
+// ref-modifier ->
+// REF_PTEE | REF_PTR | REF_PTR_PTEE // since 6.0
+//
+struct OmpRefModifier {
+ ENUM_CLASS(Value, Ref_Ptee, Ref_Ptr, Ref_Ptr_Ptee)
+ WRAPPER_CLASS_BOILERPLATE(OmpRefModifier, Value);
+};
+
+// Ref: [6.0:279-288]
+//
+// self-modifier ->
+// SELF // since 6.0
+//
+struct OmpSelfModifier {
+ ENUM_CLASS(Value, Self)
+ WRAPPER_CLASS_BOILERPLATE(OmpSelfModifier, Value);
+};
+
// Ref: [5.2:117-120]
//
// step-complex-modifier ->
@@ -4001,6 +4079,18 @@ struct OmpVariableCategory {
WRAPPER_CLASS_BOILERPLATE(OmpVariableCategory, Value);
};
+// Extension
+//
+// ompx-hold-modifier ->
+// OMPX_HOLD // since 4.5
+//
+// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
+// map-type-modifier has been split into individual modifiers.
+struct OmpxHoldModifier {
+ ENUM_CLASS(Value, Ompx_Hold)
+ WRAPPER_CLASS_BOILERPLATE(OmpxHoldModifier, Value);
+};
+
// context-selector
using OmpContextSelector = traits::OmpContextSelectorSpecification;
} // namespace modifier
@@ -4376,13 +4466,25 @@ struct OmpLinearClause {
// map-clause ->
// MAP([modifier...:] locator-list) // since 4.5
// modifier ->
-// map-type-modifier | // since 4.5
+// map-type-modifier [replaced] | // since 4.5, until 5.2
+// always-modifier | // since 6.0
+// close-modifier | // since 6.0
+// delete-modifier | // since 6.0
+// present-modifier | // since 6.0
+// ref-modifier | // since 6.0
+// self-modifier | // since 6.0
// mapper | // since 5.0
// iterator | // since 5.1
// map-type // since 4.5
+// ompx-hold-modifier | // since 6.0
+//
+// Since 6.0 the map-type-modifier has been split into individual modifiers,
+// and delete-modifier has been split from map-type.
struct OmpMapClause {
TUPLE_CLASS_BOILERPLATE(OmpMapClause);
- MODIFIER_BOILERPLATE(OmpMapTypeModifier, OmpMapper, OmpIterator, OmpMapType);
+ MODIFIER_BOILERPLATE(OmpAlwaysModifier, OmpCloseModifier, OmpDeleteModifier,
+ OmpMapTypeModifier, OmpPresentModifier, OmpRefModifier, OmpSelfModifier,
+ OmpMapper, OmpIterator, OmpMapType, OmpxHoldModifier);
std::tuple<MODIFIERS(), OmpObjectList, /*CommaSeparated=*/bool> t;
};
diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h
index 4fbd80f989e72..a9fe911ef8807 100644
--- a/flang/include/flang/Semantics/openmp-modifiers.h
+++ b/flang/include/flang/Semantics/openmp-modifiers.h
@@ -71,8 +71,11 @@ DECLARE_DESCRIPTOR(parser::OmpAlignment);
DECLARE_DESCRIPTOR(parser::OmpAlignModifier);
DECLARE_DESCRIPTOR(parser::OmpAllocatorComplexModifier);
DECLARE_DESCRIPTOR(parser::OmpAllocatorSimpleModifier);
+DECLARE_DESCRIPTOR(parser::OmpAlwaysModifier);
DECLARE_DESCRIPTOR(parser::OmpChunkModifier);
+DECLARE_DESCRIPTOR(parser::OmpCloseModifier);
DECLARE_DESCRIPTOR(parser::OmpContextSelector);
+DECLARE_DESCRIPTOR(parser::OmpDeleteModifier);
DECLARE_DESCRIPTOR(parser::OmpDependenceType);
DECLARE_DESCRIPTOR(parser::OmpDeviceModifier);
DECLARE_DESCRIPTOR(parser::OmpDirectiveNameModifier);
@@ -88,12 +91,16 @@ DECLARE_DESCRIPTOR(parser::OmpMapTypeModifier);
DECLARE_DESCRIPTOR(parser::OmpOrderModifier);
DECLARE_DESCRIPTOR(parser::OmpOrderingModifier);
DECLARE_DESCRIPTOR(parser::OmpPrescriptiveness);
+DECLARE_DESCRIPTOR(parser::OmpPresentModifier);
DECLARE_DESCRIPTOR(parser::OmpReductionIdentifier);
DECLARE_DESCRIPTOR(parser::OmpReductionModifier);
+DECLARE_DESCRIPTOR(parser::OmpRefModifier);
+DECLARE_DESCRIPTOR(parser::OmpSelfModifier);
DECLARE_DESCRIPTOR(parser::OmpStepComplexModifier);
DECLARE_DESCRIPTOR(parser::OmpStepSimpleModifier);
DECLARE_DESCRIPTOR(parser::OmpTaskDependenceType);
DECLARE_DESCRIPTOR(parser::OmpVariableCategory);
+DECLARE_DESCRIPTOR(parser::OmpxHoldModifier);
#undef DECLARE_DESCRIPTOR
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 76c9499410017..d349d8ceb0bb5 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -274,6 +274,10 @@ TYPE_PARSER( //
construct<OmpTypeSpecifier>(Parser<DeclarationTypeSpec>{}) ||
construct<OmpTypeSpecifier>(Parser<TypeSpec>{}))
+// 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list)
+TYPE_PARSER(construct<OmpReductionIdentifier>(Parser<DefinedOperator>{}) ||
+ construct<OmpReductionIdentifier>(Parser<ProcedureDesignator>{}))
+
TYPE_PARSER(construct<OmpReductionSpecifier>( //
Parser<OmpReductionIdentifier>{},
":"_tok >> nonemptyList(Parser<OmpTypeSpecifier>{}),
@@ -442,9 +446,18 @@ TYPE_PARSER(construct<OmpAllocatorComplexModifier>(
TYPE_PARSER(construct<OmpAllocatorSimpleModifier>(scalarIntExpr))
+TYPE_PARSER(construct<OmpAlwaysModifier>( //
+ "ALWAYS" >> pure(OmpAlwaysModifier::Value::Always)))
+
TYPE_PARSER(construct<OmpChunkModifier>( //
"SIMD" >> pure(OmpChunkModifier::Value::Simd)))
+TYPE_PARSER(construct<OmpCloseModifier>( //
+ "CLOSE" >> pure(OmpCloseModifier::Value::Close)))
+
+TYPE_PARSER(construct<OmpDeleteModifier>( //
+ "DELETE" >> pure(OmpDeleteModifier::Value::Delete)))
+
TYPE_PARSER(construct<OmpDependenceType>(
"SINK" >> pure(OmpDependenceType::Value::Sink) ||
"SOURCE" >> pure(OmpDependenceType::Value::Source)))
@@ -502,26 +515,16 @@ TYPE_PARSER(construct<OmpLinearModifier>( //
TYPE_PARSER(construct<OmpMapper>( //
"MAPPER"_tok >> parenthesized(Parser<ObjectName>{})))
-// map-type -> ALLOC | DELETE | FROM | RELEASE | TO | TOFROM
+// map-type -> ALLOC | DELETE | FROM | RELEASE | STORAGE | TO | TOFROM
TYPE_PARSER(construct<OmpMapType>( //
"ALLOC" >> pure(OmpMapType::Value::Alloc) ||
- "DELETE" >> pure(OmpMapType::Value::Delete) ||
+ // Parse "DELETE" as OmpDeleteModifier
"FROM" >> pure(OmpMapType::Value::From) ||
"RELEASE" >> pure(OmpMapType::Value::Release) ||
+ "STORAGE" >> pure(OmpMapType::Value::Storage) ||
"TO"_id >> pure(OmpMapType::Value::To) ||
"TOFROM" >> pure(OmpMapType::Value::Tofrom)))
-// map-type-modifier -> ALWAYS | CLOSE | OMPX_HOLD | PRESENT
-TYPE_PARSER(construct<OmpMapTypeModifier>(
- "ALWAYS" >> pure(OmpMapTypeModifier::Value::Always) ||
- "CLOSE" >> pure(OmpMapTypeModifier::Value::Close) ||
- "OMPX_HOLD" >> pure(OmpMapTypeModifier::Value::Ompx_Hold) ||
- "PRESENT" >> pure(OmpMapTypeModifier::Value::Present)))
-
-// 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list)
-TYPE_PARSER(construct<OmpReductionIdentifier>(Parser<DefinedOperator>{}) ||
- construct<OmpReductionIdentifier>(Parser<ProcedureDesignator>{}))
-
TYPE_PARSER(construct<OmpOrderModifier>(
"REPRODUCIBLE" >> pure(OmpOrderModifier::Value::Reproducible) ||
"UNCONSTRAINED" >> pure(OmpOrderModifier::Value::Unconstrained)))
@@ -534,11 +537,22 @@ TYPE_PARSER(construct<OmpOrderingModifier>(
TYPE_PARSER(construct<OmpPrescriptiveness>(
"STRICT" >> pure(OmpPrescriptiveness::Value::Strict)))
+TYPE_PARSER(construct<OmpPresentModifier>( //
+ "PRESENT" >> pure(OmpPresentModifier::Value::Present)))
+
TYPE_PARSER(construct<OmpReductionModifier>(
"INSCAN" >> pure(OmpReductionModifier::Value::Inscan) ||
"TASK" >> pure(OmpReductionModifier::Value::Task) ||
"DEFAULT" >> pure(OmpReductionModifier::Value::Default)))
+TYPE_PARSER(construct<OmpRefModifier>( //
+ "REF_PTEE" >> pure(OmpRefModifier::Value::Ref_Ptee) ||
+ "REF_PTR"_id >> pure(OmpRefModifier::Value::Ref_Ptr) ||
+ "REF_PTR_PTEE" >> pure(OmpRefModifier::Value::Ref_Ptr_Ptee)))
+
+TYPE_PARSER(construct<OmpSelfModifier>( //
+ "SELF" >> pure(OmpSelfModifier::Value::Self)))
+
TYPE_PARSER(construct<OmpStepComplexModifier>( //
"STEP" >> parenthesized(scalarIntExpr)))
@@ -559,6 +573,9 @@ TYPE_PARSER(construct<OmpVariableCategory>(
"POINTER" >> pure(OmpVariableCategory::Value::Pointer) ||
"SCALAR" >> pure(OmpVariableCategory::Value::Scalar)))
+TYPE_PARSER(construct<OmpxHoldModifier>( //
+ "OMPX_HOLD" >> pure(OmpxHoldModifier::Value::Ompx_Hold)))
+
// This could be auto-generated.
TYPE_PARSER(
sourced(construct<OmpAffinityClause::Modifier>(Parser<OmpIterator>{})))
@@ -611,10 +628,16 @@ TYPE_PARSER(sourced(
construct<OmpLinearClause::Modifier>(Parser<OmpStepSimpleModifier>{})))
TYPE_PARSER(sourced(construct<OmpMapClause::Modifier>(
- sourced(construct<OmpMapClause::Modifier>(Parser<OmpMapTypeModifier>{}) ||
+ sourced(construct<OmpMapClause::Modifier>(Parser<OmpAlwaysModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpCloseModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpDeleteModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpPresentModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpRefModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpSelfModifier>{}) ||
construct<OmpMapClause::Modifier>(Parser<OmpMapper>{}) ||
construct<OmpMapClause::Modifier>(Parser<OmpIterator>{}) ||
- construct<OmpMapClause::Modifier>(Parser<OmpMapType>{})))))
+ construct<OmpMapClause::Modifier>(Parser<OmpMapType>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpxHoldModifier>{})))))
TYPE_PARSER(
sourced(construct<OmpOrderClause::Modifier>(Parser<OmpOrderModifier>{})))
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index fbe89c668fc13..8ed16905b5099 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -3007,8 +3007,15 @@ class UnparseVisitor {
WALK_NESTED_ENUM(OmpPrescriptiveness, Value) // OMP prescriptiveness
WALK_NESTED_ENUM(OmpMapType, Value) // OMP map-type
WALK_NESTED_ENUM(OmpMapTypeModifier, Value) // OMP map-type-modifier
+ WALK_NESTED_ENUM(OmpAlwaysModifier, Value)
+ WALK_NESTED_ENUM(OmpCloseModifier, Value)
+ WALK_NESTED_ENUM(OmpDeleteModifier, Value)
+ WALK_NESTED_ENUM(OmpPresentModifier, Value)
+ WALK_NESTED_ENUM(OmpRefModifier, Value)
+ WALK_NESTED_ENUM(OmpSelfModifier, Value)
WALK_NESTED_ENUM(OmpTraitSelectorName, Value)
WALK_NESTED_ENUM(OmpTraitSetSelectorName, Value)
+ WALK_NESTED_ENUM(OmpxHoldModifier, Value)
#undef WALK_NESTED_ENUM
void Unparse(const ReductionOperator::Operator x) {
diff --git a/flang/lib/Semantics/canonicalize-omp.cpp b/flang/lib/Semantics/canonicalize-omp.cpp
index cf05d8463277f..46aaab19ded0a 100644
--- a/flang/lib/Semantics/canonicalize-omp.cpp
+++ b/flang/lib/Semantics/canonicalize-omp.cpp
@@ -27,7 +27,8 @@ class CanonicalizationOfOmp {
public:
template <typename T> bool Pre(T &) { return true; }
template <typename T> void Post(T &) {}
- CanonicalizationOfOmp(parser::Messages &messages) : messages_{messages} {}
+ CanonicalizationOfOmp(SemanticsContext &context)
+ : context_{context}, messages_{context.messages()} {}
void Post(parser::Block &block) {
for (auto it{block.begin()}; it != block.end(); ++it) {
@@ -88,6 +89,8 @@ class CanonicalizationOfOmp {
CanonicalizeUtilityConstructs(spec);
}
+ void Post(parser::OmpMapClause &map) { CanonicalizeMapModifiers(map); }
+
private:
template <typename T> T *GetConstructIf(parser::ExecutionPartConstruct &x) {
if (auto *y{std::get_if<parser::ExecutableConstruct>(&x.u)}) {
@@ -390,16 +393,53 @@ class CanonicalizationOfOmp {
omps.erase(rlast.base(), omps.end());
}
+ // Map clause modifiers are parsed as per OpenMP 6.0 spec. That spec has
+ // changed properties of some of the modifiers, for example it has expanded
+ // map-type-modifier into 3 individual modifiers (one for each of the
+ // possible values of the original modifier), and the "map-type" modifier
+ // is no longer ultimate.
+ // To utilize the modifier validation framework for semantic checks,
+ // if the specified OpenMP version is less than 6.0, rewrite the affected
+ // modifiers back into the pre-6.0 forms.
+ void CanonicalizeMapModifiers(parser::OmpMapClause &map) {
+ // Omp{Always, Close, Present, xHold}Modifier -> OmpMapTypeModifier
+ // OmpDeleteModifier -> OmpMapType
+ using Modifier = parser::OmpMapClause::Modifier;
+ using Modifiers = std::optional<std::list<Modifier>>;
+ auto &modifiers{std::get<Modifiers>(map.t)};
+ if (!modifiers) {
+ return;
+ }
+
+ using MapTypeModifier = parser::OmpMapTypeModifier;
+ using MapType = parser::OmpMapType;
+
+ for (auto &mod : *modifiers) {
+ if (std::holds_alternative<parser::OmpAlwaysModifier>(mod.u)) {
+ mod.u = MapTypeModifier(MapTypeModifier::Value::Always);
+ } else if (std::holds_alternative<parser::OmpCloseModifier>(mod.u)) {
+ mod.u = MapTypeModifier(MapTypeModifier::Value::Close);
+ } else if (std::holds_alternative<parser::OmpPresentModifier>(mod.u)) {
+ mod.u = MapTypeModifier(MapTypeModifier::Value::Present);
+ } else if (std::holds_alternative<parser::OmpxHoldModifier>(mod.u)) {
+ mod.u = MapTypeModifier(MapTypeModifier::Value::Ompx_Hold);
+ } else if (std::holds_alternative<parser::OmpDeleteModifier>(mod.u)) {
+ mod.u = MapType(MapType::Value::Delete);
+ }
+ }
+ }
+
// Mapping from the specification parts to the blocks that follow in the
// same construct. This is for converting utility constructs to executable
// constructs.
std::map<parser::SpecificationPart *, parser::Block *> blockForSpec_;
+ SemanticsContext &context_;
parser::Messages &messages_;
};
-bool CanonicalizeOmp(parser::Messages &messages, parser::Program &program) {
- CanonicalizationOfOmp omp{messages};
+bool CanonicalizeOmp(SemanticsContext &context, parser::Program &program) {
+ CanonicalizationOfOmp omp{context};
Walk(program, omp);
- return !messages.AnyFatalError();
+ return !context.messages().AnyFatalError();
}
} // namespace Fortran::semantics
diff --git a/flang/lib/Semantics/canonicalize-omp.h b/flang/lib/Semantics/canonicalize-omp.h
index c45d6bbbf9062..3251218da35ed 100644
--- a/flang/lib/Semantics/canonicalize-omp.h
+++ b/flang/lib/Semantics/canonicalize-omp.h
@@ -11,11 +11,12 @@
namespace Fortran::parser {
struct Program;
-class Messages;
-} // namespace Fortran::parser
+}
namespace Fortran::semantics {
-bool CanonicalizeOmp(parser::Messages &messages, parser::Program &program);
-}
+class SemanticsContext;
+
+bool CanonicalizeOmp(SemanticsContext &context, parser::Program &program);
+} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_CANONICALIZE_OMP_H_
diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp
index c84e832ee52a1..336ce4beb24ba 100644
--- a/flang/lib/Semantics/openmp-modifiers.cpp
+++ b/flang/lib/Semantics/openmp-modifiers.cpp
@@ -140,6 +140,22 @@ OmpGetDescriptor<parser::OmpAllocatorSimpleModifier>() {
return desc;
}
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAlwaysModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"always-modifier",
+ /*props=*/
+ {
+ {45, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {45, {Clause::OMPC_map}},
+ },
+ };
+ return desc;
+}
+
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpChunkModifier>() {
static const OmpModifierDescriptor desc{
@@ -156,6 +172,22 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpChunkModifier>() {
return desc;
}
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpCloseModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"close-modifier",
+ /*props=*/
+ {
+ {50, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {50, {Clause::OMPC_map}},
+ },
+ };
+ return desc;
+}
+
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpContextSelector>() {
static const OmpModifierDescriptor desc{
@@ -173,6 +205,23 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpContextSelector>() {
return desc;
}
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDeleteModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"delete-modifier",
+ /*props=*/
+ {
+ {45, {OmpProperty::Unique, OmpProperty::Ultimate}},
+ {60, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {45, {Clause::OMPC_map}},
+ },
+ };
+ return desc;
+}
+
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDependenceType>() {
static const OmpModifierDescriptor desc{
@@ -347,6 +396,7 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpMapType>() {
/*props=*/
{
{45, {OmpProperty::Ultimate}},
+ {60, {OmpProperty::Unique}},
},
/*clauses=*/
{
@@ -367,6 +417,7 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpMapTypeModifier>() {
/*clauses=*/
{
{45, {Clause::OMPC_map}},
+ {60, {}},
},
};
return desc;
@@ -420,6 +471,22 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpPrescriptiveness>() {
return desc;
}
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpPresentModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"present-modifier",
+ /*props=*/
+ {
+ {51, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {51, {Clause::OMPC_map}},
+ },
+ };
+ return desc;
+}
+
template <>
const OmpModifierDescriptor &
OmpGetDescriptor<parser::OmpReductionIdentifier>() {
@@ -456,6 +523,38 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpReductionModifier>() {
return desc;
}
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpRefModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"ref-modifier",
+ /*props=*/
+ {
+ {60, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {60, {Clause::OMPC_map}},
+ },
+ };
+ return desc;
+}
+
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpSelfModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"self-modifier",
+ /*props=*/
+ {
+ {60, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {60, {Clause::OMPC_map}},
+ },
+ };
+ return desc;
+}
+
template <>
const OmpModifierDescriptor &
OmpGetDescriptor<parser::OmpStepComplexModifier>() {
@@ -522,4 +621,20 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpVariableCategory>() {
};
return desc;
}
+
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpxHoldModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"ompx-hold-modifier",
+ /*props=*/
+ {
+ {45, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {45, {Clause::OMPC_map}},
+ },
+ };
+ return desc;
+}
} // namespace Fortran::semantics
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 151f4ccae634e..0b860314b4a1f 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -734,6 +734,8 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
case parser::OmpMapType::Value::Delete:
ompFlag = Symbol::Flag::OmpMapDelete;
break;
+ default:
+ break;
}
}
const auto &ompObjList{std::get<parser::OmpObjectList>(x.t)};
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index ab78605d01f4c..d0a5b200d0d8e 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -643,8 +643,7 @@ bool Semantics::Perform() {
return ValidateLabels(context_, program_) &&
parser::CanonicalizeDo(program_) && // force line break
CanonicalizeAcc(context_.messages(), program_) &&
- CanonicalizeOmp(context_.messages(), program_) &&
- CanonicalizeCUDA(program_) &&
+ CanonicalizeOmp(context_, program_) && CanonicalizeCUDA(program_) &&
PerformStatementSemantics(context_, program_) &&
CanonicalizeDirectives(context_.messages(), program_) &&
ModFileWriter{context_}
diff --git a/flang/test/Parser/OpenMP/map-modifiers-v60.f90 b/flang/test/Parser/OpenMP/map-modifiers-v60.f90
new file mode 100644
index 0000000000000..bc80886780d46
--- /dev/null
+++ b/flang/test/Parser/OpenMP/map-modifiers-v60.f90
@@ -0,0 +1,113 @@
+!RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp -fopenmp-version=60 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s
+!RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp -fopenmp-version=60 %s | FileCheck --check-prefix="PARSE-TREE" %s
+
+subroutine f00(x)
+ integer :: x
+ !$omp target map(always, close, delete, present, ompx_hold: x)
+ x = x + 1
+ !$omp end target
+end
+
+!UNPARSE: SUBROUTINE f00 (x)
+!UNPARSE: INTEGER x
+!UNPARSE: !$OMP TARGET MAP(ALWAYS, CLOSE, DELETE, PRESENT, OMPX_HOLD: x)
+!UNPARSE: x = x+1
+!UNPARSE: !$OMP END TARGET
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: OmpBeginBlockDirective
+!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
+!PARSE-TREE: | | Modifier -> OmpAlwaysModifier -> Value = Always
+!PARSE-TREE: | | Modifier -> OmpCloseModifier -> Value = Close
+!PARSE-TREE: | | Modifier -> OmpDeleteModifier -> Value = Delete
+!PARSE-TREE: | | Modifier -> OmpPresentModifier -> Value = Present
+!PARSE-TREE: | | Modifier -> OmpxHoldModifier -> Value = Ompx_Hold
+!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | bool = 'true'
+
+subroutine f01(x)
+ integer :: x
+ !$omp target map(self, storage: x)
+ x = x + 1
+ !$omp end target
+end
+
+!UNPARSE: !$OMP TARGET MAP(SELF, STORAGE: x)
+!UNPARSE: x = x+1
+!UNPARSE: !$OMP END TARGET
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: OmpBeginBlockDirective
+!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
+!PARSE-TREE: | | Modifier -> OmpSelfModifier -> Value = Self
+!PARSE-TREE: | | Modifier -> OmpMapType -> Value = Storage
+!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | bool = 'true'
+
+subroutine f02(x)
+ integer, pointer :: x
+ !$omp target map(ref_ptr, to: x)
+ x = x + 1
+ !$omp end target
+end
+
+!UNPARSE: SUBROUTINE f02 (x)
+!UNPARSE: INTEGER, POINTER :: x
+!UNPARSE: !$OMP TARGET MAP(REF_PTR, TO: x)
+!UNPARSE: x = x+1
+!UNPARSE: !$OMP END TARGET
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: OmpBeginBlockDirective
+!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
+!PARSE-TREE: | | Modifier -> OmpRefModifier -> Value = Ref_Ptr
+!PARSE-TREE: | | Modifier -> OmpMapType -> Value = To
+!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | bool = 'true'
+
+subroutine f03(x)
+ integer, pointer :: x
+ !$omp target map(ref_ptee, to: x)
+ x = x + 1
+ !$omp end target
+end
+
+!UNPARSE: SUBROUTINE f03 (x)
+!UNPARSE: INTEGER, POINTER :: x
+!UNPARSE: !$OMP TARGET MAP(REF_PTEE, TO: x)
+!UNPARSE: x = x+1
+!UNPARSE: !$OMP END TARGET
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: OmpBeginBlockDirective
+!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
+!PARSE-TREE: | | Modifier -> OmpRefModifier -> Value = Ref_Ptee
+!PARSE-TREE: | | Modifier -> OmpMapType -> Value = To
+!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | bool = 'true'
+
+subroutine f04(x)
+ integer, pointer :: x
+ !$omp target map(ref_ptr_ptee, to: x)
+ x = x + 1
+ !$omp end target
+end
+
+!UNPARSE: SUBROUTINE f04 (x)
+!UNPARSE: INTEGER, POINTER :: x
+!UNPARSE: !$OMP TARGET MAP(REF_PTR_PTEE, TO: x)
+!UNPARSE: x = x+1
+!UNPARSE: !$OMP END TARGET
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: OmpBeginBlockDirective
+!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
+!PARSE-TREE: | | Modifier -> OmpRefModifier -> Value = Ref_Ptr_Ptee
+!PARSE-TREE: | | Modifier -> OmpMapType -> Value = To
+!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | bool = 'true'
More information about the flang-commits
mailing list