Skip to content

Commit c0de17f

Browse files
committed
[flang] Revamp evaluate::CoarrayRef
Bring the typed expression representation of a coindexed reference up to F'2023, which removed some restrictions that had allowed the current representation to suffice for older revisions of the language. This new representation is somewhat more simple -- it uses a DataRef as its base, so any subscripts in a part-ref can be represented as an ArrayRef there. Update the code that creates the CoarrayRef, and add more checking to it, as well as actually capturing any STAT=, TEAM=, & TEAM_NUMBER= specifiers that might appear. Enforce the constraint that the part-ref must have subscripts if it is an array. (And update a pile of copied-and-pasted test code that lacked such subscripts.)
1 parent e5f3260 commit c0de17f

29 files changed

+162
-253
lines changed

flang/include/flang/Evaluate/tools.h

+12-26
Original file line numberDiff line numberDiff line change
@@ -391,20 +391,17 @@ template <typename T>
391391
bool IsArrayElement(const Expr<T> &expr, bool intoSubstring = true,
392392
bool skipComponents = false) {
393393
if (auto dataRef{ExtractDataRef(expr, intoSubstring)}) {
394-
const DataRef *ref{&*dataRef};
395-
if (skipComponents) {
396-
while (const Component * component{std::get_if<Component>(&ref->u)}) {
397-
ref = &component->base();
394+
for (const DataRef *ref{&*dataRef}; ref;) {
395+
if (const Component * component{std::get_if<Component>(&ref->u)}) {
396+
ref = skipComponents ? &component->base() : nullptr;
397+
} else if (const auto *coarrayRef{std::get_if<CoarrayRef>(&ref->u)}) {
398+
ref = &coarrayRef->base();
399+
} else {
400+
return std::holds_alternative<ArrayRef>(ref->u);
398401
}
399402
}
400-
if (const auto *coarrayRef{std::get_if<CoarrayRef>(&ref->u)}) {
401-
return !coarrayRef->subscript().empty();
402-
} else {
403-
return std::holds_alternative<ArrayRef>(ref->u);
404-
}
405-
} else {
406-
return false;
407403
}
404+
return false;
408405
}
409406

410407
template <typename A>
@@ -418,9 +415,6 @@ std::optional<NamedEntity> ExtractNamedEntity(const A &x) {
418415
[](Component &&component) -> std::optional<NamedEntity> {
419416
return NamedEntity{std::move(component)};
420417
},
421-
[](CoarrayRef &&co) -> std::optional<NamedEntity> {
422-
return co.GetBase();
423-
},
424418
[](auto &&) { return std::optional<NamedEntity>{}; },
425419
},
426420
std::move(dataRef->u));
@@ -528,22 +522,14 @@ const Symbol *UnwrapWholeSymbolOrComponentDataRef(const A &x) {
528522
// If an expression is a whole symbol or a whole component designator,
529523
// potentially followed by an image selector, extract and return that symbol,
530524
// else null.
525+
const Symbol *UnwrapWholeSymbolOrComponentOrCoarrayRef(const DataRef &);
531526
template <typename A>
532527
const Symbol *UnwrapWholeSymbolOrComponentOrCoarrayRef(const A &x) {
533528
if (auto dataRef{ExtractDataRef(x)}) {
534-
if (const SymbolRef * p{std::get_if<SymbolRef>(&dataRef->u)}) {
535-
return &p->get();
536-
} else if (const Component * c{std::get_if<Component>(&dataRef->u)}) {
537-
if (c->base().Rank() == 0) {
538-
return &c->GetLastSymbol();
539-
}
540-
} else if (const CoarrayRef * c{std::get_if<CoarrayRef>(&dataRef->u)}) {
541-
if (c->subscript().empty()) {
542-
return &c->GetLastSymbol();
543-
}
544-
}
529+
return UnwrapWholeSymbolOrComponentOrCoarrayRef(*dataRef);
530+
} else {
531+
return nullptr;
545532
}
546-
return nullptr;
547533
}
548534

549535
// GetFirstSymbol(A%B%C[I]%D) -> A

flang/include/flang/Evaluate/traverse.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,7 @@ class Traverse {
146146
return Combine(x.base(), x.subscript());
147147
}
148148
Result operator()(const CoarrayRef &x) const {
149-
return Combine(
150-
x.base(), x.subscript(), x.cosubscript(), x.stat(), x.team());
149+
return Combine(x.base(), x.cosubscript(), x.stat(), x.team());
151150
}
152151
Result operator()(const DataRef &x) const { return visitor_(x.u); }
153152
Result operator()(const Substring &x) const {

flang/include/flang/Evaluate/variable.h

+13-28
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,6 @@ class Component {
9898

9999
// A NamedEntity is either a whole Symbol or a component in an instance
100100
// of a derived type. It may be a descriptor.
101-
// TODO: this is basically a symbol with an optional DataRef base;
102-
// could be used to replace Component.
103101
class NamedEntity {
104102
public:
105103
CLASS_BOILERPLATE(NamedEntity)
@@ -239,28 +237,16 @@ class ArrayRef {
239237
std::vector<Subscript> subscript_;
240238
};
241239

242-
// R914 coindexed-named-object
243-
// R924 image-selector, R926 image-selector-spec.
244-
// C825 severely limits the usage of derived types with coarray ultimate
245-
// components: they can't be pointers, allocatables, arrays, coarrays, or
246-
// function results. They can be components of other derived types.
247-
// Although the F'2018 Standard never prohibits multiple image-selectors
248-
// per se in the same data-ref or designator, nor the presence of an
249-
// image-selector after a part-ref with rank, the constraints on the
250-
// derived types that would have be involved make it impossible to declare
251-
// an object that could be referenced in these ways (esp. C748 & C825).
252-
// C930 precludes having both TEAM= and TEAM_NUMBER=.
253-
// TODO C931 prohibits the use of a coindexed object as a stat-variable.
240+
// A coindexed data-ref. The base is represented as a general
241+
// DataRef, but the base may not contain a CoarrayRef and may
242+
// have rank > 0 only in an uppermost ArrayRef.
254243
class CoarrayRef {
255244
public:
256245
CLASS_BOILERPLATE(CoarrayRef)
257-
CoarrayRef(SymbolVector &&, std::vector<Subscript> &&,
258-
std::vector<Expr<SubscriptInteger>> &&);
246+
CoarrayRef(DataRef &&, std::vector<Expr<SubscriptInteger>> &&);
259247

260-
const SymbolVector &base() const { return base_; }
261-
SymbolVector &base() { return base_; }
262-
const std::vector<Subscript> &subscript() const { return subscript_; }
263-
std::vector<Subscript> &subscript() { return subscript_; }
248+
const DataRef &base() const { return base_.value(); }
249+
DataRef &base() { return base_.value(); }
264250
const std::vector<Expr<SubscriptInteger>> &cosubscript() const {
265251
return cosubscript_;
266252
}
@@ -270,25 +256,24 @@ class CoarrayRef {
270256
// (i.e., Designator or pointer-valued FunctionRef).
271257
std::optional<Expr<SomeInteger>> stat() const;
272258
CoarrayRef &set_stat(Expr<SomeInteger> &&);
273-
std::optional<Expr<SomeInteger>> team() const;
274-
bool teamIsTeamNumber() const { return teamIsTeamNumber_; }
275-
CoarrayRef &set_team(Expr<SomeInteger> &&, bool isTeamNumber = false);
259+
// When team() is Expr<SomeInteger>, it's TEAM_NUMBER=; otherwise,
260+
// it's TEAM=.
261+
std::optional<Expr<SomeType>> team() const;
262+
CoarrayRef &set_team(Expr<SomeType> &&);
276263

277264
int Rank() const;
278265
int Corank() const { return 0; }
279266
const Symbol &GetFirstSymbol() const;
280267
const Symbol &GetLastSymbol() const;
281-
NamedEntity GetBase() const;
282268
std::optional<Expr<SubscriptInteger>> LEN() const;
283269
bool operator==(const CoarrayRef &) const;
284270
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
285271

286272
private:
287-
SymbolVector base_;
288-
std::vector<Subscript> subscript_;
273+
common::CopyableIndirection<DataRef> base_;
289274
std::vector<Expr<SubscriptInteger>> cosubscript_;
290-
std::optional<common::CopyableIndirection<Expr<SomeInteger>>> stat_, team_;
291-
bool teamIsTeamNumber_{false}; // false: TEAM=, true: TEAM_NUMBER=
275+
std::optional<common::CopyableIndirection<Expr<SomeInteger>>> stat_;
276+
std::optional<common::CopyableIndirection<Expr<SomeType>>> team_;
292277
};
293278

294279
// R911 data-ref is defined syntactically as a series of part-refs, which

flang/lib/Evaluate/check-expression.cpp

+1-4
Original file line numberDiff line numberDiff line change
@@ -946,10 +946,7 @@ class IsContiguousHelper
946946
return std::nullopt;
947947
}
948948
}
949-
Result operator()(const CoarrayRef &x) const {
950-
int rank{0};
951-
return CheckSubscripts(x.subscript(), rank).has_value();
952-
}
949+
Result operator()(const CoarrayRef &x) const { return (*this)(x.base()); }
953950
Result operator()(const Component &x) const {
954951
if (x.base().Rank() == 0) {
955952
return (*this)(x.GetLastSymbol());

flang/lib/Evaluate/fold.cpp

+4-9
Original file line numberDiff line numberDiff line change
@@ -162,22 +162,17 @@ ArrayRef FoldOperation(FoldingContext &context, ArrayRef &&arrayRef) {
162162
}
163163

164164
CoarrayRef FoldOperation(FoldingContext &context, CoarrayRef &&coarrayRef) {
165-
std::vector<Subscript> subscript;
166-
for (Subscript x : coarrayRef.subscript()) {
167-
subscript.emplace_back(FoldOperation(context, std::move(x)));
168-
}
165+
DataRef base{FoldOperation(context, std::move(coarrayRef.base()))};
169166
std::vector<Expr<SubscriptInteger>> cosubscript;
170167
for (Expr<SubscriptInteger> x : coarrayRef.cosubscript()) {
171168
cosubscript.emplace_back(Fold(context, std::move(x)));
172169
}
173-
CoarrayRef folded{std::move(coarrayRef.base()), std::move(subscript),
174-
std::move(cosubscript)};
170+
CoarrayRef folded{std::move(base), std::move(cosubscript)};
175171
if (std::optional<Expr<SomeInteger>> stat{coarrayRef.stat()}) {
176172
folded.set_stat(Fold(context, std::move(*stat)));
177173
}
178-
if (std::optional<Expr<SomeInteger>> team{coarrayRef.team()}) {
179-
folded.set_team(
180-
Fold(context, std::move(*team)), coarrayRef.teamIsTeamNumber());
174+
if (std::optional<Expr<SomeType>> team{coarrayRef.team()}) {
175+
folded.set_team(Fold(context, std::move(*team)));
181176
}
182177
return folded;
183178
}

flang/lib/Evaluate/formatting.cpp

+6-20
Original file line numberDiff line numberDiff line change
@@ -723,24 +723,8 @@ llvm::raw_ostream &ArrayRef::AsFortran(llvm::raw_ostream &o) const {
723723
}
724724

725725
llvm::raw_ostream &CoarrayRef::AsFortran(llvm::raw_ostream &o) const {
726-
bool first{true};
727-
for (const Symbol &part : base_) {
728-
if (first) {
729-
first = false;
730-
} else {
731-
o << '%';
732-
}
733-
EmitVar(o, part);
734-
}
735-
char separator{'('};
736-
for (const auto &sscript : subscript_) {
737-
EmitVar(o << separator, sscript);
738-
separator = ',';
739-
}
740-
if (separator == ',') {
741-
o << ')';
742-
}
743-
separator = '[';
726+
base().AsFortran(o);
727+
char separator{'['};
744728
for (const auto &css : cosubscript_) {
745729
EmitVar(o << separator, css);
746730
separator = ',';
@@ -750,8 +734,10 @@ llvm::raw_ostream &CoarrayRef::AsFortran(llvm::raw_ostream &o) const {
750734
separator = ',';
751735
}
752736
if (team_) {
753-
EmitVar(
754-
o << separator, team_, teamIsTeamNumber_ ? "TEAM_NUMBER=" : "TEAM=");
737+
EmitVar(o << separator, team_,
738+
std::holds_alternative<Expr<SomeInteger>>(team_->value().u)
739+
? "TEAM_NUMBER="
740+
: "TEAM=");
755741
}
756742
return o << ']';
757743
}

flang/lib/Evaluate/shape.cpp

+1-14
Original file line numberDiff line numberDiff line change
@@ -891,20 +891,7 @@ auto GetShapeHelper::operator()(const ArrayRef &arrayRef) const -> Result {
891891
}
892892

893893
auto GetShapeHelper::operator()(const CoarrayRef &coarrayRef) const -> Result {
894-
NamedEntity base{coarrayRef.GetBase()};
895-
if (coarrayRef.subscript().empty()) {
896-
return (*this)(base);
897-
} else {
898-
Shape shape;
899-
int dimension{0};
900-
for (const Subscript &ss : coarrayRef.subscript()) {
901-
if (ss.Rank() > 0) {
902-
shape.emplace_back(GetExtent(ss, base, dimension));
903-
}
904-
++dimension;
905-
}
906-
return shape;
907-
}
894+
return (*this)(coarrayRef.base());
908895
}
909896

910897
auto GetShapeHelper::operator()(const Substring &substring) const -> Result {

flang/lib/Evaluate/tools.cpp

+14-1
Original file line numberDiff line numberDiff line change
@@ -1090,7 +1090,7 @@ auto GetSymbolVectorHelper::operator()(const ArrayRef &x) const -> Result {
10901090
return GetSymbolVector(x.base());
10911091
}
10921092
auto GetSymbolVectorHelper::operator()(const CoarrayRef &x) const -> Result {
1093-
return x.base();
1093+
return GetSymbolVector(x.base());
10941094
}
10951095

10961096
const Symbol *GetLastTarget(const SymbolVector &symbols) {
@@ -1320,6 +1320,19 @@ std::optional<parser::MessageFixedText> CheckProcCompatibility(bool isCall,
13201320
return msg;
13211321
}
13221322

1323+
const Symbol *UnwrapWholeSymbolOrComponentOrCoarrayRef(const DataRef &dataRef) {
1324+
if (const SymbolRef * p{std::get_if<SymbolRef>(&dataRef.u)}) {
1325+
return &p->get();
1326+
} else if (const Component * c{std::get_if<Component>(&dataRef.u)}) {
1327+
if (c->base().Rank() == 0) {
1328+
return &c->GetLastSymbol();
1329+
}
1330+
} else if (const CoarrayRef * c{std::get_if<CoarrayRef>(&dataRef.u)}) {
1331+
return UnwrapWholeSymbolOrComponentOrCoarrayRef(c->base());
1332+
}
1333+
return nullptr;
1334+
}
1335+
13231336
// GetLastPointerSymbol()
13241337
static const Symbol *GetLastPointerSymbol(const Symbol &symbol) {
13251338
return IsPointer(GetAssociationRoot(symbol)) ? &symbol : nullptr;

flang/lib/Evaluate/variable.cpp

+14-43
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,9 @@ Triplet &Triplet::set_stride(Expr<SubscriptInteger> &&expr) {
6969
return *this;
7070
}
7171

72-
CoarrayRef::CoarrayRef(SymbolVector &&base, std::vector<Subscript> &&ss,
73-
std::vector<Expr<SubscriptInteger>> &&css)
74-
: base_{std::move(base)}, subscript_(std::move(ss)),
75-
cosubscript_(std::move(css)) {
76-
CHECK(!base_.empty());
77-
CHECK(!cosubscript_.empty());
78-
}
72+
CoarrayRef::CoarrayRef(
73+
DataRef &&base, std::vector<Expr<SubscriptInteger>> &&css)
74+
: base_{std::move(base)}, cosubscript_(std::move(css)) {}
7975

8076
std::optional<Expr<SomeInteger>> CoarrayRef::stat() const {
8177
if (stat_) {
@@ -85,7 +81,7 @@ std::optional<Expr<SomeInteger>> CoarrayRef::stat() const {
8581
}
8682
}
8783

88-
std::optional<Expr<SomeInteger>> CoarrayRef::team() const {
84+
std::optional<Expr<SomeType>> CoarrayRef::team() const {
8985
if (team_) {
9086
return team_.value().value();
9187
} else {
@@ -99,16 +95,18 @@ CoarrayRef &CoarrayRef::set_stat(Expr<SomeInteger> &&v) {
9995
return *this;
10096
}
10197

102-
CoarrayRef &CoarrayRef::set_team(Expr<SomeInteger> &&v, bool isTeamNumber) {
103-
CHECK(IsVariable(v));
98+
CoarrayRef &CoarrayRef::set_team(Expr<SomeType> &&v) {
10499
team_.emplace(std::move(v));
105-
teamIsTeamNumber_ = isTeamNumber;
106100
return *this;
107101
}
108102

109-
const Symbol &CoarrayRef::GetFirstSymbol() const { return base_.front(); }
103+
const Symbol &CoarrayRef::GetFirstSymbol() const {
104+
return base().GetFirstSymbol();
105+
}
110106

111-
const Symbol &CoarrayRef::GetLastSymbol() const { return base_.back(); }
107+
const Symbol &CoarrayRef::GetLastSymbol() const {
108+
return base().GetLastSymbol();
109+
}
112110

113111
void Substring::SetBounds(std::optional<Expr<SubscriptInteger>> &lower,
114112
std::optional<Expr<SubscriptInteger>> &upper) {
@@ -426,17 +424,7 @@ int ArrayRef::Rank() const {
426424
}
427425
}
428426

429-
int CoarrayRef::Rank() const {
430-
if (!subscript_.empty()) {
431-
int rank{0};
432-
for (const auto &expr : subscript_) {
433-
rank += expr.Rank();
434-
}
435-
return rank;
436-
} else {
437-
return base_.back()->Rank();
438-
}
439-
}
427+
int CoarrayRef::Rank() const { return base().Rank(); }
440428

441429
int DataRef::Rank() const {
442430
return common::visit(common::visitors{
@@ -671,22 +659,6 @@ std::optional<DynamicType> Designator<T>::GetType() const {
671659
return std::nullopt;
672660
}
673661

674-
static NamedEntity AsNamedEntity(const SymbolVector &x) {
675-
CHECK(!x.empty());
676-
NamedEntity result{x.front()};
677-
int j{0};
678-
for (const Symbol &symbol : x) {
679-
if (j++ != 0) {
680-
DataRef base{result.IsSymbol() ? DataRef{result.GetLastSymbol()}
681-
: DataRef{result.GetComponent()}};
682-
result = NamedEntity{Component{std::move(base), symbol}};
683-
}
684-
}
685-
return result;
686-
}
687-
688-
NamedEntity CoarrayRef::GetBase() const { return AsNamedEntity(base_); }
689-
690662
// Equality testing
691663

692664
// For the purposes of comparing type parameter expressions while
@@ -759,9 +731,8 @@ bool ArrayRef::operator==(const ArrayRef &that) const {
759731
return base_ == that.base_ && subscript_ == that.subscript_;
760732
}
761733
bool CoarrayRef::operator==(const CoarrayRef &that) const {
762-
return base_ == that.base_ && subscript_ == that.subscript_ &&
763-
cosubscript_ == that.cosubscript_ && stat_ == that.stat_ &&
764-
team_ == that.team_ && teamIsTeamNumber_ == that.teamIsTeamNumber_;
734+
return base_ == that.base_ && cosubscript_ == that.cosubscript_ &&
735+
stat_ == that.stat_ && team_ == that.team_;
765736
}
766737
bool DataRef::operator==(const DataRef &that) const {
767738
return TestVariableEquality(*this, that);

0 commit comments

Comments
 (0)