@@ -1712,7 +1712,56 @@ bool MayNeedCopy(const ActualArgument *actual,
17121712 const auto *dummyObj{dummy
17131713 ? std::get_if<characteristics::DummyDataObject>(&dummy->u )
17141714 : nullptr };
1715- return MayNeedCopy (fc, *actual, dummyObj, forCopyOut);
1715+ const bool forCopyIn = !forCopyOut;
1716+ if (!evaluate::IsVariable (*actual)) {
1717+ // Actual argument expressions that aren’t variables are copy-in, but
1718+ // not copy-out.
1719+ return forCopyIn;
1720+ }
1721+ if (dummyObj) { // Explict interface
1722+ CopyInOutExplicitInterface check{fc, *actual, *dummyObj};
1723+ if (forCopyOut && check.HasIntentIn ()) {
1724+ // INTENT(IN) dummy args never need copy-out
1725+ return false ;
1726+ }
1727+ if (forCopyIn && check.HasIntentOut ()) {
1728+ // INTENT(OUT) dummy args never need copy-in
1729+ return false ;
1730+ }
1731+ if (check.PassByValue ()) {
1732+ // Pass by value, always copy-in, never copy-out
1733+ return forCopyIn;
1734+ }
1735+ if (check.HaveCoarrayDifferences ()) {
1736+ return true ;
1737+ }
1738+ // Note: contiguity and polymorphic checks deal with array or assumed rank
1739+ // arguments
1740+ if (!check.HaveArrayOrAssumedRankArgs ()) {
1741+ return false ;
1742+ }
1743+ if (check.HaveContiguityDifferences ()) {
1744+ return true ;
1745+ }
1746+ if (check.HavePolymorphicDifferences ()) {
1747+ return true ;
1748+ }
1749+ } else { // Implicit interface
1750+ if (ExtractCoarrayRef (*actual)) {
1751+ // Coindexed actual args may need copy-in and copy-out with implicit
1752+ // interface
1753+ return true ;
1754+ }
1755+ if (!IsSimplyContiguous (*actual, fc)) {
1756+ // Copy-in: actual arguments that are variables are copy-in when
1757+ // non-contiguous.
1758+ // Copy-out: vector subscripts could refer to duplicate elements, can't
1759+ // copy out.
1760+ return forCopyOut ? !HasVectorSubscript (*actual) : true ;
1761+ }
1762+ }
1763+ // For everything else, no copy-in or copy-out
1764+ return false ;
17161765}
17171766
17181767} // namespace Fortran::evaluate
0 commit comments