Skip to content

Commit 70d1844

Browse files
authored
[flang] Fix crash in error recovery (#92786)
EQUIVALENCE set processing assumes that any arrays have explicit shape and constant lower bounds. When an erroneous program violates those assumptions, the compiler crashes. Fix. Fixes #92636.
1 parent 208544f commit 70d1844

File tree

4 files changed

+39
-20
lines changed

4 files changed

+39
-20
lines changed

flang/include/flang/Semantics/symbol.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,7 @@ class Symbol {
815815
void SetIsExplicitBindName(bool);
816816
bool IsFuncResult() const;
817817
bool IsObjectArray() const;
818+
const ArraySpec *GetShape() const;
818819
bool IsSubprogram() const;
819820
bool IsFromModFile() const;
820821
bool HasExplicitInterface() const {

flang/lib/Semantics/resolve-names-utils.cpp

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -376,25 +376,35 @@ static void PropagateSaveAttr(const EquivalenceSet &src, EquivalenceSet &dst) {
376376

377377
void EquivalenceSets::AddToSet(const parser::Designator &designator) {
378378
if (CheckDesignator(designator)) {
379-
Symbol &symbol{*currObject_.symbol};
380-
if (!currSet_.empty()) {
381-
// check this symbol against first of set for compatibility
382-
Symbol &first{currSet_.front().symbol};
383-
CheckCanEquivalence(designator.source, first, symbol) &&
384-
CheckCanEquivalence(designator.source, symbol, first);
385-
}
386-
auto subscripts{currObject_.subscripts};
387-
if (subscripts.empty() && symbol.IsObjectArray()) {
388-
// record a whole array as its first element
389-
for (const ShapeSpec &spec : symbol.get<ObjectEntityDetails>().shape()) {
390-
auto &lbound{spec.lbound().GetExplicit().value()};
391-
subscripts.push_back(evaluate::ToInt64(lbound).value());
379+
if (Symbol * symbol{currObject_.symbol}) {
380+
if (!currSet_.empty()) {
381+
// check this symbol against first of set for compatibility
382+
Symbol &first{currSet_.front().symbol};
383+
CheckCanEquivalence(designator.source, first, *symbol) &&
384+
CheckCanEquivalence(designator.source, *symbol, first);
385+
}
386+
auto subscripts{currObject_.subscripts};
387+
if (subscripts.empty()) {
388+
if (const ArraySpec * shape{symbol->GetShape()};
389+
shape && shape->IsExplicitShape()) {
390+
// record a whole array as its first element
391+
for (const ShapeSpec &spec : *shape) {
392+
if (auto lbound{spec.lbound().GetExplicit()}) {
393+
if (auto lbValue{evaluate::ToInt64(*lbound)}) {
394+
subscripts.push_back(*lbValue);
395+
continue;
396+
}
397+
}
398+
subscripts.clear(); // error recovery
399+
break;
400+
}
401+
}
392402
}
403+
auto substringStart{currObject_.substringStart};
404+
currSet_.emplace_back(
405+
*symbol, subscripts, substringStart, designator.source);
406+
PropagateSaveAttr(currSet_.back(), currSet_);
393407
}
394-
auto substringStart{currObject_.substringStart};
395-
currSet_.emplace_back(
396-
symbol, subscripts, substringStart, designator.source);
397-
PropagateSaveAttr(currSet_.back(), currSet_);
398408
}
399409
currObject_ = {};
400410
}

flang/lib/Semantics/resolve-names.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6227,7 +6227,7 @@ void DeclarationVisitor::CheckEquivalenceSets() {
62276227
}
62286228
for (const parser::EquivalenceObject &object : *set) {
62296229
const auto &designator{object.v.value()};
6230-
// The designator was not resolved when it was encountered so do it now.
6230+
// The designator was not resolved when it was encountered, so do it now.
62316231
// AnalyzeExpr causes array sections to be changed to substrings as needed
62326232
Walk(designator);
62336233
if (AnalyzeExpr(context(), designator)) {

flang/lib/Semantics/symbol.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,9 +385,17 @@ bool Symbol::IsFuncResult() const {
385385
details_);
386386
}
387387

388+
const ArraySpec *Symbol::GetShape() const {
389+
if (const auto *details{std::get_if<ObjectEntityDetails>(&details_)}) {
390+
return &details->shape();
391+
} else {
392+
return nullptr;
393+
}
394+
}
395+
388396
bool Symbol::IsObjectArray() const {
389-
const auto *details{std::get_if<ObjectEntityDetails>(&details_)};
390-
return details && details->IsArray();
397+
const ArraySpec *shape{GetShape()};
398+
return shape && !shape->empty();
391399
}
392400

393401
bool Symbol::IsSubprogram() const {

0 commit comments

Comments
 (0)