[flang-commits] [flang] [flang][openmp] Add semantic checks in THREADPRIVATE/DECLARE TARGET (PR #209084)
Thirumalai Shaktivel via flang-commits
flang-commits at lists.llvm.org
Wed Jul 29 02:52:37 PDT 2026
https://github.com/Thirumalai-Shaktivel updated https://github.com/llvm/llvm-project/pull/209084
>From 8858c64def796ed0d653f4843c07fc9f3781a333 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Wed, 29 Jul 2026 15:21:11 +0530
Subject: [PATCH] [flang][openmp] Add semantic checks in THREADPRIVATE/DECLARE
TARGET
The problem is that the automatic object was used as the
threadprivate argument.
Solution:
>From the documentation (J3/24-007):
> C814 An automatic data object shall not have the SAVE attribute.
> C862 The SAVE attribute shall not be specified for a dummy argument,
> a function result, an automatic data object, or an object
> that is in a common block.
The bare SAVE statement makes any valid local variables tagged
with the SAVE attribute. As the restriction mentioned above, the
automatic object cannot have a SAVE attribute and shall not be
used as the THREADPRIVATE argument. This patch adds semantic
checks for dummy arguments, function results, and automatic data
objects in both THREADPRIVATE and DECLARE TARGET directives.
[flang][OpenMP] Fix DECLARE TARGET to reject distinct result name
When a function uses a distinct result name (e.g. result(res)),
DECLARE TARGET(res) was not diagnosed because ResolveOmpDesignator
rebound it to the procedure, skipping the IsFunctionResult check.
---
flang/lib/Semantics/check-omp-structure.cpp | 12 ++++
flang/lib/Semantics/resolve-directives.cpp | 2 +-
.../Semantics/OpenMP/declare-target02.f90 | 39 +++++++++++
.../test/Semantics/OpenMP/threadprivate02.f90 | 66 +++++++++++++++++++
4 files changed, 118 insertions(+), 1 deletion(-)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index a12e12725dd28..9a74d37ad2713 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1847,6 +1847,18 @@ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
context_.Say(name->source,
"A variable in a %s directive cannot appear in an EQUIVALENCE statement"_err_en_US,
ContextDirectiveAsFortran());
+ } else if (IsDummy(*name->symbol)) {
+ context_.Say(name->source,
+ "A dummy argument cannot appear in %s, because it cannot be given the SAVE attribute"_err_en_US,
+ ContextDirectiveAsFortran());
+ } else if (IsAutomatic(*name->symbol)) {
+ context_.Say(name->source,
+ "An automatic data object cannot appear in %s, because it cannot be given the SAVE attribute"_err_en_US,
+ ContextDirectiveAsFortran());
+ } else if (IsFunctionResult(*name->symbol)) {
+ context_.Say(name->source,
+ "A function result object cannot appear in %s, because it cannot be given the SAVE attribute"_err_en_US,
+ ContextDirectiveAsFortran());
} else if (name->symbol->test(Symbol::Flag::OmpThreadprivate) &&
directive == llvm::omp::Directive::OMPD_declare_target) {
context_.Say(name->source,
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 8b550b1c1d70a..15bb84d7e486f 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -3100,7 +3100,7 @@ void OmpAttributeVisitor::ResolveOmpDesignator(
}
}
if (ompFlag == Symbol::Flag::OmpDeclareTarget) {
- if (symbol->IsFuncResult()) {
+ if (IsFunctionResultWithSameNameAsFunction(*symbol)) {
if (Symbol * func{currScope().symbol()}) {
CHECK(func->IsSubprogram());
func->set(ompFlag);
diff --git a/flang/test/Semantics/OpenMP/declare-target02.f90 b/flang/test/Semantics/OpenMP/declare-target02.f90
index 1dddb62231d82..aea6220ca4fb2 100644
--- a/flang/test/Semantics/OpenMP/declare-target02.f90
+++ b/flang/test/Semantics/OpenMP/declare-target02.f90
@@ -204,3 +204,42 @@ subroutine func5()
!ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block
!$omp declare target link (a5_link)
end
+
+subroutine func6
+ common /foo/ l
+ integer :: l
+ integer :: k(l)
+ save
+ !ERROR: An automatic data object cannot appear in DECLARE TARGET, because it cannot be given the SAVE attribute
+ !$omp declare target(k)
+end subroutine
+
+subroutine func7(a)
+ integer :: a(:)
+ save
+ !ERROR: A dummy argument cannot appear in DECLARE TARGET, because it cannot be given the SAVE attribute
+ !$omp declare target(a)
+end subroutine
+
+integer function func8()
+ save
+ !$omp declare target(func8)
+end function
+
+function func8b() result(res)
+ integer :: res
+ save
+ !ERROR: A function result object cannot appear in DECLARE TARGET, because it cannot be given the SAVE attribute
+ !$omp declare target(res)
+end function
+
+integer function func9()
+ integer :: x
+ common /blk/ x
+ save
+ !ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block
+ !$omp declare target(x)
+
+ ! PASS
+ !$omp declare target(/blk/)
+end function
diff --git a/flang/test/Semantics/OpenMP/threadprivate02.f90 b/flang/test/Semantics/OpenMP/threadprivate02.f90
index 6ac024780aa79..5f5922738ca42 100644
--- a/flang/test/Semantics/OpenMP/threadprivate02.f90
+++ b/flang/test/Semantics/OpenMP/threadprivate02.f90
@@ -86,3 +86,69 @@ subroutine func5()
!ERROR: A variable in a THREADPRIVATE directive cannot be an element of a common block
!$omp threadprivate(a5)
end
+
+subroutine func6
+ common /foo/ l
+ integer :: l
+ integer :: k(l)
+ save
+ !ERROR: An automatic data object cannot appear in THREADPRIVATE, because it cannot be given the SAVE attribute
+ !$omp threadprivate(k)
+end subroutine func6
+
+subroutine func7()
+ integer :: x
+ common /blk/ x
+ save
+ !ERROR: A variable in a THREADPRIVATE directive cannot be an element of a common block
+ !$omp threadprivate(x)
+
+ ! PASS
+ !$omp threadprivate(/blk/)
+end subroutine
+
+module mod_func8
+ integer, save :: x
+contains
+ subroutine func8()
+ !ERROR: The THREADPRIVATE directive and the common block or variable in it must appear in the same declaration section of a scoping unit
+ !$omp threadprivate(x)
+ end subroutine
+end module
+
+subroutine func9()
+ use mod_func8
+ !ERROR: The THREADPRIVATE directive and the common block or variable in it must appear in the same declaration section of a scoping unit
+ !$omp threadprivate(x)
+end subroutine
+
+subroutine func10()
+ !ERROR: A variable that appears in a THREADPRIVATE directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly
+ !$omp threadprivate(x)
+ x = 1
+end subroutine
+
+subroutine func11
+ type :: t
+ integer :: a = 12
+ end type t
+ type(t) :: x
+ integer :: i, j
+
+ save :: x, j
+ !ERROR: A variable that appears in a THREADPRIVATE directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly
+ !$omp threadprivate(x, i, j)
+end subroutine
+
+subroutine func12(a)
+ integer :: a(:)
+ save
+ !ERROR: A dummy argument cannot appear in THREADPRIVATE, because it cannot be given the SAVE attribute
+ !$omp threadprivate(a)
+end subroutine
+
+integer function func13()
+ save
+ !ERROR: A function result object cannot appear in THREADPRIVATE, because it cannot be given the SAVE attribute
+ !$omp threadprivate(func13)
+end function
More information about the flang-commits
mailing list