[llvm-branch-commits] [flang] [flang][OpenMP] Version-dependent parsing of map-type-modifier (PR #213473)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Aug 1 11:11:46 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-fir-hlfir

Author: Krzysztof Parzyszek (kparzysz)

<details>
<summary>Changes</summary>

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>

---
Full diff: https://github.com/llvm/llvm-project/pull/213473.diff


6 Files Affected:

- (modified) flang/include/flang/Parser/parse-tree.h (+1-2) 
- (modified) flang/lib/Lower/OpenMP/Clauses.cpp (-1) 
- (modified) flang/lib/Parser/openmp-parsers.cpp (+62-19) 
- (modified) flang/lib/Semantics/canonicalize-omp.cpp (+1-45) 
- (modified) flang/test/Parser/OpenMP/map-modifiers-v60.f90 (+7-7) 
- (modified) flang/test/Parser/OpenMP/map-modifiers.f90 (+4-4) 


``````````diff
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

``````````

</details>


https://github.com/llvm/llvm-project/pull/213473


More information about the llvm-branch-commits mailing list