Skip to content

Commit 3a8a52f

Browse files
authored
[flang] Make IsCoarray() more accurate (#121415)
A designator without cosubscripts can have subscripts, component references, substrings, &c. and still have corank. The current IsCoarray() predicate only seems to work for whole variable/component references. This was breaking some cases of THIS_IMAGE().
1 parent eb77f44 commit 3a8a52f

File tree

18 files changed

+182
-51
lines changed

18 files changed

+182
-51
lines changed

flang/include/flang/Evaluate/call.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ class ProcedureRef {
250250

251251
std::optional<Expr<SubscriptInteger>> LEN() const;
252252
int Rank() const;
253+
static constexpr int Corank() { return 0; } // TODO
253254
bool IsElemental() const { return proc_.IsElemental(); }
254255
bool hasAlternateReturns() const { return hasAlternateReturns_; }
255256

flang/include/flang/Evaluate/characteristics.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ class TypeAndShape {
102102
}
103103
if (auto type{x.GetType()}) {
104104
TypeAndShape result{*type, GetShape(context, x, invariantOnly)};
105+
result.corank_ = GetCorank(x);
106+
if (result.corank_ > 0) {
107+
result.attrs_.set(Attr::Coarray);
108+
}
105109
if (type->category() == TypeCategory::Character) {
106110
if (const auto *chExpr{UnwrapExpr<Expr<SomeCharacter>>(x)}) {
107111
if (auto length{chExpr->LEN()}) {

flang/include/flang/Evaluate/constant.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class ConstantBounds {
6565
~ConstantBounds();
6666
const ConstantSubscripts &shape() const { return shape_; }
6767
int Rank() const { return GetRank(shape_); }
68+
static constexpr int Corank() { return 0; }
6869
Constant<SubscriptInteger> SHAPE() const;
6970

7071
// It is possible in this representation for a constant array to have

flang/include/flang/Evaluate/expression.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ template <typename RESULT> class ExpressionBase {
9292

9393
std::optional<DynamicType> GetType() const;
9494
int Rank() const;
95+
int Corank() const;
9596
std::string AsFortran() const;
9697
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
9798
LLVM_DUMP_METHOD void dump() const;
@@ -190,6 +191,7 @@ class Operation {
190191
return rank;
191192
}
192193
}
194+
static constexpr int Corank() { return 0; }
193195

194196
bool operator==(const Operation &that) const {
195197
return operand_ == that.operand_;
@@ -395,6 +397,7 @@ struct ImpliedDoIndex {
395397
using Result = SubscriptInteger;
396398
bool operator==(const ImpliedDoIndex &) const;
397399
static constexpr int Rank() { return 0; }
400+
static constexpr int Corank() { return 0; }
398401
parser::CharBlock name; // nested implied DOs must use distinct names
399402
};
400403

@@ -441,6 +444,7 @@ template <typename RESULT> class ArrayConstructorValues {
441444

442445
bool operator==(const ArrayConstructorValues &) const;
443446
static constexpr int Rank() { return 1; }
447+
static constexpr int Corank() { return 0; }
444448
template <typename A> common::NoLvalue<A> Push(A &&x) {
445449
values_.emplace_back(std::move(x));
446450
}
@@ -680,6 +684,7 @@ template <> class Relational<SomeType> {
680684
int Rank() const {
681685
return common::visit([](const auto &x) { return x.Rank(); }, u);
682686
}
687+
static constexpr int Corank() { return 0; }
683688
llvm::raw_ostream &AsFortran(llvm::raw_ostream &o) const;
684689
common::MapTemplate<Relational, DirectlyComparableTypes> u;
685690
};
@@ -766,7 +771,8 @@ class StructureConstructor {
766771
std::optional<Expr<SomeType>> Find(const Symbol &) const;
767772

768773
StructureConstructor &Add(const semantics::Symbol &, Expr<SomeType> &&);
769-
int Rank() const { return 0; }
774+
static constexpr int Rank() { return 0; }
775+
static constexpr int Corank() { return 0; }
770776
DynamicType GetType() const;
771777
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
772778

@@ -820,7 +826,8 @@ using BOZLiteralConstant = typename LargestReal::Scalar::Word;
820826
// Null pointers without MOLD= arguments are typed by context.
821827
struct NullPointer {
822828
constexpr bool operator==(const NullPointer &) const { return true; }
823-
constexpr int Rank() const { return 0; }
829+
static constexpr int Rank() { return 0; }
830+
static constexpr int Corank() { return 0; }
824831
};
825832

826833
// Procedure pointer targets are treated as if they were typeless.

flang/include/flang/Evaluate/tools.h

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -102,22 +102,26 @@ template <typename A> bool IsAssumedRank(const A *x) {
102102
return x && IsAssumedRank(*x);
103103
}
104104

105-
// Predicate: true when an expression is a coarray (corank > 0)
106-
bool IsCoarray(const ActualArgument &);
107-
bool IsCoarray(const Symbol &);
108-
template <typename A> bool IsCoarray(const A &) { return false; }
109-
template <typename A> bool IsCoarray(const Designator<A> &designator) {
110-
if (const auto *symbol{std::get_if<SymbolRef>(&designator.u)}) {
111-
return IsCoarray(**symbol);
112-
}
113-
return false;
105+
// Finds the corank of an entity, possibly packaged in various ways.
106+
// Unlike rank, only data references have corank > 0.
107+
int GetCorank(const ActualArgument &);
108+
static inline int GetCorank(const Symbol &symbol) { return symbol.Corank(); }
109+
template <typename A> int GetCorank(const A &) { return 0; }
110+
template <typename T> int GetCorank(const Designator<T> &designator) {
111+
return designator.Corank();
114112
}
115-
template <typename T> bool IsCoarray(const Expr<T> &expr) {
116-
return common::visit([](const auto &x) { return IsCoarray(x); }, expr.u);
113+
template <typename T> int GetCorank(const Expr<T> &expr) {
114+
return common::visit([](const auto &x) { return GetCorank(x); }, expr.u);
117115
}
118-
template <typename A> bool IsCoarray(const std::optional<A> &x) {
119-
return x && IsCoarray(*x);
116+
template <typename A> int GetCorank(const std::optional<A> &x) {
117+
return x ? GetCorank(*x) : 0;
120118
}
119+
template <typename A> int GetCorank(const A *x) {
120+
return x ? GetCorank(*x) : 0;
121+
}
122+
123+
// Predicate: true when an expression is a coarray (corank > 0)
124+
template <typename A> bool IsCoarray(const A &x) { return GetCorank(x) > 0; }
121125

122126
// Generalizing packagers: these take operations and expressions of more
123127
// specific types and wrap them in Expr<> containers of more abstract types.

flang/include/flang/Evaluate/variable.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ template <typename T> struct Variable;
5151
struct BaseObject {
5252
EVALUATE_UNION_CLASS_BOILERPLATE(BaseObject)
5353
int Rank() const;
54+
int Corank() const;
5455
std::optional<Expr<SubscriptInteger>> LEN() const;
5556
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
5657
const Symbol *symbol() const {
@@ -84,6 +85,7 @@ class Component {
8485
SymbolRef &symbol() { return symbol_; }
8586

8687
int Rank() const;
88+
int Corank() const;
8789
const Symbol &GetFirstSymbol() const;
8890
const Symbol &GetLastSymbol() const { return symbol_; }
8991
std::optional<Expr<SubscriptInteger>> LEN() const;
@@ -116,6 +118,7 @@ class NamedEntity {
116118
Component *UnwrapComponent();
117119

118120
int Rank() const;
121+
int Corank() const;
119122
std::optional<Expr<SubscriptInteger>> LEN() const;
120123
bool operator==(const NamedEntity &) const;
121124
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
@@ -147,6 +150,7 @@ class TypeParamInquiry {
147150
const Symbol &parameter() const { return parameter_; }
148151

149152
static constexpr int Rank() { return 0; } // always scalar
153+
static constexpr int Corank() { return 0; }
150154
bool operator==(const TypeParamInquiry &) const;
151155
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
152156

@@ -224,6 +228,7 @@ class ArrayRef {
224228
}
225229

226230
int Rank() const;
231+
int Corank() const;
227232
const Symbol &GetFirstSymbol() const;
228233
const Symbol &GetLastSymbol() const;
229234
std::optional<Expr<SubscriptInteger>> LEN() const;
@@ -271,6 +276,7 @@ class CoarrayRef {
271276
CoarrayRef &set_team(Expr<SomeInteger> &&, bool isTeamNumber = false);
272277

273278
int Rank() const;
279+
int Corank() const { return 0; }
274280
const Symbol &GetFirstSymbol() const;
275281
const Symbol &GetLastSymbol() const;
276282
NamedEntity GetBase() const;
@@ -294,6 +300,7 @@ class CoarrayRef {
294300
struct DataRef {
295301
EVALUATE_UNION_CLASS_BOILERPLATE(DataRef)
296302
int Rank() const;
303+
int Corank() const;
297304
const Symbol &GetFirstSymbol() const;
298305
const Symbol &GetLastSymbol() const;
299306
std::optional<Expr<SubscriptInteger>> LEN() const;
@@ -331,6 +338,7 @@ class Substring {
331338
Parent &parent() { return parent_; }
332339

333340
int Rank() const;
341+
int Corank() const;
334342
template <typename A> const A *GetParentIf() const {
335343
return std::get_if<A>(&parent_);
336344
}
@@ -361,6 +369,7 @@ class ComplexPart {
361369
const DataRef &complex() const { return complex_; }
362370
Part part() const { return part_; }
363371
int Rank() const;
372+
int Corank() const;
364373
const Symbol &GetFirstSymbol() const { return complex_.GetFirstSymbol(); }
365374
const Symbol &GetLastSymbol() const { return complex_.GetLastSymbol(); }
366375
bool operator==(const ComplexPart &) const;
@@ -396,6 +405,7 @@ template <typename T> class Designator {
396405

397406
std::optional<DynamicType> GetType() const;
398407
int Rank() const;
408+
int Corank() const;
399409
BaseObject GetBaseObject() const;
400410
const Symbol *GetLastSymbol() const;
401411
std::optional<Expr<SubscriptInteger>> LEN() const;
@@ -421,6 +431,7 @@ class DescriptorInquiry {
421431
int dimension() const { return dimension_; }
422432

423433
static constexpr int Rank() { return 0; } // always scalar
434+
static constexpr int Corank() { return 0; }
424435
bool operator==(const DescriptorInquiry &) const;
425436
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
426437

flang/include/flang/Semantics/symbol.h

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -861,23 +861,7 @@ class Symbol {
861861
bool operator!=(const Symbol &that) const { return !(*this == that); }
862862

863863
int Rank() const { return RankImpl(); }
864-
865-
int Corank() const {
866-
return common::visit(
867-
common::visitors{
868-
[](const SubprogramDetails &sd) {
869-
return sd.isFunction() ? sd.result().Corank() : 0;
870-
},
871-
[](const GenericDetails &) {
872-
return 0; /*TODO*/
873-
},
874-
[](const UseDetails &x) { return x.symbol().Corank(); },
875-
[](const HostAssocDetails &x) { return x.symbol().Corank(); },
876-
[](const ObjectEntityDetails &oed) { return oed.coshape().Rank(); },
877-
[](const auto &) { return 0; },
878-
},
879-
details_);
880-
}
864+
int Corank() const { return CorankImpl(); }
881865

882866
// If there is a parent component, return a pointer to its derived type spec.
883867
// The Scope * argument defaults to this->scope_ but should be overridden
@@ -955,6 +939,32 @@ class Symbol {
955939
},
956940
details_);
957941
}
942+
inline int CorankImpl(int depth = startRecursionDepth) const {
943+
if (depth-- == 0) {
944+
return 0;
945+
}
946+
return common::visit(
947+
common::visitors{
948+
[&](const SubprogramDetails &sd) {
949+
return sd.isFunction() ? sd.result().CorankImpl(depth) : 0;
950+
},
951+
[](const GenericDetails &) { return 0; },
952+
[&](const ProcEntityDetails &ped) {
953+
const Symbol *iface{ped.procInterface()};
954+
return iface ? iface->CorankImpl(depth) : 0;
955+
},
956+
[&](const UseDetails &x) { return x.symbol().CorankImpl(depth); },
957+
[&](const HostAssocDetails &x) {
958+
return x.symbol().CorankImpl(depth);
959+
},
960+
[](const ObjectEntityDetails &oed) { return oed.coshape().Rank(); },
961+
[](const AssocEntityDetails &aed) {
962+
return aed.expr() ? aed.expr()->Corank() : 0;
963+
},
964+
[](const auto &) { return 0; },
965+
},
966+
details_);
967+
}
958968
template <std::size_t> friend class Symbols;
959969
template <class, std::size_t> friend class std::array;
960970
};

flang/lib/Evaluate/characteristics.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -227,15 +227,14 @@ void TypeAndShape::AcquireAttrs(const semantics::Symbol &symbol) {
227227
} else if (semantics::IsAssumedSizeArray(symbol)) {
228228
attrs_.set(Attr::AssumedSize);
229229
}
230+
if (int n{GetCorank(symbol)}) {
231+
corank_ = n;
232+
attrs_.set(Attr::Coarray);
233+
}
230234
if (const auto *object{
231-
symbol.GetUltimate().detailsIf<semantics::ObjectEntityDetails>()}) {
232-
corank_ = object->coshape().Rank();
233-
if (object->IsAssumedRank()) {
234-
attrs_.set(Attr::AssumedRank);
235-
}
236-
if (object->IsCoarray()) {
237-
attrs_.set(Attr::Coarray);
238-
}
235+
symbol.GetUltimate().detailsIf<semantics::ObjectEntityDetails>()};
236+
object && object->IsAssumedRank()) {
237+
attrs_.set(Attr::AssumedRank);
239238
}
240239
}
241240

flang/lib/Evaluate/expression.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,18 @@ template <typename A> int ExpressionBase<A>::Rank() const {
113113
derived().u);
114114
}
115115

116+
template <typename A> int ExpressionBase<A>::Corank() const {
117+
return common::visit(
118+
[](const auto &x) {
119+
if constexpr (common::HasMember<decltype(x), TypelessExpression>) {
120+
return 0;
121+
} else {
122+
return x.Corank();
123+
}
124+
},
125+
derived().u);
126+
}
127+
116128
DynamicType Parentheses<SomeDerived>::GetType() const {
117129
return left().GetType().value();
118130
}

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -958,7 +958,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
958958
{{"coarray", AnyData, Rank::coarray}, RequiredDIM, OptionalTEAM},
959959
DefaultInt, Rank::scalar, IntrinsicClass::transformationalFunction},
960960
{"this_image", {{"coarray", AnyData, Rank::coarray}, OptionalTEAM},
961-
DefaultInt, Rank::scalar, IntrinsicClass::transformationalFunction},
961+
DefaultInt, Rank::vector, IntrinsicClass::transformationalFunction},
962962
{"this_image", {OptionalTEAM}, DefaultInt, Rank::scalar,
963963
IntrinsicClass::transformationalFunction},
964964
{"tiny",

0 commit comments

Comments
 (0)