[flang-commits] [flang] [flang][OpenMP] Use 'linear-step' instead of 'step-simple-modifier' i… (PR #214041)

Krzysztof Parzyszek via flang-commits flang-commits at lists.llvm.org
Tue Aug 4 12:02:45 PDT 2026


https://github.com/kparzysz created https://github.com/llvm/llvm-project/pull/214041

…n 5.1-

These two modifiers are structurally identical, but the latter has an exclusive property whereas the former does not.
Also, this allows diagnostics to use the modifier name that appears in the spec that corresponds to the version in -fopenmp-version.

>From fa2201d91e5e454c48e550648dfeb2dfe4e6ff45 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Tue, 4 Aug 2026 12:05:58 -0500
Subject: [PATCH] [flang][OpenMP] Use 'linear-step' instead of
 'step-simple-modifier' in 5.1-

These two modifiers are structurally identical, but the latter has an
exclusive property whereas the former does not.
Also, this allows diagnostics to use the modifier name that appears in
the spec that corresponds to the version in -fopenmp-version.
---
 flang/include/flang/Parser/dump-parse-tree.h  |  1 +
 flang/include/flang/Parser/parse-tree.h       | 25 ++++--
 .../flang/Semantics/openmp-modifiers.h        |  1 +
 flang/lib/Lower/OpenMP/Clauses.cpp            |  6 +-
 flang/lib/Parser/openmp-parsers.cpp           | 37 +++++++--
 flang/lib/Semantics/openmp-modifiers.cpp      | 20 ++++-
 .../test/Parser/OpenMP/linear-clause-v45.f90  | 78 +++++++++++++++++++
 ...inear-clause.f90 => linear-clause-v52.f90} |  0
 .../test/Semantics/OpenMP/linear-clause02.f90 |  6 ++
 .../test/Semantics/OpenMP/linear-clause03.f90 |  9 +++
 10 files changed, 164 insertions(+), 19 deletions(-)
 create mode 100644 flang/test/Parser/OpenMP/linear-clause-v45.f90
 rename flang/test/Parser/OpenMP/{linear-clause.f90 => linear-clause-v52.f90} (100%)

diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 729bcbc9b7cab..b7d5634dafc2c 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -677,6 +677,7 @@ class ParseTreeDumper {
   NODE(OmpLinearClause, Modifier)
   NODE(parser, OmpLinearModifier)
   NODE_ENUM(OmpLinearModifier, Value)
+  NODE(parser, OmpLinearStep)
   NODE(parser, OmpLocator)
   NODE(parser, OmpLooprangeClause)
   NODE(parser, OmpLowerBound)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 497d985c1c8c5..d647879c0dc92 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4157,6 +4157,14 @@ struct OmpLinearModifier {
   WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Value);
 };
 
+// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325]
+//
+// linear-stepr ->
+//    integer-expresion                             // since 4.5, until 5.1
+struct OmpLinearStep {
+  WRAPPER_CLASS_BOILERPLATE(OmpLinearStep, ScalarIntExpr);
+};
+
 // Ref: [6.0:372-373]
 //
 // loop-modifier ->
@@ -4334,10 +4342,10 @@ struct OmpStepComplexModifier {
   WRAPPER_CLASS_BOILERPLATE(OmpStepComplexModifier, ScalarIntExpr);
 };
 
-// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
+// Ref: [5.2:117-120], [6.0:232-235]
 //
 // step-simple-modifier ->
-//    integer-expresion                             // since 4.5
+//    integer-expresion                             // since 5.2
 struct OmpStepSimpleModifier {
   WRAPPER_CLASS_BOILERPLATE(OmpStepSimpleModifier, ScalarIntExpr);
 };
@@ -4817,16 +4825,19 @@ struct OmpLastprivateClause {
 // Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
 //
 // linear-clause ->
-//    LINEAR(list [: step-simple-modifier]) |       // since 4.5
+//    LINEAR(list [: linear-step]) |                // since 4.5, until 5.1
+//    LINEAR(list [: step-simple-modifier]) |       // since 5.2
+//    LINEAR(
+//        linear-modifier(list) [: linear-step]) |  // since 4.5, until 5.1
 //    LINEAR(linear-modifier(list)
-//        [: step-simple-modifier]) |               // since 4.5, until 5.2[*]
+//        [: step-simple-modifier]) |               // since 5.2, until 5.2[*]
 //    LINEAR(list [: linear-modifier,
 //        step-complex-modifier])                   // since 5.2
-// [*] Still allowed in 5.2 when on DECLARE SIMD, but deprecated.
+// [*] Allowed in 5.2 when on DECLARE SIMD, but deprecated.
 struct OmpLinearClause {
   TUPLE_CLASS_BOILERPLATE(OmpLinearClause);
-  MODIFIER_BOILERPLATE(
-      OmpLinearModifier, OmpStepSimpleModifier, OmpStepComplexModifier);
+  MODIFIER_BOILERPLATE(OmpLinearModifier, OmpLinearStep, OmpStepSimpleModifier,
+      OmpStepComplexModifier);
   std::tuple<OmpObjectList, MODIFIERS(), /*PostModified=*/bool> t;
 };
 
diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h
index d6f225f329f41..41a4a87f60949 100644
--- a/flang/include/flang/Semantics/openmp-modifiers.h
+++ b/flang/include/flang/Semantics/openmp-modifiers.h
@@ -90,6 +90,7 @@ DECLARE_DESCRIPTOR(parser::OmpInteropType);
 DECLARE_DESCRIPTOR(parser::OmpIterator);
 DECLARE_DESCRIPTOR(parser::OmpLastprivateModifier);
 DECLARE_DESCRIPTOR(parser::OmpLinearModifier);
+DECLARE_DESCRIPTOR(parser::OmpLinearStep);
 DECLARE_DESCRIPTOR(parser::OmpLoopModifier);
 DECLARE_DESCRIPTOR(parser::OmpLowerBound);
 DECLARE_DESCRIPTOR(parser::OmpMapper);
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 941e875259a20..1b9ce1401118e 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -1181,15 +1181,17 @@ Linear make(const parser::OmpClause::Linear &inp,
       semantics::OmpGetUniqueModifier<parser::OmpStepSimpleModifier>(mods);
   assert((!m0 || !m1) && "Simple and complex modifiers both present");
 
-  auto *m2 = semantics::OmpGetUniqueModifier<parser::OmpLinearModifier>(mods);
+  auto *m2 = semantics::OmpGetUniqueModifier<parser::OmpLinearStep>(mods);
+  auto *m3 = semantics::OmpGetUniqueModifier<parser::OmpLinearModifier>(mods);
   auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
 
   auto &&maybeStep = m0   ? maybeApplyToV(makeExprFn(semaCtx), m0)
                      : m1 ? maybeApplyToV(makeExprFn(semaCtx), m1)
+                     : m2 ? maybeApplyToV(makeExprFn(semaCtx), m2)
                           : std::optional<Linear::StepComplexModifier>{};
 
   return Linear{{/*StepComplexModifier=*/std::move(maybeStep),
-                 /*LinearModifier=*/maybeApplyToV(convert, m2),
+                 /*LinearModifier=*/maybeApplyToV(convert, m3),
                  /*List=*/makeObjects(t1, semaCtx)}};
 }
 
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 7b467c73d8fc1..ad74cb84aa8bf 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -931,6 +931,8 @@ TYPE_PARSER(construct<OmpLinearModifier>( //
     "VAL" >> pure(OmpLinearModifier::Value::Val) ||
     "UVAL" >> pure(OmpLinearModifier::Value::Uval)))
 
+TYPE_PARSER(construct<OmpLinearStep>(scalarIntExpr))
+
 TYPE_PARSER(construct<OmpLowerBound>(scalarIntExpr))
 
 TYPE_PARSER(construct<OmpMapper>( //
@@ -1109,10 +1111,27 @@ TYPE_PARSER(sourced(construct<OmpInReductionClause::Modifier>(
 TYPE_PARSER(sourced(construct<OmpLastprivateClause::Modifier>(
     Parser<OmpLastprivateModifier>{})))
 
-TYPE_PARSER(sourced(
-    construct<OmpLinearClause::Modifier>(Parser<OmpLinearModifier>{}) ||
-    construct<OmpLinearClause::Modifier>(Parser<OmpStepComplexModifier>{}) ||
-    construct<OmpLinearClause::Modifier>(Parser<OmpStepSimpleModifier>{})))
+struct OmpLinearClauseModifierParser {
+  using resultType = OmpLinearClause::Modifier;
+
+  std::optional<resultType> Parse(ParseState &state) const {
+    unsigned version{state.userState()->langOptions().OpenMPVersion};
+    if (version < 52) {
+      auto parser{sourced( //
+          construct<resultType>(Parser<OmpLinearModifier>{}) ||
+          construct<resultType>(Parser<OmpLinearStep>{}))};
+      return parser.Parse(state);
+    } else {
+      auto parser{sourced( //
+          construct<resultType>(Parser<OmpLinearModifier>{}) ||
+          construct<resultType>(Parser<OmpStepComplexModifier>{}) ||
+          construct<resultType>(Parser<OmpStepSimpleModifier>{}))};
+      return parser.Parse(state);
+    }
+  }
+};
+
+TYPE_PARSER(OmpLinearClauseModifierParser{})
 
 TYPE_PARSER(sourced(construct<OmpMapClause::Modifier>(
     // Try the two custom parsers first.
@@ -1426,17 +1445,19 @@ OmpLinearClause makeLinearFromOldSyntax(OmpLinearClause::Modifier &&lm,
 TYPE_PARSER(
     // Parse the "modifier(x)" first, because syntacticaly it will match
     // an array element (i.e. a list item).
-    // LINEAR(linear-modifier(list) [: step-simple-modifier])
+    // LINEAR(linear-modifier(list) [: linear-step])
     construct<OmpLinearClause>( //
         applyFunction<OmpLinearClause>(makeLinearFromOldSyntax,
             SpecificModifierParser<OmpLinearModifier, OmpLinearClause>{},
             parenthesized(Parser<OmpObjectList>{}),
-            maybe(":"_tok >> SpecificModifierParser<OmpStepSimpleModifier,
-                                 OmpLinearClause>{}))) ||
+            maybe(":"_tok >>
+                (SpecificModifierParser<OmpLinearStep, OmpLinearClause>{} ||
+                    SpecificModifierParser<OmpStepSimpleModifier,
+                        OmpLinearClause>{})))) ||
     // LINEAR(list [: modifiers])
     construct<OmpLinearClause>( //
         Parser<OmpObjectList>{},
-        maybe(":"_tok >> nonemptyList(Parser<OmpLinearClause::Modifier>{})),
+        maybe(":"_tok >> nonemptyList(OmpLinearClauseModifierParser{})),
         /*PostModified=*/pure(true)))
 
 TYPE_PARSER(construct<OmpLooprangeClause>(
diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp
index f3ee8917356fa..972788aff1247 100644
--- a/flang/lib/Semantics/openmp-modifiers.cpp
+++ b/flang/lib/Semantics/openmp-modifiers.cpp
@@ -456,6 +456,23 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpLinearModifier>() {
   return desc;
 }
 
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpLinearStep>() {
+  static const OmpModifierDescriptor desc{
+      /*name=*/"linear-step",
+      /*props=*/
+      {
+          {45, {OmpProperty::Unique}},
+      },
+      /*clauses=*/
+      {
+          {45, {Clause::OMPC_linear}},
+          {52, {}},
+      },
+  };
+  return desc;
+}
+
 template <>
 const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpLoopModifier>() {
   static const OmpModifierDescriptor desc{
@@ -709,12 +726,11 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpStepSimpleModifier>() {
       /*name=*/"step-simple-modifier",
       /*props=*/
       {
-          {45, {OmpProperty::Unique}},
           {52, {OmpProperty::Unique, OmpProperty::Exclusive}},
       },
       /*clauses=*/
       {
-          {45, {Clause::OMPC_linear}},
+          {52, {Clause::OMPC_linear}},
       },
   };
   return desc;
diff --git a/flang/test/Parser/OpenMP/linear-clause-v45.f90 b/flang/test/Parser/OpenMP/linear-clause-v45.f90
new file mode 100644
index 0000000000000..e6d32fce900c2
--- /dev/null
+++ b/flang/test/Parser/OpenMP/linear-clause-v45.f90
@@ -0,0 +1,78 @@
+!RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp -fopenmp-version=45 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s
+!RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp -fopenmp-version=45 %s | FileCheck --check-prefix="PARSE-TREE" %s
+
+subroutine f00(x)
+  integer :: x
+  integer :: i
+  !$omp do linear(x)
+  do i = 1, 10
+    x = x + 1
+  enddo
+  !$omp end do
+end
+
+!UNPARSE: SUBROUTINE f00 (x)
+!UNPARSE:  INTEGER x
+!UNPARSE:  INTEGER i
+!UNPARSE: !$OMP DO  LINEAR(x)
+!UNPARSE:  DO i=1,10
+!UNPARSE:   x = x+1
+!UNPARSE:  END DO
+!UNPARSE: !$OMP END DO
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: OmpBeginDirective
+!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = do
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Linear -> OmpLinearClause
+!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | bool = 'true'
+!PARSE-TREE: | Flags = {}
+!PARSE-TREE: DoConstruct
+
+subroutine f01(x)
+  integer :: x
+  integer :: i
+  !$omp do linear(x : 2)
+  do i = 1, 10
+    x = x + 2
+  enddo
+  !$omp end do
+end
+
+!UNPARSE: SUBROUTINE f01 (x)
+!UNPARSE:  INTEGER x
+!UNPARSE:  INTEGER i
+!UNPARSE: !$OMP DO  LINEAR(x: 2)
+!UNPARSE:  DO i=1,10
+!UNPARSE:   x = x+2
+!UNPARSE:  END DO
+!UNPARSE: !$OMP END DO
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: OmpBeginDirective
+!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = do
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Linear -> OmpLinearClause
+!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | Modifier -> OmpLinearStep -> Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '2'
+!PARSE-TREE: | | bool = 'true'
+!PARSE-TREE: | Flags = {}
+!PARSE-TREE: DoConstruct
+
+subroutine f02(x)
+  integer, allocatable :: x
+  !$omp declare simd linear(ref(x) : 2)
+end
+
+!UNPARSE: SUBROUTINE f02 (x)
+!UNPARSE:  INTEGER, ALLOCATABLE :: x
+!UNPARSE: !$OMP DECLARE SIMD LINEAR(REF(x): 2)
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: OpenMPDeclarativeConstruct -> OmpDeclareSimdDirective -> OmpDirectiveSpecification
+!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare simd
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Linear -> OmpLinearClause
+!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | Modifier -> OmpLinearModifier -> Value = Ref
+!PARSE-TREE: | | Modifier -> OmpLinearStep -> Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '2'
+!PARSE-TREE: | | bool = 'false'
+!PARSE-TREE: | Flags = {}
diff --git a/flang/test/Parser/OpenMP/linear-clause.f90 b/flang/test/Parser/OpenMP/linear-clause-v52.f90
similarity index 100%
rename from flang/test/Parser/OpenMP/linear-clause.f90
rename to flang/test/Parser/OpenMP/linear-clause-v52.f90
diff --git a/flang/test/Semantics/OpenMP/linear-clause02.f90 b/flang/test/Semantics/OpenMP/linear-clause02.f90
index 695d61715820f..d76f921f63694 100644
--- a/flang/test/Semantics/OpenMP/linear-clause02.f90
+++ b/flang/test/Semantics/OpenMP/linear-clause02.f90
@@ -11,3 +11,9 @@ subroutine f01(x)
   !ERROR: An exclusive 'step-simple-modifier' modifier cannot be specified together with a modifier of a different type
   !$omp declare simd linear(uval(x) : 2)
 end
+
+subroutine f02(x)
+  integer :: x
+  !ERROR: 'step-simple-modifier' modifier cannot occur multiple times
+  !$omp declare simd linear(x : 2, 2)
+end
diff --git a/flang/test/Semantics/OpenMP/linear-clause03.f90 b/flang/test/Semantics/OpenMP/linear-clause03.f90
index 3c89f2e93b4ac..5eb4f31537a74 100644
--- a/flang/test/Semantics/OpenMP/linear-clause03.f90
+++ b/flang/test/Semantics/OpenMP/linear-clause03.f90
@@ -23,4 +23,13 @@ subroutine g
   end do
 end
 
+subroutine h
+  integer :: x, i
+  !ERROR: 'linear-step' modifier cannot occur multiple times
+  !$omp do linear(x : 2, 2)
+  do i = 1, 10
+    x = x + 2
+  end do
+end
+
 end module



More information about the flang-commits mailing list