Skip to content

Commit 1c202be

Browse files
Merge branch '1-copy-in-out-new-interface' into fix-poly-copy-in-out
2 parents 23393fe + 4371a28 commit 1c202be

File tree

4 files changed

+45
-49
lines changed

4 files changed

+45
-49
lines changed

flang/include/flang/Evaluate/check-expression.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,8 @@ extern template bool IsErrorExpr(const Expr<SomeType> &);
163163
std::optional<parser::Message> CheckStatementFunction(
164164
const Symbol &, const Expr<SomeType> &, FoldingContext &);
165165

166-
bool MayNeedCopy(const ActualArgument *, const characteristics::DummyArgument *,
167-
FoldingContext &, bool forCopyOut);
166+
std::optional<bool> ActualArgNeedsCopy(const ActualArgument *,
167+
const characteristics::DummyArgument *, FoldingContext &, bool forCopyOut);
168168

169169
} // namespace Fortran::evaluate
170170
#endif

flang/lib/Evaluate/check-expression.cpp

Lines changed: 30 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -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

flang/lib/Lower/ConvertCall.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,10 +1296,14 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
12961296
Fortran::evaluate::FoldingContext &foldingContext{
12971297
callContext.converter.getFoldingContext()};
12981298

1299-
bool suggestCopyIn = Fortran::evaluate::MayNeedCopy(
1300-
arg.entity, arg.characteristics, foldingContext, /*forCopyOut=*/false);
1301-
bool suggestCopyOut = Fortran::evaluate::MayNeedCopy(
1302-
arg.entity, arg.characteristics, foldingContext, /*forCopyOut=*/true);
1299+
bool suggestCopyIn = Fortran::evaluate::ActualArgNeedsCopy(
1300+
arg.entity, arg.characteristics, foldingContext,
1301+
/*forCopyOut=*/false)
1302+
.value_or(false);
1303+
bool suggestCopyOut = Fortran::evaluate::ActualArgNeedsCopy(
1304+
arg.entity, arg.characteristics, foldingContext,
1305+
/*forCopyOut=*/true)
1306+
.value_or(false);
13031307
mustDoCopyIn = actual.isArray() && suggestCopyIn;
13041308
mustDoCopyOut = actual.isArray() && suggestCopyOut;
13051309
}

flang/lib/Semantics/check-call.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,9 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
795795
bool dummyIsAssumedShape{dummy.type.attrs().test(
796796
characteristics::TypeAndShape::Attr::AssumedShape)};
797797
bool copyOutNeeded{
798-
evaluate::MayNeedCopy(&arg, &dummyArg, foldingContext, true)};
798+
evaluate::ActualArgNeedsCopy(&arg, &dummyArg, foldingContext,
799+
/*forCopyOut=*/true)
800+
.value_or(false)};
799801
if (copyOutNeeded && !dummyIsValue &&
800802
(dummyIsAsynchronous || dummyIsVolatile)) {
801803
if (actualIsAsynchronous || actualIsVolatile) {
@@ -832,8 +834,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
832834
// a unread value in the actual argument.
833835
// Occurences of `volatileOrAsyncNeedsTempDiagnosticIssued = true` indicate a
834836
// more specific error message has already been issued. We might be able to
835-
// clean this up by switching the coding style of MayNeedCopy to be more like
836-
// WhyNotDefinable.
837+
// clean this up by switching the coding style of ActualArgNeedsCopy to be
838+
// more like WhyNotDefinable.
837839
if (copyOutNeeded && !volatileOrAsyncNeedsTempDiagnosticIssued) {
838840
if ((actualIsVolatile || actualIsAsynchronous) &&
839841
(dummyIsVolatile || dummyIsAsynchronous)) {

0 commit comments

Comments
 (0)