[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