[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:34:46 PST 2026


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

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"

>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] [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



More information about the flang-commits mailing list