@@ -1475,13 +1475,9 @@ class CopyInOutExplicitInterface {
14751475 const characteristics::DummyDataObject &dummyObj)
14761476 : fc_{fc}, actual_{actual}, dummyObj_{dummyObj} {}
14771477
1478- // Returns true, if actual and dummy have different contiguity requirements
1479- bool HaveContiguityDifferences() const {
1480- // Check actual contiguity, unless dummy doesn't care
1478+ // Returns true if dummy arg needs to be contiguous
1479+ bool DummyNeedsContiguity() const {
14811480 bool dummyTreatAsArray{dummyObj_.ignoreTKR.test(common::IgnoreTKR::Rank)};
1482- bool actualTreatAsContiguous{
1483- dummyObj_.ignoreTKR.test(common::IgnoreTKR::Contiguous) ||
1484- IsSimplyContiguous(actual_, fc_)};
14851481 bool dummyIsExplicitShape{dummyObj_.type.IsExplicitShape()};
14861482 bool dummyIsAssumedSize{dummyObj_.type.attrs().test(
14871483 characteristics::TypeAndShape::Attr::AssumedSize)};
@@ -1498,24 +1494,20 @@ class CopyInOutExplicitInterface {
14981494 (dummyTreatAsArray && !dummyIsPolymorphic) || dummyIsVoidStar ||
14991495 dummyObj_.attrs.test(
15001496 characteristics::DummyDataObject::Attr::Contiguous)};
1501- return !actualTreatAsContiguous && dummyNeedsContiguity;
1497+ return dummyNeedsContiguity;
15021498 }
15031499
15041500 bool HavePolymorphicDifferences() const {
1505- // These cases require temporary of non-polymorphic type. (For example,
1506- // the actual argument could be polymorphic array of child type,
1507- // while the dummy argument could be non-polymorphic array of parent
1508- // type.)
15091501 if (dummyObj_.ignoreTKR.test(common::IgnoreTKR::Type)) {
15101502 return false;
15111503 }
1512- auto actualType{characteristics::TypeAndShape::Characterize(actual_, fc_)};
1513- if (actualType && actualType->type().IsPolymorphic() &&
1514- ! actualType->type().IsAssumedType() &&
1515- ! dummyObj_.IsPassedByDescriptor(/*isBindC*/ false)) {
1516- // Not passing a descriptor, so will need to make a copy of the data
1517- // with a proper type.
1518- return true;
1504+ if ( auto actualType{
1505+ characteristics::TypeAndShape::Characterize(actual_, fc_)}) {
1506+ bool actualIsPolymorphic{ actualType->type().IsPolymorphic()};
1507+ bool dummyIsPolymorphic{ dummyObj_.type.type().IsPolymorphic()};
1508+ if (actualIsPolymorphic && !dummyIsPolymorphic) {
1509+ return true;
1510+ }
15191511 }
15201512 return false;
15211513 }
@@ -1561,28 +1553,35 @@ class CopyInOutExplicitInterface {
15611553// procedures with explicit interface, it's expected that "dummy" is not null.
15621554// For procedures with implicit interface dummy may be null.
15631555//
1556+ // Returns std::optional<bool> indicating whether the copy is known to be
1557+ // needed (true) or not needed (false); returns std::nullopt if the necessity
1558+ // of the copy is undetermined.
1559+ //
15641560// Note that these copy-in and copy-out checks are done from the caller's
15651561// perspective, meaning that for copy-in the caller need to do the copy
15661562// before calling the callee. Similarly, for copy-out the caller is expected
15671563// to do the copy after the callee returns.
1568- bool MayNeedCopy (const ActualArgument *actual,
1564+ std::optional< bool> ActualArgNeedsCopy (const ActualArgument *actual,
15691565 const characteristics::DummyArgument *dummy, FoldingContext &fc,
15701566 bool forCopyOut) {
1567+ constexpr auto unknown = std::nullopt;
15711568 if (!actual) {
1572- return false ;
1569+ return unknown ;
15731570 }
15741571 if (actual->isAlternateReturn()) {
1575- return false ;
1572+ return unknown ;
15761573 }
15771574 const auto *dummyObj{dummy
15781575 ? std::get_if<characteristics::DummyDataObject>(&dummy->u)
15791576 : nullptr};
15801577 const bool forCopyIn = !forCopyOut;
15811578 if (!evaluate::IsVariable(*actual)) {
1582- // Actual argument expressions that aren’t variables are copy-in, but
1583- // not copy-out.
1579+ // Expressions are copy-in, but not copy-out.
15841580 return forCopyIn;
15851581 }
1582+ auto maybeContigActual{IsContiguous(*actual, fc)};
1583+ bool isContiguousActual{
1584+ maybeContigActual.has_value() && maybeContigActual.value()};
15861585 if (dummyObj) { // Explict interface
15871586 CopyInOutExplicitInterface check{fc, *actual, *dummyObj};
15881587 if (forCopyOut && check.HasIntentIn()) {
@@ -1605,28 +1604,19 @@ bool MayNeedCopy(const ActualArgument *actual,
16051604 if (!check.HaveArrayOrAssumedRankArgs()) {
16061605 return false;
16071606 }
1608- if (check.HaveContiguityDifferences()) {
1609- return true ;
1610- }
1611- if ( check.HavePolymorphicDifferences ()) {
1607+ bool actualTreatAsContiguous{isContiguousActual ||
1608+ dummyObj->ignoreTKR.test(common::IgnoreTKR::Contiguous)} ;
1609+ if ((!actualTreatAsContiguous || check.HavePolymorphicDifferences()) &&
1610+ check.DummyNeedsContiguity ()) {
16121611 return true;
16131612 }
16141613 } else { // Implicit interface
1615- if (ExtractCoarrayRef(*actual)) {
1616- // Coindexed actual args may need copy-in and copy-out with implicit
1617- // interface
1618- return true;
1619- }
1620- if (!IsSimplyContiguous(*actual, fc)) {
1621- // Copy-in: actual arguments that are variables are copy-in when
1622- // non-contiguous.
1623- // Copy-out: vector subscripts could refer to duplicate elements, can't
1624- // copy out.
1625- return !(forCopyOut && HasVectorSubscript(*actual));
1614+ if (isContiguousActual) {
1615+ // Known contiguous, don't copy in/out
1616+ return false;
16261617 }
16271618 }
1628- // For everything else, no copy-in or copy-out
1629- return false;
1619+ return unknown;
16301620}
16311621
16321622} // namespace Fortran::evaluate
0 commit comments