[flang-commits] [flang] [flang][DRAFT] Disable copy-out to INTENT(IN) args (PR #192382)

Eugene Epshteyn via flang-commits flang-commits at lists.llvm.org
Thu Apr 16 03:25:14 PDT 2026


https://github.com/eugeneepshteyn updated https://github.com/llvm/llvm-project/pull/192382

>From 56bb905526eae5b4fc44a3036e7864a11c5d31a6 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Wed, 15 Apr 2026 23:38:36 -0400
Subject: [PATCH 1/4] [flang][DRAFT]

Don't copy out to actual args that themselves happen to be INTENT(IN)
dummy args.
---
 flang/lib/Evaluate/check-expression.cpp | 11 +++++++++++
 flang/test/Lower/call-copy-in-out.f90   | 14 ++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp
index be7db0f20821d..25a6dfa799e9e 100644
--- a/flang/lib/Evaluate/check-expression.cpp
+++ b/flang/lib/Evaluate/check-expression.cpp
@@ -1649,6 +1649,17 @@ std::optional<bool> ActualArgNeedsCopy(const ActualArgument *actual,
     // Expressions are copy-in, but not copy-out.
     return forCopyIn;
   }
+  if (forCopyOut) {
+    // If the actual argument's base object has INTENT(IN) in the caller's
+    // context, copy-out would violate the read-only semantics of INTENT(IN).
+    if (const Expr<SomeType> *expr{actual->UnwrapExpr()}) {
+      if (const Symbol *symbol{GetFirstSymbol(*expr)}) {
+        if (semantics::IsIntentIn(*symbol)) {
+          return false;
+        }
+      }
+    }
+  }
   auto maybeContigActual{IsContiguous(*actual, fc)};
   if (dummyObj) { // Explict interface
     CopyInOutExplicitInterface check{fc, *actual, *dummyObj};
diff --git a/flang/test/Lower/call-copy-in-out.f90 b/flang/test/Lower/call-copy-in-out.f90
index fa2182ac11bac..2a988feeccdc2 100644
--- a/flang/test/Lower/call-copy-in-out.f90
+++ b/flang/test/Lower/call-copy-in-out.f90
@@ -84,6 +84,20 @@ subroutine bar_intent_in(x)
   call bar_intent_in(x)
 end subroutine
 
+! Test copy-out is skipped when the actual argument has INTENT(IN).
+! CHECK-LABEL: func @_QPtest_actual_arg_intent_in(
+subroutine test_actual_arg_intent_in(x)
+  real, intent(in) :: x(:)
+! CHECK: hlfir.copy_in
+! CHECK: fir.call @_QPbar
+! Note: no-op hlfir.copy_out has comma separated list of args.
+! The actual working hlfir.copy_out has "to" in it.
+! CHECK: hlfir.copy_out
+! CHECK-SAME: ,
+! CHECK: return
+  call bar(x)
+end subroutine
+
 ! Test copy-in/copy-out is done for intent(inout)
 ! CHECK-LABEL: func @_QPtest_intent_inout(
 subroutine test_intent_inout(x)

>From 31561cda91bf08495f5d826752c4e27c4e92c57d Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Wed, 15 Apr 2026 23:40:03 -0400
Subject: [PATCH 2/4] clang-format

---
 flang/lib/Evaluate/check-expression.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp
index 25a6dfa799e9e..e6f3350b344be 100644
--- a/flang/lib/Evaluate/check-expression.cpp
+++ b/flang/lib/Evaluate/check-expression.cpp
@@ -1653,7 +1653,7 @@ std::optional<bool> ActualArgNeedsCopy(const ActualArgument *actual,
     // If the actual argument's base object has INTENT(IN) in the caller's
     // context, copy-out would violate the read-only semantics of INTENT(IN).
     if (const Expr<SomeType> *expr{actual->UnwrapExpr()}) {
-      if (const Symbol *symbol{GetFirstSymbol(*expr)}) {
+      if (const Symbol * symbol{GetFirstSymbol(*expr)}) {
         if (semantics::IsIntentIn(*symbol)) {
           return false;
         }

>From def94a375315cecf4e351492f5726be44dff577b Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Wed, 15 Apr 2026 23:46:54 -0400
Subject: [PATCH 3/4] Revert "clang-format"

This reverts commit 31561cda91bf08495f5d826752c4e27c4e92c57d.
---
 flang/lib/Evaluate/check-expression.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp
index e6f3350b344be..25a6dfa799e9e 100644
--- a/flang/lib/Evaluate/check-expression.cpp
+++ b/flang/lib/Evaluate/check-expression.cpp
@@ -1653,7 +1653,7 @@ std::optional<bool> ActualArgNeedsCopy(const ActualArgument *actual,
     // If the actual argument's base object has INTENT(IN) in the caller's
     // context, copy-out would violate the read-only semantics of INTENT(IN).
     if (const Expr<SomeType> *expr{actual->UnwrapExpr()}) {
-      if (const Symbol * symbol{GetFirstSymbol(*expr)}) {
+      if (const Symbol *symbol{GetFirstSymbol(*expr)}) {
         if (semantics::IsIntentIn(*symbol)) {
           return false;
         }

>From cb91cb882979463916cba1e77ed67eac00dd32da Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Thu, 16 Apr 2026 00:02:37 -0400
Subject: [PATCH 4/4] tweaked the test

---
 flang/test/Lower/call-copy-in-out.f90 | 1 +
 1 file changed, 1 insertion(+)

diff --git a/flang/test/Lower/call-copy-in-out.f90 b/flang/test/Lower/call-copy-in-out.f90
index 2a988feeccdc2..e87ae5e294a84 100644
--- a/flang/test/Lower/call-copy-in-out.f90
+++ b/flang/test/Lower/call-copy-in-out.f90
@@ -89,6 +89,7 @@ subroutine bar_intent_in(x)
 subroutine test_actual_arg_intent_in(x)
   real, intent(in) :: x(:)
 ! CHECK: hlfir.copy_in
+! CHECK-SAME: to
 ! CHECK: fir.call @_QPbar
 ! Note: no-op hlfir.copy_out has comma separated list of args.
 ! The actual working hlfir.copy_out has "to" in it.



More information about the flang-commits mailing list