[llvm-branch-commits] [flang] [flang][OpenMP] Version-dependent parsing of map-type-modifier (PR #213473)
Krzysztof Parzyszek via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat Aug 1 11:09:36 PDT 2026
https://github.com/kparzysz created https://github.com/llvm/llvm-project/pull/213473
Up until 5.2, ALWAYS, CLOSE, and PRESENT were keywords of the
map-type-modifier. Starting from 6.0 they all became their own
single-keyword modifiers. This allowed specifying them together,
unlike in the past where map-type-modifier was unique.
To avoid using a single representation of the modifiers, and be
able to validate them through non-conditional properties, the
AST was rewritten back to the older form in canonicalization
when the spec version was set to 5.2 or earlier.
Now that the parser is version-aware, it can generate the desired
AST from the start.
Additionally, extract the OMPX_HOLD modifier out of the map-type-
modifier into its own AST node regardless of version.
---
<sub>Stack created with <a href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>
>From ce1c15a062ad4bfa8d6ad3c2f4394435ad1ee5f5 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Fri, 31 Jul 2026 13:47:50 -0500
Subject: [PATCH] [flang][OpenMP] Version-dependent parsing of
map-type-modifier
Up until 5.2, ALWAYS, CLOSE, and PRESENT were keywords of the
map-type-modifier. Starting from 6.0 they all became their own
single-keyword modifiers. This allowed specifying them together,
unlike in the past where map-type-modifier was unique.
To avoid using a single representation of the modifiers, and be
able to validate them through non-conditional properties, the
AST was rewritten back to the older form in canonicalization
when the spec version was set to 5.2 or earlier.
Now that the parser is version-aware, it can generate the desired
AST from the start.
Additionally, extract the OMPX_HOLD modifier out of the map-type-
modifier into its own AST node regardless of version.
---
flang/include/flang/Parser/parse-tree.h | 3 +-
flang/lib/Lower/OpenMP/Clauses.cpp | 1 -
flang/lib/Parser/openmp-parsers.cpp | 81 ++++++++++++++-----
flang/lib/Semantics/canonicalize-omp.cpp | 46 +----------
.../test/Parser/OpenMP/map-modifiers-v60.f90 | 14 ++--
flang/test/Parser/OpenMP/map-modifiers.f90 | 8 +-
6 files changed, 75 insertions(+), 78 deletions(-)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index f9b7ec51c87e0..497d985c1c8c5 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4212,9 +4212,8 @@ struct OmpMapType {
// 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)
+ ENUM_CLASS(Value, Always, Close, Present)
WRAPPER_CLASS_BOILERPLATE(OmpMapTypeModifier, Value);
};
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 9db79110df9e5..941e875259a20 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -1229,7 +1229,6 @@ Map make(const parser::OmpClause::Map &inp,
// clang-format off
MS(Always, Always)
MS(Close, Close)
- MS(Ompx_Hold, OmpxHold)
MS(Present, Present)
// clang-format on
);
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 6cf57040cecd2..7b467c73d8fc1 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -937,14 +937,55 @@ TYPE_PARSER(construct<OmpMapper>( //
"MAPPER"_tok >> parenthesized(Parser<ObjectName>{})))
// map-type -> ALLOC | DELETE | FROM | RELEASE | STORAGE | TO | TOFROM
-TYPE_PARSER(construct<OmpMapType>( //
- "ALLOC" >> pure(OmpMapType::Value::Alloc) ||
- // 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)))
+struct OmpMapTypeParser {
+ using resultType = OmpMapType::Value;
+
+ std::optional<resultType> Parse(ParseState &state) const {
+ unsigned version{state.userState()->langOptions().OpenMPVersion};
+ if (version < 60) {
+ auto parser{//
+ "ALLOC" >> pure(OmpMapType::Value::Alloc) ||
+ "DELETE" >> pure(OmpMapType::Value::Delete) ||
+ "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)};
+ return parser.Parse(state);
+ } else {
+ auto parser{//
+ "ALLOC" >> pure(OmpMapType::Value::Alloc) ||
+ "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)};
+ return parser.Parse(state);
+ }
+ }
+};
+
+TYPE_PARSER(OmpMapTypeParser{})
+
+struct OmpMapTypeModifierParser {
+ using resultType = OmpMapTypeModifier::Value;
+
+ std::optional<resultType> Parse(ParseState &state) const {
+ unsigned version{state.userState()->langOptions().OpenMPVersion};
+ if (version < 60) {
+ auto parser{//
+ "ALWAYS" >> pure(OmpMapTypeModifier::Value::Always) ||
+ "CLOSE" >> pure(OmpMapTypeModifier::Value::Close) ||
+ "PRESENT" >> pure(OmpMapTypeModifier::Value::Present)};
+ return parser.Parse(state);
+ } else {
+ // No longer in 6.0.
+ return std::nullopt;
+ }
+ }
+};
+
+TYPE_PARSER(OmpMapTypeModifierParser{})
TYPE_PARSER(construct<OmpOrderModifier>(
"REPRODUCIBLE" >> pure(OmpOrderModifier::Value::Reproducible) ||
@@ -1074,17 +1115,19 @@ TYPE_PARSER(sourced(
construct<OmpLinearClause::Modifier>(Parser<OmpStepSimpleModifier>{})))
TYPE_PARSER(sourced(construct<OmpMapClause::Modifier>(
- sourced(construct<OmpMapClause::Modifier>(Parser<OmpAlwaysModifier>{}) ||
- construct<OmpMapClause::Modifier>(Parser<OmpAttachModifier>{}) ||
- 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<OmpxHoldModifier>{})))))
+ // Try the two custom parsers first.
+ construct<OmpMapClause::Modifier>(OmpMapTypeParser{}) ||
+ construct<OmpMapClause::Modifier>(OmpMapTypeModifierParser{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpAlwaysModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpAttachModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpCloseModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpDeleteModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpIterator>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpMapper>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpPresentModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpRefModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpSelfModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpxHoldModifier>{}))))
TYPE_PARSER(
sourced(construct<OmpOrderClause::Modifier>(Parser<OmpOrderModifier>{})))
diff --git a/flang/lib/Semantics/canonicalize-omp.cpp b/flang/lib/Semantics/canonicalize-omp.cpp
index 1dc149c54d21f..fe96a63b3982b 100644
--- a/flang/lib/Semantics/canonicalize-omp.cpp
+++ b/flang/lib/Semantics/canonicalize-omp.cpp
@@ -26,7 +26,7 @@ class CanonicalizationOfOmp {
template <typename T> bool Pre(T &) { return true; }
template <typename T> void Post(T &) {}
CanonicalizationOfOmp(SemanticsContext &context)
- : context_{context}, messages_{context.messages()} {}
+ : messages_{context.messages()} {}
// Pre-visit all constructs that have both a specification part and
// an execution part, and store the connection between the two.
@@ -66,8 +66,6 @@ class CanonicalizationOfOmp {
CanonicalizeAllocateDirectives(spec);
}
- void Post(parser::OmpMapClause &map) { CanonicalizeMapModifiers(map); }
-
private:
// Canonicalization of allocate directives
//
@@ -325,52 +323,10 @@ 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) {
- unsigned version{context_.langOptions().OpenMPVersion};
- if (version >= 60) {
- return;
- }
-
- // 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_;
};
diff --git a/flang/test/Parser/OpenMP/map-modifiers-v60.f90 b/flang/test/Parser/OpenMP/map-modifiers-v60.f90
index 46d57a0700390..3c487019bbc12 100644
--- a/flang/test/Parser/OpenMP/map-modifiers-v60.f90
+++ b/flang/test/Parser/OpenMP/map-modifiers-v60.f90
@@ -1,5 +1,5 @@
-!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
+!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=60 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s
+!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=60 %s | FileCheck --check-prefix="PARSE-TREE" %s
subroutine f00(x)
integer :: x
@@ -11,7 +11,7 @@ subroutine f00(x)
!UNPARSE: SUBROUTINE f00 (x)
!UNPARSE: INTEGER x
!UNPARSE: !$OMP TARGET MAP(ALWAYS, CLOSE, DELETE, PRESENT, OMPX_HOLD: x)
-!UNPARSE: x = x+1
+!UNPARSE: x=x+1_4
!UNPARSE: !$OMP END TARGET
!UNPARSE: END SUBROUTINE
@@ -34,7 +34,7 @@ subroutine f01(x)
end
!UNPARSE: !$OMP TARGET MAP(SELF, STORAGE: x)
-!UNPARSE: x = x+1
+!UNPARSE: x=x+1_4
!UNPARSE: !$OMP END TARGET
!UNPARSE: END SUBROUTINE
@@ -56,7 +56,7 @@ subroutine f02(x)
!UNPARSE: SUBROUTINE f02 (x)
!UNPARSE: INTEGER, POINTER :: x
!UNPARSE: !$OMP TARGET MAP(REF_PTR, TO: x)
-!UNPARSE: x = x+1
+!UNPARSE: x=x+1_4
!UNPARSE: !$OMP END TARGET
!UNPARSE: END SUBROUTINE
@@ -78,7 +78,7 @@ subroutine f03(x)
!UNPARSE: SUBROUTINE f03 (x)
!UNPARSE: INTEGER, POINTER :: x
!UNPARSE: !$OMP TARGET MAP(REF_PTEE, TO: x)
-!UNPARSE: x = x+1
+!UNPARSE: x=x+1_4
!UNPARSE: !$OMP END TARGET
!UNPARSE: END SUBROUTINE
@@ -100,7 +100,7 @@ subroutine f04(x)
!UNPARSE: SUBROUTINE f04 (x)
!UNPARSE: INTEGER, POINTER :: x
!UNPARSE: !$OMP TARGET MAP(REF_PTR_PTEE, TO: x)
-!UNPARSE: x = x+1
+!UNPARSE: x=x+1_4
!UNPARSE: !$OMP END TARGET
!UNPARSE: END SUBROUTINE
diff --git a/flang/test/Parser/OpenMP/map-modifiers.f90 b/flang/test/Parser/OpenMP/map-modifiers.f90
index 7d9b8856ac833..48d5172bcdefd 100644
--- a/flang/test/Parser/OpenMP/map-modifiers.f90
+++ b/flang/test/Parser/OpenMP/map-modifiers.f90
@@ -18,7 +18,7 @@ subroutine f00(x)
!PARSE-TREE: OmpBeginDirective
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = target
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
-!PARSE-TREE: | | Modifier -> OmpMapTypeModifier -> Value = Ompx_Hold
+!PARSE-TREE: | | Modifier -> OmpxHoldModifier -> Value = Ompx_Hold
!PARSE-TREE: | | Modifier -> OmpMapTypeModifier -> Value = Always
!PARSE-TREE: | | Modifier -> OmpMapTypeModifier -> Value = Present
!PARSE-TREE: | | Modifier -> OmpMapTypeModifier -> Value = Close
@@ -43,7 +43,7 @@ subroutine f01(x)
!PARSE-TREE: OmpBeginDirective
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = target
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
-!PARSE-TREE: | | Modifier -> OmpMapTypeModifier -> Value = Ompx_Hold
+!PARSE-TREE: | | Modifier -> OmpxHoldModifier -> Value = Ompx_Hold
!PARSE-TREE: | | Modifier -> OmpMapTypeModifier -> Value = Always
!PARSE-TREE: | | Modifier -> OmpMapTypeModifier -> Value = Present
!PARSE-TREE: | | Modifier -> OmpMapTypeModifier -> Value = Close
@@ -108,7 +108,7 @@ subroutine f04(x)
!PARSE-TREE: OmpBeginDirective
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = target
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
-!PARSE-TREE: | | Modifier -> OmpMapTypeModifier -> Value = Ompx_Hold
+!PARSE-TREE: | | Modifier -> OmpxHoldModifier -> Value = Ompx_Hold
!PARSE-TREE: | | Modifier -> OmpMapTypeModifier -> Value = Always
!PARSE-TREE: | | Modifier -> OmpMapTypeModifier -> Value = Present
!PARSE-TREE: | | Modifier -> OmpMapTypeModifier -> Value = Close
@@ -133,7 +133,7 @@ subroutine f05(x)
!PARSE-TREE: OmpBeginDirective
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = target
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
-!PARSE-TREE: | | Modifier -> OmpMapTypeModifier -> Value = Ompx_Hold
+!PARSE-TREE: | | Modifier -> OmpxHoldModifier -> Value = Ompx_Hold
!PARSE-TREE: | | Modifier -> OmpMapTypeModifier -> Value = Always
!PARSE-TREE: | | Modifier -> OmpMapTypeModifier -> Value = Present
!PARSE-TREE: | | Modifier -> OmpMapTypeModifier -> Value = Close
More information about the llvm-branch-commits
mailing list