[flang-commits] [flang] [flang][acc] Disallow duplicate variables in use_device clause (PR #176217)

Razvan Lupusoru via flang-commits flang-commits at lists.llvm.org
Thu Jan 15 10:57:43 PST 2026


https://github.com/razvanlupusoru updated https://github.com/llvm/llvm-project/pull/176217

>From a6ee4e0c7530b16a4bfd43a6ac8408e87ef541dc Mon Sep 17 00:00:00 2001
From: Razvan Lupusoru <rlupusoru at nvidia.com>
Date: Thu, 15 Jan 2026 10:33:06 -0800
Subject: [PATCH 1/4] [flang][acc] Disallow duplicate variables in use_device
 clause

Add a semantic check to detect when the same variable appears multiple
times in `use_device` clauses on the same `host_data` directive. While
the OpenACC specification does not explicitly prohibit this, allowing
duplicates is likely a user error and provides no additional semantics.

A similar restriction was already in place for `private`,
`firstprivate`, and `reduction` clauses on compute constructs. This change
extends that behavior to `use_device` on `host_data`.

Error message:
  "'<var>' appears in more than one USE_DEVICE clause on the same
   HOST_DATA directive"
---
 flang/docs/OpenACC.md                         |  6 ++++
 flang/lib/Semantics/resolve-directives.cpp    | 32 +++++++++++++++++++
 .../test/Semantics/OpenACC/acc-host-data.f90  |  8 +++++
 3 files changed, 46 insertions(+)

diff --git a/flang/docs/OpenACC.md b/flang/docs/OpenACC.md
index f1fe69e57bf37..a83c6b233152a 100644
--- a/flang/docs/OpenACC.md
+++ b/flang/docs/OpenACC.md
@@ -30,6 +30,12 @@ local:
 * The OpenACC specification disallows a variable appearing multiple times in
   clauses of `!$acc declare` directives for a function, subroutine, program,
   or module, but it is allowed with a warning when same clause is used.
+* The OpenACC specification does not disallow the same variable from appearing
+  in multiple data clauses, but this is disallowed for variables appearing in
+  `private`, `firstprivate`, or `reduction` clauses.
+* The OpenACC specification does not disallow the same variable from appearing
+  multiple times in a `use_device` clause on a `host_data` construct, but this
+  is disallowed.
 
 ## Remarks about incompatibilities with other implementations
 * Array element references in the data clauses are equivalent to array sections
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 6467abf872c16..48793e6c08319 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -334,6 +334,28 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
 
   bool Pre(const parser::AccClause::UseDevice &x) {
     ResolveAccObjectList(x.v, Symbol::Flag::AccUseDevice);
+    // use_device is only valid on host_data directive
+    assert(GetContext().directive == llvm::acc::Directive::ACCD_host_data &&
+        "use_device clause is only valid on host_data directive");
+    // Check for duplicate use_device variables
+    for (const auto &accObject : x.v.v) {
+      if (const auto *designator{
+              std::get_if<parser::Designator>(&accObject.u)}) {
+        if (const auto *name{
+                parser::GetDesignatorNameIfDataRef(*designator)}) {
+          if (name->symbol) {
+            if (HasUseDeviceObject(*name->symbol)) {
+              context_.Say(name->source,
+                  "'%s' appears in more than one USE_DEVICE clause "
+                  "on the same HOST_DATA directive"_err_en_US,
+                  name->ToString());
+            } else {
+              AddUseDeviceObject(*name->symbol);
+            }
+          }
+        }
+      }
+    }
     return false;
   }
 
@@ -379,6 +401,15 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
       const llvm::acc::Clause clause, const parser::AccObjectList &objectList);
   void AddRoutineInfoToSymbol(
       Symbol &, const parser::OpenACCRoutineConstruct &);
+
+  // Track use_device variables
+  void AddUseDeviceObject(SymbolRef object) { useDeviceObjects_.insert(object); }
+  void ClearUseDeviceObjects() { useDeviceObjects_.clear(); }
+  bool HasUseDeviceObject(const Symbol &object) {
+    return useDeviceObjects_.find(object) != useDeviceObjects_.end();
+  }
+  UnorderedSymbolSet useDeviceObjects_;
+
   Scope *topScope_;
 };
 
@@ -1185,6 +1216,7 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCBlockConstruct &x) {
     break;
   }
   ClearDataSharingAttributeObjects();
+  ClearUseDeviceObjects();
   return true;
 }
 
diff --git a/flang/test/Semantics/OpenACC/acc-host-data.f90 b/flang/test/Semantics/OpenACC/acc-host-data.f90
index f5aa4d7f320ff..e6d76e373347b 100644
--- a/flang/test/Semantics/OpenACC/acc-host-data.f90
+++ b/flang/test/Semantics/OpenACC/acc-host-data.f90
@@ -38,4 +38,12 @@ program openacc_host_data_validity
   !$acc host_data use_device(aa, bb) if(.true.) if(ifCondition)
   !$acc end host_data
 
+  !ERROR: 'aa' appears in more than one USE_DEVICE clause on the same HOST_DATA directive
+  !$acc host_data use_device(aa) use_device(aa)
+  !$acc end host_data
+
+  !ERROR: 'bb' appears in more than one USE_DEVICE clause on the same HOST_DATA directive
+  !$acc host_data use_device(bb, bb)
+  !$acc end host_data
+
 end program openacc_host_data_validity

>From d241455390bd9386a207b5b4ad6172483ef2c3d5 Mon Sep 17 00:00:00 2001
From: Razvan Lupusoru <rlupusoru at nvidia.com>
Date: Thu, 15 Jan 2026 10:44:30 -0800
Subject: [PATCH 2/4] Fix format

---
 flang/lib/Semantics/resolve-directives.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 48793e6c08319..682f8f29b490b 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -341,8 +341,7 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
     for (const auto &accObject : x.v.v) {
       if (const auto *designator{
               std::get_if<parser::Designator>(&accObject.u)}) {
-        if (const auto *name{
-                parser::GetDesignatorNameIfDataRef(*designator)}) {
+        if (const auto *name{parser::GetDesignatorNameIfDataRef(*designator)}) {
           if (name->symbol) {
             if (HasUseDeviceObject(*name->symbol)) {
               context_.Say(name->source,
@@ -403,7 +402,9 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
       Symbol &, const parser::OpenACCRoutineConstruct &);
 
   // Track use_device variables
-  void AddUseDeviceObject(SymbolRef object) { useDeviceObjects_.insert(object); }
+  void AddUseDeviceObject(SymbolRef object) {
+    useDeviceObjects_.insert(object);
+  }
   void ClearUseDeviceObjects() { useDeviceObjects_.clear(); }
   bool HasUseDeviceObject(const Symbol &object) {
     return useDeviceObjects_.find(object) != useDeviceObjects_.end();

>From f3283babb0d826bcec20f1c1ff6c0cd1037883c6 Mon Sep 17 00:00:00 2001
From: Razvan Lupusoru <rlupusoru at nvidia.com>
Date: Thu, 15 Jan 2026 10:57:15 -0800
Subject: [PATCH 3/4] Move error checking into AddUseDeviceObject

---
 flang/lib/Semantics/resolve-directives.cpp | 25 ++++++++++------------
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 682f8f29b490b..b3c4da396fb88 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -343,14 +343,7 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
               std::get_if<parser::Designator>(&accObject.u)}) {
         if (const auto *name{parser::GetDesignatorNameIfDataRef(*designator)}) {
           if (name->symbol) {
-            if (HasUseDeviceObject(*name->symbol)) {
-              context_.Say(name->source,
-                  "'%s' appears in more than one USE_DEVICE clause "
-                  "on the same HOST_DATA directive"_err_en_US,
-                  name->ToString());
-            } else {
-              AddUseDeviceObject(*name->symbol);
-            }
+            AddUseDeviceObject(*name->symbol, *name);
           }
         }
       }
@@ -401,14 +394,18 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
   void AddRoutineInfoToSymbol(
       Symbol &, const parser::OpenACCRoutineConstruct &);
 
-  // Track use_device variables
-  void AddUseDeviceObject(SymbolRef object) {
-    useDeviceObjects_.insert(object);
+  // Track use_device variables and check for duplicates.
+  // Emits an error if the object was already added.
+  void AddUseDeviceObject(const Symbol &object, const parser::Name &name) {
+    auto result = useDeviceObjects_.insert(object);
+    if (!result.second) {
+      context_.Say(name.source,
+          "'%s' appears in more than one USE_DEVICE clause "
+          "on the same HOST_DATA directive"_err_en_US,
+          name.ToString());
+    }
   }
   void ClearUseDeviceObjects() { useDeviceObjects_.clear(); }
-  bool HasUseDeviceObject(const Symbol &object) {
-    return useDeviceObjects_.find(object) != useDeviceObjects_.end();
-  }
   UnorderedSymbolSet useDeviceObjects_;
 
   Scope *topScope_;

>From 403e0bc1b28146be0c331bcc918d662a7ad0dc41 Mon Sep 17 00:00:00 2001
From: Razvan Lupusoru <rlupusoru at nvidia.com>
Date: Thu, 15 Jan 2026 10:57:28 -0800
Subject: [PATCH 4/4] Avoid repeated use of disallow

---
 flang/docs/OpenACC.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/flang/docs/OpenACC.md b/flang/docs/OpenACC.md
index a83c6b233152a..85e9430a203ec 100644
--- a/flang/docs/OpenACC.md
+++ b/flang/docs/OpenACC.md
@@ -30,10 +30,10 @@ local:
 * The OpenACC specification disallows a variable appearing multiple times in
   clauses of `!$acc declare` directives for a function, subroutine, program,
   or module, but it is allowed with a warning when same clause is used.
-* The OpenACC specification does not disallow the same variable from appearing
+* The OpenACC specification does not prohibit the same variable from appearing
   in multiple data clauses, but this is disallowed for variables appearing in
   `private`, `firstprivate`, or `reduction` clauses.
-* The OpenACC specification does not disallow the same variable from appearing
+* The OpenACC specification does not prohibit the same variable from appearing
   multiple times in a `use_device` clause on a `host_data` construct, but this
   is disallowed.
 



More information about the flang-commits mailing list