[flang-commits] [flang] a73bdba - [flang][OpenMP] Update semantic checks for LINEAR clause (#177055)

via flang-commits flang-commits at lists.llvm.org
Tue Jan 27 06:35:31 PST 2026


Author: Krzysztof Parzyszek
Date: 2026-01-27T08:35:26-06:00
New Revision: a73bdba2e80c6cff91ec135b5502909b14934d68

URL: https://github.com/llvm/llvm-project/commit/a73bdba2e80c6cff91ec135b5502909b14934d68
DIFF: https://github.com/llvm/llvm-project/commit/a73bdba2e80c6cff91ec135b5502909b14934d68.diff

LOG: [flang][OpenMP] Update semantic checks for LINEAR clause (#177055)

Fixes https://github.com/llvm/llvm-project/issues/173980.

In particular, make step-simple-modifier be compatible (i.e. not
exclusive) for OpenMP spec versions < 52, and update the modifier
validity checks for the construct on which the clause is located.

Added: 
    flang/test/Semantics/OpenMP/linear-clause03.f90

Modified: 
    flang/lib/Semantics/check-omp-loop.cpp
    flang/lib/Semantics/openmp-modifiers.cpp
    flang/test/Semantics/OpenMP/clause-validity01.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index 3ee18c8e449e5..20c52ba3417ad 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -775,54 +775,62 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
     auto &modifiers{OmpGetModifiers(x.v)};
     linearMod = OmpGetUniqueModifier<parser::OmpLinearModifier>(modifiers);
     if (linearMod) {
-      // 2.7 Loop Construct Restriction
-      if ((llvm::omp::allDoSet | llvm::omp::allSimdSet).test(dir)) {
-        context_.Say(clauseSource,
-            "A modifier may not be specified in a LINEAR clause on the %s directive"_err_en_US,
-            ContextDirectiveAsFortran());
-        // Don't return early - continue to check other restrictions
-      }
-
       auto &desc{OmpGetDescriptor<parser::OmpLinearModifier>()};
-      for (auto &[symbol, source] : symbols) {
-        if (linearMod->v != parser::OmpLinearModifier::Value::Ref) {
-          CheckIntegerNoRef(symbol, source);
-        } else {
-          if (!IsAllocatable(*symbol) && !IsAssumedShape(*symbol) &&
-              !IsPolymorphic(*symbol)) {
-            context_.Say(source,
-                "The list item `%s` specified with the REF '%s' must be polymorphic variable, assumed-shape array, or a variable with the `ALLOCATABLE` attribute"_err_en_US,
-                symbol->name(), desc.name.str());
-          }
+      parser::CharBlock modSource{OmpGetModifierSource(modifiers, linearMod)};
+      bool valid{true};
+
+      if (version < 52) {
+        // Modifiers on LINEAR are only allowed on DECLARE SIMD
+        if (dir != llvm::omp::Directive::OMPD_declare_simd) {
+          context_.Say(modSource,
+              "A modifier may not be specified in a LINEAR clause on the %s directive"_err_en_US,
+              parser::ToUpperCaseLetters(getDirectiveName(dir)));
+          valid = false;
         }
+      } else {
         if (linearMod->v == parser::OmpLinearModifier::Value::Ref ||
             linearMod->v == parser::OmpLinearModifier::Value::Uval) {
-          if (!IsDummy(*symbol) || IsValue(*symbol)) {
-            context_.Say(source,
-                "If the `%s` is REF or UVAL, the list item '%s' must be a dummy argument without the VALUE attribute"_err_en_US,
-                desc.name.str(), symbol->name());
+          if (dir != llvm::omp::Directive::OMPD_declare_simd) {
+            context_.Say(modSource,
+                "A REF or UVAL '%s' may not be specified in a LINEAR clause on the %s directive"_err_en_US,
+                desc.name.str(),
+                parser::ToUpperCaseLetters(getDirectiveName(dir)));
+            valid = false;
           }
         }
-      } // for (symbol, source)
-
-      if (version >= 52 && !std::get</*PostModified=*/bool>(x.v.t)) {
-        context_.Say(OmpGetModifierSource(modifiers, linearMod),
-            "The 'modifier(<list>)' syntax is deprecated in %s, use '<list> : modifier' instead"_warn_en_US,
-            ThisVersion(version));
+        if (!std::get</*PostModified=*/bool>(x.v.t)) {
+          context_.Say(modSource,
+              "The 'modifier(<list>)' syntax is deprecated in %s, use '<list> : modifier' instead"_warn_en_US,
+              ThisVersion(version));
+        }
       }
-    }
-  }
 
-  // OpenMP 5.2: Ordered clause restriction
-  if (const auto *clause{
-          FindClause(GetContext(), llvm::omp::Clause::OMPC_ordered)}) {
-    const auto &orderedClause{std::get<parser::OmpClause::Ordered>(clause->u)};
-    if (orderedClause.v) {
-      return;
+      if (valid) {
+        for (auto &[symbol, source] : symbols) {
+          if (linearMod->v != parser::OmpLinearModifier::Value::Ref) {
+            CheckIntegerNoRef(symbol, source);
+          } else {
+            if (!IsAllocatable(*symbol) && !IsAssumedShape(*symbol) &&
+                !IsPolymorphic(*symbol)) {
+              context_.Say(source,
+                  "The list item `%s` specified with the REF '%s' must be polymorphic variable, assumed-shape array, or a variable with the `ALLOCATABLE` attribute"_err_en_US,
+                  symbol->name(), desc.name.str());
+            }
+          }
+          if (linearMod->v == parser::OmpLinearModifier::Value::Ref ||
+              linearMod->v == parser::OmpLinearModifier::Value::Uval) {
+            if (!IsDummy(*symbol) || IsValue(*symbol)) {
+              context_.Say(source,
+                  "If the `%s` is REF or UVAL, the list item '%s' must be a dummy argument without the VALUE attribute"_err_en_US,
+                  desc.name.str(), symbol->name());
+            }
+          }
+        } // for (symbol, source)
+      }
     }
   }
 
-  // OpenMP 5.2: Linear clause Restrictions
+  // Linear clause restrictions.
   for (auto &[symbol, source] : symbols) {
     // Check that the list item is a scalar variable (rank 0)
     // For declare simd with REF modifier, arrays are allowed

diff  --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp
index bf5a135c4ba00..b6a6d476ceec6 100644
--- a/flang/lib/Semantics/openmp-modifiers.cpp
+++ b/flang/lib/Semantics/openmp-modifiers.cpp
@@ -693,7 +693,8 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpStepSimpleModifier>() {
       /*name=*/"step-simple-modifier",
       /*props=*/
       {
-          {45, {OmpProperty::Unique, OmpProperty::Exclusive}},
+          {45, {OmpProperty::Unique}},
+          {52, {OmpProperty::Unique, OmpProperty::Exclusive}},
       },
       /*clauses=*/
       {

diff  --git a/flang/test/Semantics/OpenMP/clause-validity01.f90 b/flang/test/Semantics/OpenMP/clause-validity01.f90
index 6c9e9c6a5e07c..9371a2fc6fd58 100644
--- a/flang/test/Semantics/OpenMP/clause-validity01.f90
+++ b/flang/test/Semantics/OpenMP/clause-validity01.f90
@@ -200,7 +200,6 @@
      a = 3.14
   enddo
 
-  !ERROR: A modifier may not be specified in a LINEAR clause on the DO directive
   !$omp do linear(b: val)
   do i = 1, N
      a = 3.14
@@ -221,6 +220,7 @@
   !ERROR: Clause LINEAR is not allowed if clause ORDERED appears on the DO directive
   !ERROR: The parameter of the ORDERED clause must be a constant positive integer expression
   !ERROR: 'b' appears in more than one data-sharing clause on the same OpenMP directive
+  !ERROR: The list item 'a' specified without the REF 'linear-modifier' must be of INTEGER type
   !$omp do ordered(1-1) private(b) linear(b) linear(a)
   do i = 1, N
      a = 3.14
@@ -228,6 +228,7 @@
 
   !ERROR: Clause LINEAR is not allowed if clause ORDERED appears on the DO directive
   !ERROR: The parameter of the ORDERED clause must be a constant positive integer expression
+  !ERROR: The list item 'a' specified without the REF 'linear-modifier' must be of INTEGER type
   !$omp do ordered(1-1) linear(a)
   do i = 1, N
      a = 3.14
@@ -407,8 +408,8 @@
 !                              do-clause
 
   !ERROR: At most one PROC_BIND clause can appear on the PARALLEL DO directive
-  !ERROR: A modifier may not be specified in a LINEAR clause on the PARALLEL DO directive
-  !$omp parallel do proc_bind(master) proc_bind(close) linear(b: val)
+  !ERROR: A REF or UVAL 'linear-modifier' may not be specified in a LINEAR clause on the PARALLEL DO directive
+  !$omp parallel do proc_bind(master) proc_bind(close) linear(b: uval)
   do i = 1, N
      a = 3.14
   enddo

diff  --git a/flang/test/Semantics/OpenMP/linear-clause03.f90 b/flang/test/Semantics/OpenMP/linear-clause03.f90
new file mode 100644
index 0000000000000..124eb65701e26
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/linear-clause03.f90
@@ -0,0 +1,23 @@
+!RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -fopenmp-version=50
+
+module m
+
+interface
+  subroutine f(x, y)
+    integer, allocatable :: x
+    integer :: y
+    !$omp declare simd(f) linear(ref(x) : 1) linear(uval(y))
+  end
+end interface
+
+contains
+
+subroutine g
+  integer :: i
+  !ERROR: Clause LINEAR is not allowed if clause ORDERED appears on the DO directive
+  !$omp do ordered(1) linear(i)
+  do i = 1, 10
+  end do
+end
+
+end module


        


More information about the flang-commits mailing list