[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
Tue Jul 21 02:23:56 PDT 2026


https://github.com/Thirumalai-Shaktivel updated https://github.com/llvm/llvm-project/pull/209084

>From 764254f59b1a24a9d269c9229a7b631b7d3101cc Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Thu, 14 May 2026 15:51:38 +0530
Subject: [PATCH 1/3] [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/lib/Semantics/check-omp-structure.cpp   | 12 ++++
 .../Semantics/OpenMP/declare-target02.f90     | 32 +++++++++
 .../test/Semantics/OpenMP/threadprivate02.f90 | 66 +++++++++++++++++++
 3 files changed, 110 insertions(+)

diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 68d7a166be0fb..137b6b35f15d5 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1786,6 +1786,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/test/Semantics/OpenMP/declare-target02.f90 b/flang/test/Semantics/OpenMP/declare-target02.f90
index 1dddb62231d82..098b8f8b178ff 100644
--- a/flang/test/Semantics/OpenMP/declare-target02.f90
+++ b/flang/test/Semantics/OpenMP/declare-target02.f90
@@ -204,3 +204,35 @@ 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
+
+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..b49af65843d2c 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

>From 1383b3612a94c1d096fb191aad41060126f90e38 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Mon, 20 Jul 2026 16:43:02 +0530
Subject: [PATCH 2/3] [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.

Change-Id: I0be87ec91304871a365fe2128e52a96c44cecef2
---
 flang/lib/Semantics/resolve-directives.cpp       | 2 +-
 flang/test/Semantics/OpenMP/declare-target02.f90 | 7 +++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 51ad81bcbc2ef..abc12d8200194 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -3076,7 +3076,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 098b8f8b178ff..51e6ed9cf3637 100644
--- a/flang/test/Semantics/OpenMP/declare-target02.f90
+++ b/flang/test/Semantics/OpenMP/declare-target02.f90
@@ -226,6 +226,13 @@ integer function func8()
     !$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

>From 9f4f9319517a9a318d49af3982423452236ff304 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Tue, 21 Jul 2026 14:52:24 +0530
Subject: [PATCH 3/3] Use :: in variable declarations in tests

Change-Id: I8a7ad5c77896f65be93b5c66bb92ce997e1a5c32
---
 flang/test/Semantics/OpenMP/declare-target02.f90 | 4 ++--
 flang/test/Semantics/OpenMP/threadprivate02.f90  | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/flang/test/Semantics/OpenMP/declare-target02.f90 b/flang/test/Semantics/OpenMP/declare-target02.f90
index 51e6ed9cf3637..aea6220ca4fb2 100644
--- a/flang/test/Semantics/OpenMP/declare-target02.f90
+++ b/flang/test/Semantics/OpenMP/declare-target02.f90
@@ -207,8 +207,8 @@ subroutine func5()
 
 subroutine func6
     common /foo/ l
-    integer l
-    integer k(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)
diff --git a/flang/test/Semantics/OpenMP/threadprivate02.f90 b/flang/test/Semantics/OpenMP/threadprivate02.f90
index b49af65843d2c..5f5922738ca42 100644
--- a/flang/test/Semantics/OpenMP/threadprivate02.f90
+++ b/flang/test/Semantics/OpenMP/threadprivate02.f90
@@ -89,8 +89,8 @@ subroutine func5()
 
 subroutine func6
     common /foo/ l
-    integer l
-    integer k(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)



More information about the flang-commits mailing list