Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
120 commits
Select commit Hold shift + click to select a range
54c0158
[flang][DRAFT] Copy-in/Copy-out determination
eugeneepshteyn Jul 30, 2025
808fb20
Call DetermineCopyInOut() from lowering
eugeneepshteyn Jul 30, 2025
28bc5bd
clang-format
eugeneepshteyn Jul 30, 2025
f44b945
DetermineCopyInOut() is now called from ProcedureRef constructor
eugeneepshteyn Jul 30, 2025
ffd6563
clang-format
eugeneepshteyn Jul 30, 2025
fb3a93c
Minor tweak
eugeneepshteyn Jul 31, 2025
6e052f4
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Jul 31, 2025
b914f79
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Jul 31, 2025
527b2d7
DetermineCopyInOut() is now called at ProcedureRef instantiation
eugeneepshteyn Jul 31, 2025
9c1755b
Very rough beginnings of argument handling in DetermineCopyInOut()
eugeneepshteyn Aug 1, 2025
3198e90
More args handing in DetermineCopyInOut()
eugeneepshteyn Aug 1, 2025
0378a5f
clang-format
eugeneepshteyn Aug 3, 2025
5d5418a
clang-format
eugeneepshteyn Aug 3, 2025
2cce4bb
clang-format
eugeneepshteyn Aug 3, 2025
f6f64ca
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 3, 2025
4a6d402
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 6, 2025
698b865
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 6, 2025
de06d25
Initial implementation of DetermineCopyInOutArgument() for implicit
eugeneepshteyn Aug 7, 2025
cf42b12
Removed empty line
eugeneepshteyn Aug 7, 2025
9373b90
clang-format
eugeneepshteyn Aug 7, 2025
889f7c1
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 7, 2025
905c315
Merge branch 'llvm:main' into copy-inout-review
eugeneepshteyn Aug 7, 2025
d9452c3
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 7, 2025
fab0c75
Merge branch 'copy-inout-dev' into copy-inout-review
eugeneepshteyn Aug 7, 2025
9e47176
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 8, 2025
12ca5a8
Braces!
eugeneepshteyn Aug 8, 2025
3126a8c
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 10, 2025
c2fc2e9
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 11, 2025
902894c
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 12, 2025
c3ef243
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 12, 2025
143f7bd
clang-format
eugeneepshteyn Aug 8, 2025
6d0935c
Renamed copy-in/copy-out getter/setter functions
eugeneepshteyn Aug 11, 2025
15db3f8
Contiguity check
eugeneepshteyn Aug 12, 2025
58764a6
clang-format
eugeneepshteyn Aug 12, 2025
eb27031
Continue filling out DetermineCopyInOutArgument(). Implemented IsExpl…
eugeneepshteyn Aug 12, 2025
3ec01ad
clang-format
eugeneepshteyn Aug 12, 2025
889d514
In DetermineCopyInOutArgument(), handle INTENT(IN) and INTENT(OUT)
eugeneepshteyn Aug 12, 2025
040572f
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 12, 2025
04daa83
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 13, 2025
5136de2
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 13, 2025
7e448f0
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 14, 2025
546af8f
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 14, 2025
068216f
Support polymorphic-to-non-polymorphic case. Initial hookup into lowe…
eugeneepshteyn Aug 13, 2025
3f36c9f
clang-format
eugeneepshteyn Aug 13, 2025
070ffd1
array check
eugeneepshteyn Aug 14, 2025
5062266
array check
eugeneepshteyn Aug 14, 2025
312cf25
Changed IsExplicitShape() and restructured the checks
eugeneepshteyn Aug 14, 2025
bc2e17a
Redid the integration to basically the old code but debug output with…
eugeneepshteyn Aug 15, 2025
d026f49
Tweaks and debug output
eugeneepshteyn Aug 15, 2025
55b8e0e
Switched to the new code. 5 failed tests left
eugeneepshteyn Aug 15, 2025
a781512
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 15, 2025
384bc2e
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 18, 2025
b3fd99a
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 18, 2025
258fc64
Fixed one issue with assumed rank arrays
eugeneepshteyn Aug 15, 2025
a197190
clang-format
eugeneepshteyn Aug 15, 2025
30d36b0
Expaned IsAssumedShape() checks and moved them to Fortran::evaluate n…
eugeneepshteyn Aug 15, 2025
47f2656
clang-format
eugeneepshteyn Aug 15, 2025
aa65a3e
Passes LIT tests
eugeneepshteyn Aug 18, 2025
d285ded
Clean up in lowering to switch to the new checks
eugeneepshteyn Aug 18, 2025
413eafd
Ignore rank support
eugeneepshteyn Aug 18, 2025
4590955
Polymorphic dummy with ignore rank
eugeneepshteyn Aug 18, 2025
d026e0d
clang-format (upstream)
eugeneepshteyn Aug 18, 2025
0289de2
clang-format (upstream)
eugeneepshteyn Aug 18, 2025
2464dd3
clang-format (started using upstream)
eugeneepshteyn Aug 18, 2025
f76c9e3
Added LIT test
eugeneepshteyn Aug 18, 2025
b12d2c8
Implement copy-in/copy-out determination in Fortran::evaluate::MayNee…
eugeneepshteyn Aug 18, 2025
24c2040
clang-format
eugeneepshteyn Aug 18, 2025
a760320
Removed the old way to integrate copy-in/copy-out check
eugeneepshteyn Aug 18, 2025
6868af8
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 18, 2025
e69fa22
Merge branch 'llvm:main' into copy-inout-review
eugeneepshteyn Aug 18, 2025
1bd1822
Merge branch 'copy-inout-dev' into copy-inout-review
eugeneepshteyn Aug 18, 2025
f752112
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 19, 2025
7aa458c
Fixed the issue with user defined assignment
eugeneepshteyn Aug 19, 2025
d1a8d7c
clang-format
eugeneepshteyn Aug 19, 2025
57fd73e
Tweaked MayNeedCopyInOut() API
eugeneepshteyn Aug 19, 2025
b7dab28
Simplified IsAssumedRank() and IsAssumedShape()
eugeneepshteyn Aug 19, 2025
0239c1d
Moved IsAssumedRank() and IsAssumedShape() to namespace Fortran::sema…
eugeneepshteyn Aug 19, 2025
95f0aac
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 19, 2025
02ee2b7
Merge branch 'llvm:main' into copy-inout-review
eugeneepshteyn Aug 19, 2025
4938d03
Merge branch 'copy-inout-dev' into copy-inout-review
eugeneepshteyn Aug 19, 2025
0faca16
clang-format
eugeneepshteyn Aug 19, 2025
6f828b3
Merge branch 'copy-inout-dev' into copy-inout-review
eugeneepshteyn Aug 19, 2025
450a5d7
WIP: new API MayNeedCopy()
eugeneepshteyn Aug 20, 2025
0be16a4
clang-format
eugeneepshteyn Aug 20, 2025
68722d6
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 20, 2025
dd9560a
Continue implementation of new MayNeedCopy()
eugeneepshteyn Aug 20, 2025
a8c4dcf
Assumed type check for contiguity
eugeneepshteyn Aug 20, 2025
be85c20
Better void* standing for old implementation
eugeneepshteyn Aug 20, 2025
36a3049
clang-format
eugeneepshteyn Aug 20, 2025
69d7ca0
Tweaks to MayNeedCopyIn() to bring it closer to the old implementation
eugeneepshteyn Aug 20, 2025
f6bb3df
Removed the old implementation (MayNeedCopyInOut) and switched to the…
eugeneepshteyn Aug 20, 2025
fce3da4
Simplified MayNeedCopyOut()
eugeneepshteyn Aug 21, 2025
e36a534
Enhanced flang/test/Lower/force-temp.f90 to cover more cases
eugeneepshteyn Aug 21, 2025
6c5a1e2
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 21, 2025
0050af6
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 21, 2025
3e281e4
Yet another refactoring and logic update: use common class CopyInOutE…
eugeneepshteyn Aug 22, 2025
bd61c2a
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 22, 2025
335a463
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 22, 2025
b8e78b1
clang-format
eugeneepshteyn Aug 22, 2025
9be6a3e
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 22, 2025
36993cd
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 22, 2025
629b67d
debugging (checking the old code again)
eugeneepshteyn Aug 22, 2025
6138cc8
Fixed build issue with the old code
eugeneepshteyn Aug 22, 2025
02eec4c
Different copy-in/copy-out flag configuration
eugeneepshteyn Aug 22, 2025
f5be38b
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 25, 2025
5ddac27
Removed the old code
eugeneepshteyn Aug 25, 2025
b5ff581
updated comment
eugeneepshteyn Aug 25, 2025
6284e57
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 25, 2025
e54a8d2
Code review feedback
eugeneepshteyn Aug 25, 2025
d22d27c
clang-format
eugeneepshteyn Aug 25, 2025
84ce8ad
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 25, 2025
45eaddc
force-temp.f90: add test for INTENT(OUT) dummy argument
eugeneepshteyn Aug 25, 2025
fc28315
MayNeedCopy() simplification
eugeneepshteyn Aug 25, 2025
c7a740c
Further simplification of MayNeedCopy()
eugeneepshteyn Aug 25, 2025
0d9302e
Removed the old code
eugeneepshteyn Aug 25, 2025
3bb10d5
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 26, 2025
d22d76f
Removed DummyDataObject::IsArray() (no longer used)
eugeneepshteyn Aug 26, 2025
99aaa2b
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 26, 2025
3c64f13
Code review feedback
eugeneepshteyn Aug 26, 2025
0c5dc79
Merge branch 'llvm:main' into copy-inout-dev
eugeneepshteyn Aug 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions flang/include/flang/Evaluate/characteristics.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,12 @@ class TypeAndShape {
std::optional<Expr<SubscriptInteger>> MeasureSizeInBytes(
FoldingContext &) const;

bool IsExplicitShape() const {
// If it's array and no special attributes are set, then must be
// explicit shape.
return Rank() > 0 && attrs_.none();
}

// called by Fold() to rewrite in place
TypeAndShape &Rewrite(FoldingContext &);

Expand Down
6 changes: 6 additions & 0 deletions flang/include/flang/Evaluate/check-expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ std::optional<bool> IsContiguous(const A &, FoldingContext &,
extern template std::optional<bool> IsContiguous(const Expr<SomeType> &,
FoldingContext &, bool namedConstantSectionsAreContiguous,
bool firstDimensionStride1);
extern template std::optional<bool> IsContiguous(const ActualArgument &,
FoldingContext &, bool namedConstantSectionsAreContiguous,
bool firstDimensionStride1);
extern template std::optional<bool> IsContiguous(const ArrayRef &,
FoldingContext &, bool namedConstantSectionsAreContiguous,
bool firstDimensionStride1);
Expand Down Expand Up @@ -160,5 +163,8 @@ extern template bool IsErrorExpr(const Expr<SomeType> &);
std::optional<parser::Message> CheckStatementFunction(
const Symbol &, const Expr<SomeType> &, FoldingContext &);

bool MayNeedCopy(const ActualArgument *, const characteristics::DummyArgument *,
FoldingContext &, bool forCopyOut);

} // namespace Fortran::evaluate
#endif
34 changes: 13 additions & 21 deletions flang/include/flang/Evaluate/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,27 +82,6 @@ template <typename A> bool IsVariable(const A &x) {
}
}

// Predicate: true when an expression is assumed-rank
bool IsAssumedRank(const Symbol &);
bool IsAssumedRank(const ActualArgument &);
template <typename A> bool IsAssumedRank(const A &) { return false; }
template <typename A> bool IsAssumedRank(const Designator<A> &designator) {
if (const auto *symbol{std::get_if<SymbolRef>(&designator.u)}) {
return IsAssumedRank(symbol->get());
} else {
return false;
}
}
template <typename T> bool IsAssumedRank(const Expr<T> &expr) {
return common::visit([](const auto &x) { return IsAssumedRank(x); }, expr.u);
}
template <typename A> bool IsAssumedRank(const std::optional<A> &x) {
return x && IsAssumedRank(*x);
}
template <typename A> bool IsAssumedRank(const A *x) {
return x && IsAssumedRank(*x);
}

// Finds the corank of an entity, possibly packaged in various ways.
// Unlike rank, only data references have corank > 0.
int GetCorank(const ActualArgument &);
Expand Down Expand Up @@ -1123,6 +1102,7 @@ extern template semantics::UnorderedSymbolSet CollectCudaSymbols(

// Predicate: does a variable contain a vector-valued subscript (not a triplet)?
bool HasVectorSubscript(const Expr<SomeType> &);
bool HasVectorSubscript(const ActualArgument &);

// Predicate: does an expression contain constant?
bool HasConstant(const Expr<SomeType> &);
Expand Down Expand Up @@ -1555,7 +1535,19 @@ bool IsAllocatableOrObjectPointer(const Symbol *);
bool IsAutomatic(const Symbol &);
bool IsSaved(const Symbol &); // saved implicitly or explicitly
bool IsDummy(const Symbol &);

bool IsAssumedRank(const Symbol &);
template <typename A> bool IsAssumedRank(const A &x) {
auto *symbol{UnwrapWholeSymbolDataRef(x)};
return symbol && IsAssumedRank(*symbol);
}

bool IsAssumedShape(const Symbol &);
template <typename A> bool IsAssumedShape(const A &x) {
auto *symbol{UnwrapWholeSymbolDataRef(x)};
return symbol && IsAssumedShape(*symbol);
}

bool IsDeferredShape(const Symbol &);
bool IsFunctionResult(const Symbol &);
bool IsKindTypeParameter(const Symbol &);
Expand Down
189 changes: 187 additions & 2 deletions flang/lib/Evaluate/check-expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1001,8 +1001,8 @@ class IsContiguousHelper
} else {
return Base::operator()(ultimate); // use expr
}
} else if (semantics::IsPointer(ultimate) ||
semantics::IsAssumedShape(ultimate) || IsAssumedRank(ultimate)) {
} else if (semantics::IsPointer(ultimate) || IsAssumedShape(ultimate) ||
IsAssumedRank(ultimate)) {
return std::nullopt;
} else if (ultimate.has<semantics::ObjectEntityDetails>()) {
return true;
Expand Down Expand Up @@ -1282,9 +1282,21 @@ std::optional<bool> IsContiguous(const A &x, FoldingContext &context,
}
}

std::optional<bool> IsContiguous(const ActualArgument &actual,
FoldingContext &fc, bool namedConstantSectionsAreContiguous,
bool firstDimensionStride1) {
auto *expr{actual.UnwrapExpr()};
return expr &&
IsContiguous(
*expr, fc, namedConstantSectionsAreContiguous, firstDimensionStride1);
}

template std::optional<bool> IsContiguous(const Expr<SomeType> &,
FoldingContext &, bool namedConstantSectionsAreContiguous,
bool firstDimensionStride1);
template std::optional<bool> IsContiguous(const ActualArgument &,
FoldingContext &, bool namedConstantSectionsAreContiguous,
bool firstDimensionStride1);
template std::optional<bool> IsContiguous(const ArrayRef &, FoldingContext &,
bool namedConstantSectionsAreContiguous, bool firstDimensionStride1);
template std::optional<bool> IsContiguous(const Substring &, FoldingContext &,
Expand Down Expand Up @@ -1434,4 +1446,177 @@ std::optional<parser::Message> CheckStatementFunction(
return StmtFunctionChecker{sf, context}(expr);
}

// Helper class for checking differences between actual and dummy arguments
class CopyInOutExplicitInterface {
public:
explicit CopyInOutExplicitInterface(FoldingContext &fc,
const ActualArgument &actual,
const characteristics::DummyDataObject &dummyObj)
: fc_{fc}, actual_{actual}, dummyObj_{dummyObj} {}

// Returns true, if actual and dummy have different contiguity requirements
bool HaveContiguityDifferences() const {
// Check actual contiguity, unless dummy doesn't care
bool dummyTreatAsArray{dummyObj_.ignoreTKR.test(common::IgnoreTKR::Rank)};
bool actualTreatAsContiguous{
dummyObj_.ignoreTKR.test(common::IgnoreTKR::Contiguous) ||
IsSimplyContiguous(actual_, fc_)};
bool dummyIsExplicitShape{dummyObj_.type.IsExplicitShape()};
bool dummyIsAssumedSize{dummyObj_.type.attrs().test(
characteristics::TypeAndShape::Attr::AssumedSize)};
bool dummyIsPolymorphic{dummyObj_.type.type().IsPolymorphic()};
// type(*) with IGNORE_TKR(tkr) is often used to interface with C "void*".
// Since the other languages don't know about Fortran's discontiguity
// handling, such cases should require contiguity.
bool dummyIsVoidStar{dummyObj_.type.type().IsAssumedType() &&
dummyObj_.ignoreTKR.test(common::IgnoreTKR::Type) &&
dummyObj_.ignoreTKR.test(common::IgnoreTKR::Rank) &&
dummyObj_.ignoreTKR.test(common::IgnoreTKR::Kind)};
// Explicit shape and assumed size arrays must be contiguous
bool dummyNeedsContiguity{dummyIsExplicitShape || dummyIsAssumedSize ||
(dummyTreatAsArray && !dummyIsPolymorphic) || dummyIsVoidStar ||
dummyObj_.attrs.test(
characteristics::DummyDataObject::Attr::Contiguous)};
return !actualTreatAsContiguous && dummyNeedsContiguity;
}

// Returns true, if actual and dummy have polymorphic differences
bool HavePolymorphicDifferences() const {
bool dummyIsAssumedRank{dummyObj_.type.attrs().test(
characteristics::TypeAndShape::Attr::AssumedRank)};
bool actualIsAssumedRank{semantics::IsAssumedRank(actual_)};
bool dummyIsAssumedShape{dummyObj_.type.attrs().test(
characteristics::TypeAndShape::Attr::AssumedShape)};
bool actualIsAssumedShape{semantics::IsAssumedShape(actual_)};
if ((actualIsAssumedRank && dummyIsAssumedRank) ||
(actualIsAssumedShape && dummyIsAssumedShape)) {
// Assumed-rank and assumed-shape arrays are represented by descriptors,
// so don't need to do polymorphic check.
} else if (!dummyObj_.ignoreTKR.test(common::IgnoreTKR::Type)) {
// flang supports limited cases of passing polymorphic to non-polimorphic.
// These cases require temporary of non-polymorphic type. (For example,
// the actual argument could be polymorphic array of child type,
// while the dummy argument could be non-polymorphic array of parent
// type.)
bool dummyIsPolymorphic{dummyObj_.type.type().IsPolymorphic()};
auto actualType{
characteristics::TypeAndShape::Characterize(actual_, fc_)};
bool actualIsPolymorphic{
actualType && actualType->type().IsPolymorphic()};
if (actualIsPolymorphic && !dummyIsPolymorphic) {
return true;
}
}
return false;
}

bool HaveArrayOrAssumedRankArgs() const {
bool dummyTreatAsArray{dummyObj_.ignoreTKR.test(common::IgnoreTKR::Rank)};
return IsArrayOrAssumedRank(actual_) &&
(IsArrayOrAssumedRank(dummyObj_) || dummyTreatAsArray);
}

bool PassByValue() const {
return dummyObj_.attrs.test(characteristics::DummyDataObject::Attr::Value);
}

bool HaveCoarrayDifferences() const {
return ExtractCoarrayRef(actual_) && dummyObj_.type.corank() == 0;
}

bool HasIntentOut() const { return dummyObj_.intent == common::Intent::Out; }

bool HasIntentIn() const { return dummyObj_.intent == common::Intent::In; }

static bool IsArrayOrAssumedRank(const ActualArgument &actual) {
return semantics::IsAssumedRank(actual) || actual.Rank() > 0;
}

static bool IsArrayOrAssumedRank(
const characteristics::DummyDataObject &dummy) {
return dummy.type.attrs().test(
characteristics::TypeAndShape::Attr::AssumedRank) ||
dummy.type.Rank() > 0;
}

private:
FoldingContext &fc_;
const ActualArgument &actual_;
const characteristics::DummyDataObject &dummyObj_;
};

// If forCopyOut is false, returns if a particular actual/dummy argument
// combination may need a temporary creation with copy-in operation. If
// forCopyOut is true, returns the same for copy-out operation. For
// procedures with explicit interface, it's expected that "dummy" is not null.
// For procedures with implicit interface dummy may be null.
//
// Note that these copy-in and copy-out checks are done from the caller's
// perspective, meaning that for copy-in the caller need to do the copy
// before calling the callee. Similarly, for copy-out the caller is expected
// to do the copy after the callee returns.
bool MayNeedCopy(const ActualArgument *actual,
const characteristics::DummyArgument *dummy, FoldingContext &fc,
bool forCopyOut) {
if (!actual) {
return false;
}
if (actual->isAlternateReturn()) {
return false;
}
const auto *dummyObj{dummy
? std::get_if<characteristics::DummyDataObject>(&dummy->u)
: nullptr};
const bool forCopyIn = !forCopyOut;
if (!evaluate::IsVariable(*actual)) {
// Actual argument expressions that aren’t variables are copy-in, but
// not copy-out.
return forCopyIn;
}
if (dummyObj) { // Explict interface
CopyInOutExplicitInterface check{fc, *actual, *dummyObj};
if (forCopyOut && check.HasIntentIn()) {
// INTENT(IN) dummy args never need copy-out
return false;
}
if (forCopyIn && check.HasIntentOut()) {
// INTENT(OUT) dummy args never need copy-in
return false;
}
if (check.PassByValue()) {
// Pass by value, always copy-in, never copy-out
return forCopyIn;
}
if (check.HaveCoarrayDifferences()) {
return true;
}
// Note: contiguity and polymorphic checks deal with array or assumed rank
// arguments
if (!check.HaveArrayOrAssumedRankArgs()) {
return false;
}
if (check.HaveContiguityDifferences()) {
return true;
}
if (check.HavePolymorphicDifferences()) {
return true;
}
} else { // Implicit interface
if (ExtractCoarrayRef(*actual)) {
// Coindexed actual args may need copy-in and copy-out with implicit
// interface
return true;
}
if (!IsSimplyContiguous(*actual, fc)) {
// Copy-in: actual arguments that are variables are copy-in when
// non-contiguous.
// Copy-out: vector subscripts could refer to duplicate elements, can't
// copy out.
return !(forCopyOut && HasVectorSubscript(*actual));
}
}
// For everything else, no copy-in or copy-out
return false;
}

} // namespace Fortran::evaluate
10 changes: 5 additions & 5 deletions flang/lib/Evaluate/fold-integer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ static bool CheckDimArg(const std::optional<ActualArgument> &dimArg,
const Expr<SomeType> &array, parser::ContextualMessages &messages,
bool isLBound, std::optional<int> &dimVal) {
dimVal.reset();
if (int rank{array.Rank()}; rank > 0 || IsAssumedRank(array)) {
if (int rank{array.Rank()}; rank > 0 || semantics::IsAssumedRank(array)) {
auto named{ExtractNamedEntity(array)};
if (auto dim64{ToInt64(dimArg)}) {
if (*dim64 < 1) {
messages.Say("DIM=%jd dimension must be positive"_err_en_US, *dim64);
return false;
} else if (!IsAssumedRank(array) && *dim64 > rank) {
} else if (!semantics::IsAssumedRank(array) && *dim64 > rank) {
messages.Say(
"DIM=%jd dimension is out of range for rank-%d array"_err_en_US,
*dim64, rank);
Expand All @@ -56,7 +56,7 @@ static bool CheckDimArg(const std::optional<ActualArgument> &dimArg,
"DIM=%jd dimension is out of range for rank-%d assumed-size array"_err_en_US,
*dim64, rank);
return false;
} else if (IsAssumedRank(array)) {
} else if (semantics::IsAssumedRank(array)) {
if (*dim64 > common::maxRank) {
messages.Say(
"DIM=%jd dimension is too large for any array (maximum rank %d)"_err_en_US,
Expand Down Expand Up @@ -189,7 +189,7 @@ Expr<Type<TypeCategory::Integer, KIND>> LBOUND(FoldingContext &context,
return Expr<T>{std::move(funcRef)};
}
}
if (IsAssumedRank(*array)) {
if (semantics::IsAssumedRank(*array)) {
// Would like to return 1 if DIM=.. is present, but that would be
// hiding a runtime error if the DIM= were too large (including
// the case of an assumed-rank argument that's scalar).
Expand Down Expand Up @@ -240,7 +240,7 @@ Expr<Type<TypeCategory::Integer, KIND>> UBOUND(FoldingContext &context,
return Expr<T>{std::move(funcRef)};
}
}
if (IsAssumedRank(*array)) {
if (semantics::IsAssumedRank(*array)) {
} else if (int rank{array->Rank()}; rank > 0) {
bool takeBoundsFromShape{true};
if (auto named{ExtractNamedEntity(*array)}) {
Expand Down
4 changes: 2 additions & 2 deletions flang/lib/Evaluate/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2260,7 +2260,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
for (std::size_t j{0}; j < dummies; ++j) {
const IntrinsicDummyArgument &d{dummy[std::min(j, dummyArgPatterns - 1)]};
if (const ActualArgument *arg{actualForDummy[j]}) {
bool isAssumedRank{IsAssumedRank(*arg)};
bool isAssumedRank{semantics::IsAssumedRank(*arg)};
if (isAssumedRank && d.rank != Rank::anyOrAssumedRank &&
d.rank != Rank::arrayOrAssumedRank) {
messages.Say(arg->sourceLocation(),
Expand Down Expand Up @@ -3006,7 +3006,7 @@ SpecificCall IntrinsicProcTable::Implementation::HandleNull(
mold = nullptr;
}
if (mold) {
if (IsAssumedRank(*arguments[0])) {
if (semantics::IsAssumedRank(*arguments[0])) {
context.messages().Say(arguments[0]->sourceLocation(),
"MOLD= argument to NULL() must not be assumed-rank"_err_en_US);
}
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Evaluate/shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,7 @@ auto GetShapeHelper::operator()(const ProcedureRef &call) const -> Result {
intrinsic->name == "ubound") {
// For LBOUND/UBOUND, these are the array-valued cases (no DIM=)
if (!call.arguments().empty() && call.arguments().front()) {
if (IsAssumedRank(*call.arguments().front())) {
if (semantics::IsAssumedRank(*call.arguments().front())) {
return Shape{MaybeExtentExpr{}};
} else {
return Shape{
Expand Down
Loading