@@ -1478,13 +1478,12 @@ class CopyInOutExplicitInterface {
14781478 const characteristics::DummyDataObject &dummyObj)
14791479 : fc_{fc}, actual_{actual}, dummyObj_{dummyObj} {}
14801480
1481- // Returns true, if actual and dummy have different contiguity requirements
1482- bool HaveContiguityDifferences () const {
1483- // Check actual contiguity, unless dummy doesn't care
1481+ // Returns true if dummy arg needs to be contiguous
1482+ bool DummyNeedsContiguity () const {
1483+ if (dummyObj_.ignoreTKR .test (common::IgnoreTKR::Contiguous)) {
1484+ return false ;
1485+ }
14841486 bool dummyTreatAsArray{dummyObj_.ignoreTKR .test (common::IgnoreTKR::Rank)};
1485- bool actualTreatAsContiguous{
1486- dummyObj_.ignoreTKR .test (common::IgnoreTKR::Contiguous) ||
1487- IsSimplyContiguous (actual_, fc_)};
14881487 bool dummyIsExplicitShape{dummyObj_.type .IsExplicitShape ()};
14891488 bool dummyIsAssumedSize{dummyObj_.type .attrs ().test (
14901489 characteristics::TypeAndShape::Attr::AssumedSize)};
@@ -1501,32 +1500,17 @@ class CopyInOutExplicitInterface {
15011500 (dummyTreatAsArray && !dummyIsPolymorphic) || dummyIsVoidStar ||
15021501 dummyObj_.attrs .test (
15031502 characteristics::DummyDataObject::Attr::Contiguous)};
1504- return !actualTreatAsContiguous && dummyNeedsContiguity;
1503+ return dummyNeedsContiguity;
15051504 }
15061505
1507- // Returns true, if actual and dummy have polymorphic differences
15081506 bool HavePolymorphicDifferences () const {
1509- bool dummyIsAssumedRank{dummyObj_.type .attrs ().test (
1510- characteristics::TypeAndShape::Attr::AssumedRank)};
1511- bool actualIsAssumedRank{semantics::IsAssumedRank (actual_)};
1512- bool dummyIsAssumedShape{dummyObj_.type .attrs ().test (
1513- characteristics::TypeAndShape::Attr::AssumedShape)};
1514- bool actualIsAssumedShape{semantics::IsAssumedShape (actual_)};
1515- if ((actualIsAssumedRank && dummyIsAssumedRank) ||
1516- (actualIsAssumedShape && dummyIsAssumedShape)) {
1517- // Assumed-rank and assumed-shape arrays are represented by descriptors,
1518- // so don't need to do polymorphic check.
1519- } else if (!dummyObj_.ignoreTKR .test (common::IgnoreTKR::Type)) {
1520- // flang supports limited cases of passing polymorphic to non-polimorphic.
1521- // These cases require temporary of non-polymorphic type. (For example,
1522- // the actual argument could be polymorphic array of child type,
1523- // while the dummy argument could be non-polymorphic array of parent
1524- // type.)
1507+ if (dummyObj_.ignoreTKR .test (common::IgnoreTKR::Type)) {
1508+ return false ;
1509+ }
1510+ if (auto actualType{
1511+ characteristics::TypeAndShape::Characterize (actual_, fc_)}) {
1512+ bool actualIsPolymorphic{actualType->type ().IsPolymorphic ()};
15251513 bool dummyIsPolymorphic{dummyObj_.type .type ().IsPolymorphic ()};
1526- auto actualType{
1527- characteristics::TypeAndShape::Characterize (actual_, fc_)};
1528- bool actualIsPolymorphic{
1529- actualType && actualType->type ().IsPolymorphic ()};
15301514 if (actualIsPolymorphic && !dummyIsPolymorphic) {
15311515 return true ;
15321516 }
@@ -1575,28 +1559,32 @@ class CopyInOutExplicitInterface {
15751559// procedures with explicit interface, it's expected that "dummy" is not null.
15761560// For procedures with implicit interface dummy may be null.
15771561//
1562+ // Returns std::optional<bool> indicating whether the copy is known to be
1563+ // needed (true) or not needed (false); returns std::nullopt if the necessity
1564+ // of the copy is undetermined.
1565+ //
15781566// Note that these copy-in and copy-out checks are done from the caller's
15791567// perspective, meaning that for copy-in the caller need to do the copy
15801568// before calling the callee. Similarly, for copy-out the caller is expected
15811569// to do the copy after the callee returns.
1582- bool MayNeedCopy (const ActualArgument *actual,
1570+ std::optional< bool > ActualArgNeedsCopy (const ActualArgument *actual,
15831571 const characteristics::DummyArgument *dummy, FoldingContext &fc,
15841572 bool forCopyOut) {
15851573 if (!actual) {
1586- return false ;
1574+ return std:: nullopt ;
15871575 }
15881576 if (actual->isAlternateReturn ()) {
1589- return false ;
1577+ return std:: nullopt ;
15901578 }
15911579 const auto *dummyObj{dummy
15921580 ? std::get_if<characteristics::DummyDataObject>(&dummy->u )
15931581 : nullptr };
1594- const bool forCopyIn = !forCopyOut;
1582+ const bool forCopyIn{ !forCopyOut} ;
15951583 if (!evaluate::IsVariable (*actual)) {
1596- // Actual argument expressions that aren’t variables are copy-in, but
1597- // not copy-out.
1584+ // Expressions are copy-in, but not copy-out.
15981585 return forCopyIn;
15991586 }
1587+ auto maybeContigActual{IsContiguous (*actual, fc)};
16001588 if (dummyObj) { // Explict interface
16011589 CopyInOutExplicitInterface check{fc, *actual, *dummyObj};
16021590 if (forCopyOut && check.HasIntentIn ()) {
@@ -1619,28 +1607,25 @@ bool MayNeedCopy(const ActualArgument *actual,
16191607 if (!check.HaveArrayOrAssumedRankArgs ()) {
16201608 return false ;
16211609 }
1622- if (check.HaveContiguityDifferences ()) {
1623- return true ;
1624- }
1625- if (check.HavePolymorphicDifferences ()) {
1626- return true ;
1610+ if (maybeContigActual.has_value ()) {
1611+ // We know whether actual arg is contiguous or not
1612+ bool isContiguousActual{maybeContigActual.value ()};
1613+ bool actualArgNeedsCopy{
1614+ (!isContiguousActual || check.HavePolymorphicDifferences ()) &&
1615+ check.DummyNeedsContiguity ()};
1616+ return actualArgNeedsCopy;
1617+ } else {
1618+ // We don't know whether actual arg is contiguous or not
1619+ return check.DummyNeedsContiguity ();
16271620 }
16281621 } else { // Implicit interface
1629- if (ExtractCoarrayRef (*actual)) {
1630- // Coindexed actual args may need copy-in and copy-out with implicit
1631- // interface
1632- return true ;
1633- }
1634- if (!IsSimplyContiguous (*actual, fc)) {
1635- // Copy-in: actual arguments that are variables are copy-in when
1636- // non-contiguous.
1637- // Copy-out: vector subscripts could refer to duplicate elements, can't
1638- // copy out.
1639- return !(forCopyOut && HasVectorSubscript (*actual));
1622+ if (maybeContigActual.has_value ()) {
1623+ // If known contiguous, don't copy in/out.
1624+ // If known non-contiguous, copy in/out.
1625+ return !*maybeContigActual;
16401626 }
16411627 }
1642- // For everything else, no copy-in or copy-out
1643- return false ;
1628+ return std::nullopt ;
16441629}
16451630
16461631} // namespace Fortran::evaluate
0 commit comments