[flang-commits] [flang] [flang][CUDA] Preserve data attrs on assignment RHS (PR #207849)
via flang-commits
flang-commits at lists.llvm.org
Mon Jul 6 14:46:24 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: Andre Kuhlenschmidt (akuhlens)
<details>
<summary>Changes</summary>
Treat a parenthesized variable as a source of CUDA data attributes when checking dummy/actual argument compatibility. Defined assignment parenthesizes non-VALUE RHS actuals to preserve value semantics, but the CUDA address space of the referenced data is unchanged by that materialization.
Add CUDA semantics coverage for a device RHS selected through defined assignment.
---
Full diff: https://github.com/llvm/llvm-project/pull/207849.diff
2 Files Affected:
- (modified) flang/lib/Semantics/check-call.cpp (+34-1)
- (added) flang/test/Semantics/CUDA/cuf-defined-assignment-rhs.cuf (+34)
``````````diff
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index 16c1e166ded66..060459ea0d495 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -27,6 +27,37 @@ namespace characteristics = Fortran::evaluate::characteristics;
namespace Fortran::semantics {
+template <typename A> static bool IsParenthesizedVariable(const A &) {
+ return false;
+}
+
+template <typename T>
+static bool IsParenthesizedVariable(const evaluate::Expr<T> &expr) {
+ if (const auto *parens{
+ evaluate::UnwrapExpr<evaluate::Parentheses<T>>(expr)}) {
+ return evaluate::IsVariable(parens->left());
+ }
+ return false;
+}
+
+template <evaluate::TypeCategory CAT>
+static bool IsParenthesizedVariable(
+ const evaluate::Expr<evaluate::SomeKind<CAT>> &expr) {
+ return common::visit(
+ [](const auto &x) { return IsParenthesizedVariable(x); }, expr.u);
+}
+
+static bool IsParenthesizedVariable(
+ const evaluate::Expr<evaluate::SomeType> &expr) {
+ return common::visit(
+ [](const auto &x) { return IsParenthesizedVariable(x); }, expr.u);
+}
+
+static bool IsVariableOrParenthesizedVariable(
+ const evaluate::Expr<evaluate::SomeType> &expr) {
+ return evaluate::IsVariable(expr) || IsParenthesizedVariable(expr);
+}
+
void CheckImplicitInterfaceArgKeywords(
const evaluate::ActualArgument &arg, parser::ContextualMessages &messages) {
auto restorer{
@@ -1124,7 +1155,9 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
!FindOpenACCConstructContaining(scope)) {
std::optional<common::CUDADataAttr> actualDataAttr, dummyDataAttr;
// For a%b%c, the last symbol with a CUDA data attribute wins
- if (actualIsVariable) {
+ // Parentheses here mean expression/copy semantics, but CUDA address space
+ // attributes remain stable when a variable is materialized as a copy.
+ if (IsVariableOrParenthesizedVariable(actual)) {
for (const Symbol &s : evaluate::GetSymbolVector(actual)) {
if (const auto *object{s.detailsIf<ObjectEntityDetails>()}) {
if (auto cudaAttr{object->cudaDataAttr()}) {
diff --git a/flang/test/Semantics/CUDA/cuf-defined-assignment-rhs.cuf b/flang/test/Semantics/CUDA/cuf-defined-assignment-rhs.cuf
new file mode 100644
index 0000000000000..bd0ab5f7c3068
--- /dev/null
+++ b/flang/test/Semantics/CUDA/cuf-defined-assignment-rhs.cuf
@@ -0,0 +1,34 @@
+! RUN: %python %S/../test_errors.py %s %flang_fc1
+
+module m
+ type box
+ integer :: n
+ end type
+
+ interface assignment(=)
+ module procedure assign_host
+ module procedure assign_device
+ end interface
+
+contains
+ subroutine assign_host(lhs, rhs)
+ type(box), intent(inout) :: lhs
+ real, intent(in) :: rhs(:)
+ end subroutine
+
+ subroutine assign_device(lhs, rhs)
+ type(box), intent(inout) :: lhs
+ real, device, intent(in) :: rhs(:)
+ end subroutine
+end module
+
+subroutine test
+ use m
+ type(box) :: lhs
+ real :: host(4)
+ real, device, allocatable :: dev(:)
+ allocate(dev(4))
+
+ lhs = host
+ lhs = dev
+end subroutine
``````````
</details>
https://github.com/llvm/llvm-project/pull/207849
More information about the flang-commits
mailing list