[flang-commits] [flang] [Flang][OpenMP] Reject substring and section-component in affinity (PR #184424)

via flang-commits flang-commits at lists.llvm.org
Thu Mar 5 09:06:12 PST 2026


https://github.com/chichunchen updated https://github.com/llvm/llvm-project/pull/184424

>From 0f2fc0e3e48a3211cc8017de18d74b99f8e4c3ad Mon Sep 17 00:00:00 2001
From: "Chi Chun, Chen" <chichun.chen at hpe.com>
Date: Tue, 3 Mar 2026 13:01:37 -0600
Subject: [PATCH 1/2] [Flang][OpenMP] Reject invalid AFFINITY locators in
 semantics

Add semantic checks for OpenMP AFFINITY clauses to reject
substring designators and structure components, including
iterator forms.
---
 flang/lib/Semantics/check-omp-structure.cpp   | 30 +++++++++-
 .../Semantics/OpenMP/affinity-invalid.f90     | 57 +++++++++++++++++++
 2 files changed, 86 insertions(+), 1 deletion(-)
 create mode 100644 flang/test/Semantics/OpenMP/affinity-invalid.f90

diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 9bdd3d1dbc231..fc82d4bc19d4c 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -5687,12 +5687,40 @@ void OmpStructureChecker::Leave(const parser::OpenMPInvalidDirective &x) {
     RequiresPositiveParameter(llvm::omp::Clause::Y, c.v); \
   }
 
+void OmpStructureChecker::Enter(const parser::OmpClause::Affinity &x) {
+  CheckAllowedClause(llvm::omp::Clause::OMPC_affinity);
+
+  auto &modifiers{OmpGetModifiers(x.v)};
+  if (auto *iter{OmpGetUniqueModifier<parser::OmpIterator>(modifiers)})
+    CheckIteratorModifier(*iter);
+
+  const auto &objects{std::get<parser::OmpObjectList>(x.v.t)};
+  for (const parser::OmpObject &object : objects.v) {
+    if (const parser::Designator *designator{
+            omp::GetDesignatorFromObj(object)}) {
+      if (std::holds_alternative<parser::Substring>(designator->u)) {
+        context_.Say(designator->source,
+            "Substrings are not allowed on AFFINITY clause"_err_en_US);
+        continue;
+      }
+
+      // OpenMP 5.2 3.2.1, unless otherwise specified, a variable
+      // that is part of another variable as a structure element cannot be a
+      // locator list item. AFFINITY does not provide an exception for
+      // structure components.
+      if (parser::Unwrap<parser::StructureComponent>(object)) {
+        context_.Say(designator->source,
+            "Structure components are not allowed in an AFFINITY clause"_err_en_US);
+      }
+    }
+  }
+}
+
 // Following clauses do not have a separate node in parse-tree.h.
 CHECK_SIMPLE_CLAUSE(Absent, OMPC_absent)
 CHECK_SIMPLE_CLAUSE(AcqRel, OMPC_acq_rel)
 CHECK_SIMPLE_CLAUSE(Acquire, OMPC_acquire)
 CHECK_SIMPLE_CLAUSE(AdjustArgs, OMPC_adjust_args)
-CHECK_SIMPLE_CLAUSE(Affinity, OMPC_affinity)
 CHECK_SIMPLE_CLAUSE(AppendArgs, OMPC_append_args)
 CHECK_SIMPLE_CLAUSE(Apply, OMPC_apply)
 CHECK_SIMPLE_CLAUSE(Bind, OMPC_bind)
diff --git a/flang/test/Semantics/OpenMP/affinity-invalid.f90 b/flang/test/Semantics/OpenMP/affinity-invalid.f90
new file mode 100644
index 0000000000000..4d79f61bbefb2
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/affinity-invalid.f90
@@ -0,0 +1,57 @@
+! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52
+
+subroutine affinity_substring()
+  character(len=7) :: a(8)
+  !ERROR: Substrings are not allowed on AFFINITY clause
+  !$omp task affinity(a(2)(2:4))
+    a(1) = "abcdefg"
+  !$omp end task
+end subroutine
+
+subroutine affinity_iterator_substring(n)
+  integer, intent(in) :: n
+  integer :: i
+  character(len=7) :: a(n)
+  !ERROR: Substrings are not allowed on AFFINITY clause
+  !$omp task affinity(iterator(i = 1:n) : a(i)(2:4))
+    a(1) = "abcdefg"
+  !$omp end task
+end subroutine
+
+subroutine affinity_section_component(n)
+  integer, intent(in) :: n
+  type t
+    integer :: x
+  end type
+  type(t) :: a(n)
+  !ERROR: Structure components are not allowed in an AFFINITY clause
+  !$omp task affinity(a(1:n)%x)
+    a(1)%x = 1
+  !$omp end task
+end subroutine
+
+subroutine affinity_iterator_component(n)
+  integer, intent(in) :: n
+  integer :: i
+  type t
+    integer :: x
+  end type
+  type(t) :: a(n)
+  !ERROR: Structure components are not allowed in an AFFINITY clause
+  !$omp task affinity(iterator(i = 1:n) : a(i)%x)
+    a(1)%x = 1
+  !$omp end task
+end subroutine
+
+subroutine affinity_iterator_section_component(n)
+  integer, intent(in) :: n
+  integer :: i
+  type t
+    integer :: x
+  end type
+  type(t) :: a(n)
+  !ERROR: Structure components are not allowed in an AFFINITY clause
+  !$omp task affinity(iterator(i = 1:n) : a(i:i+1)%x)
+    a(1)%x = 1
+  !$omp end task
+end subroutine

>From 3e3977461b6c9916cdb0a153c741666f784555b2 Mon Sep 17 00:00:00 2001
From: "Chi Chun, Chen" <chichun.chen at hpe.com>
Date: Wed, 4 Mar 2026 20:30:16 -0600
Subject: [PATCH 2/2] Modify semantic check for affinity clause

- Add CheckLastPartRef
- Add CheckArraySection
- Add comment why we still need check for substring even if
  CheckArraySection is called
---
 flang/lib/Semantics/check-omp-structure.cpp   | 37 +++++--
 flang/lib/Semantics/check-omp-structure.h     |  2 +
 .../Semantics/OpenMP/affinity-invalid.f90     | 99 ++++++++++++++-----
 3 files changed, 104 insertions(+), 34 deletions(-)

diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index fc82d4bc19d4c..ffb625ad6012f 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -5178,6 +5178,20 @@ void OmpStructureChecker::CheckArraySection(
   }
 }
 
+void OmpStructureChecker::CheckLastPartRefForArraySection(
+    const parser::Designator &designator, llvm::omp::Clause clauseId) {
+  if (!designator.EndsInBareName()) {
+    return;
+  }
+  if (MaybeExpr expr{AnalyzeExpr(context_, designator)}) {
+    if (evaluate::IsArraySection(*expr)) {
+      context_.Say(designator.source,
+          "If a list item is an array section, the last part-ref of the list item must have a section subscript list in %s clause"_err_en_US,
+          parser::ToUpperCaseLetters(getClauseName(clauseId).str()));
+    }
+  }
+}
+
 void OmpStructureChecker::CheckIntentInPointer(
     SymbolSourceMap &symbols, llvm::omp::Clause clauseId) {
   for (auto &[symbol, source] : symbols) {
@@ -5698,20 +5712,25 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Affinity &x) {
   for (const parser::OmpObject &object : objects.v) {
     if (const parser::Designator *designator{
             omp::GetDesignatorFromObj(object)}) {
+      if (const auto *dataRef{GetDataRefFromObj(object)}) {
+        if (const auto *arrayElement{GetArrayElementFromObj(object)}) {
+          CheckArraySection(*arrayElement, GetLastName(*dataRef),
+              llvm::omp::Clause::OMPC_affinity);
+        }
+      }
+
+      // CheckArraySection handles ArrayElement cases,
+      // but true substrings (e.g. a(2)(2:4)) are parser::Substring and bypass
+      // CheckArraySection.
       if (std::holds_alternative<parser::Substring>(designator->u)) {
         context_.Say(designator->source,
             "Substrings are not allowed on AFFINITY clause"_err_en_US);
-        continue;
       }
 
-      // OpenMP 5.2 3.2.1, unless otherwise specified, a variable
-      // that is part of another variable as a structure element cannot be a
-      // locator list item. AFFINITY does not provide an exception for
-      // structure components.
-      if (parser::Unwrap<parser::StructureComponent>(object)) {
-        context_.Say(designator->source,
-            "Structure components are not allowed in an AFFINITY clause"_err_en_US);
-      }
+      // OpenMP 5.2 5.2.5 Array section: if a list item is an array section, the
+      // last part-ref of the list item must have a section subscript list.
+      CheckLastPartRefForArraySection(
+          *designator, llvm::omp::Clause::OMPC_affinity);
     }
   }
 }
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 15a16b7156ded..cd98334ad8662 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -359,6 +359,8 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
       const parser::OmpObjectList &ompObjectList, llvm::omp::Clause clauseId);
   void CheckArraySection(const parser::ArrayElement &arrayElement,
       const parser::Name &name, const llvm::omp::Clause clause);
+  void CheckLastPartRefForArraySection(
+      const parser::Designator &designator, llvm::omp::Clause clauseId);
   void CheckSharedBindingInOuterContext(
       const parser::OmpObjectList &ompObjectList);
   void CheckIfContiguous(const parser::OmpObject &object);
diff --git a/flang/test/Semantics/OpenMP/affinity-invalid.f90 b/flang/test/Semantics/OpenMP/affinity-invalid.f90
index 4d79f61bbefb2..32e726bada937 100644
--- a/flang/test/Semantics/OpenMP/affinity-invalid.f90
+++ b/flang/test/Semantics/OpenMP/affinity-invalid.f90
@@ -18,40 +18,89 @@ subroutine affinity_iterator_substring(n)
   !$omp end task
 end subroutine
 
-subroutine affinity_section_component(n)
-  integer, intent(in) :: n
+subroutine affinity_iterator_section_component(n, m)
+  integer, intent(in) :: n, m
   type t
-    integer :: x
+    integer :: x(10)
+    integer :: y
   end type
-  type(t) :: a(n)
-  !ERROR: Structure components are not allowed in an AFFINITY clause
-  !$omp task affinity(a(1:n)%x)
-    a(1)%x = 1
+  type(t) :: a(10)
+
+  !ERROR: Subscripts of component 'x' of rank-1 derived type array have rank 1 but must all be scalar
+  !$omp task affinity(a(1:n)%x(1:m))
+  !$omp end task
+
+  !ERROR: If a list item is an array section, the last part-ref of the list item must have a section subscript list in AFFINITY clause
+  !$omp task affinity(a(1:n)%y)
   !$omp end task
 end subroutine
 
-subroutine affinity_iterator_component(n)
+subroutine affinity_section_bad_stride(n)
   integer, intent(in) :: n
-  integer :: i
-  type t
-    integer :: x
-  end type
-  type(t) :: a(n)
-  !ERROR: Structure components are not allowed in an AFFINITY clause
-  !$omp task affinity(iterator(i = 1:n) : a(i)%x)
-    a(1)%x = 1
+  integer :: a(n)
+  !ERROR: 'a' in AFFINITY clause must have a positive stride
+  !$omp task affinity(a(1:n:-1))
   !$omp end task
 end subroutine
 
-subroutine affinity_iterator_section_component(n)
+subroutine affinity_section_zero_size(n)
   integer, intent(in) :: n
-  integer :: i
-  type t
-    integer :: x
-  end type
-  type(t) :: a(n)
-  !ERROR: Structure components are not allowed in an AFFINITY clause
-  !$omp task affinity(iterator(i = 1:n) : a(i:i+1)%x)
-    a(1)%x = 1
+  integer :: a(n)
+  !ERROR: 'a' in AFFINITY clause is a zero size array section
+  !$omp task affinity(a(5:2))
+  !$omp end task
+end subroutine
+
+
+subroutine affinity_iterator_noninteger_iv()
+  integer :: x(10)
+  !ERROR: The iterator variable must be of integer type
+  !$omp task affinity(iterator(real :: i = 1:10): x(1))
+  !$omp end task
+end subroutine
+
+subroutine affinity_iterator_missing_begin()
+  integer :: x(10)
+  !ERROR: The begin and end expressions in iterator range-specification are mandatory
+  !$omp task affinity(iterator(integer :: i = :10:1): x(1))
+  !$omp end task
+end subroutine
+
+subroutine affinity_iterator_step_zero()
+  integer :: x(10)
+  !WARNING: The step value in the iterator range is 0
+  !$omp task affinity(iterator(integer :: i = 1:10:0): x(1))
+  !$omp end task
+end subroutine
+
+subroutine affinity_iterator_section_bad_stride(n)
+  integer, intent(in) :: n
+  integer :: a(n)
+  !ERROR: 'a' in AFFINITY clause must have a positive stride
+  !$omp task affinity(iterator(i = 1:n): a(i:n:-1))
+  !$omp end task
+end subroutine
+
+subroutine affinity_substring_like_single_index()
+  character(len=7) :: s
+  !PORTABILITY: The use of substrings in OpenMP argument lists has been disallowed since OpenMP 5.2.
+  !ERROR: Substrings must be in the form parent-string(lb:ub)
+  !$omp task affinity(s(2))
+  !$omp end task
+end subroutine
+
+subroutine affinity_substring_like_step()
+  character(len=7) :: s
+  !PORTABILITY: The use of substrings in OpenMP argument lists has been disallowed since OpenMP 5.2.
+  !ERROR: Cannot specify a step for a substring
+  !$omp task affinity(s(2:6:2))
+  !$omp end task
+end subroutine
+
+subroutine affinity_section_step_zero()
+  integer :: a(10)
+  !ERROR: 'a' in AFFINITY clause must have a positive stride
+  !ERROR: Stride of triplet must not be zero
+  !$omp task affinity(a(1:10:0))
   !$omp end task
 end subroutine



More information about the flang-commits mailing list