diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index 50f7b68d80cb17..f130036d949d73 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -815,6 +815,7 @@ class Symbol { void SetIsExplicitBindName(bool); bool IsFuncResult() const; bool IsObjectArray() const; + const ArraySpec *GetShape() const; bool IsSubprogram() const; bool IsFromModFile() const; bool HasExplicitInterface() const { diff --git a/flang/lib/Semantics/resolve-names-utils.cpp b/flang/lib/Semantics/resolve-names-utils.cpp index 3ca460b8e46ac2..e27a54361749f3 100644 --- a/flang/lib/Semantics/resolve-names-utils.cpp +++ b/flang/lib/Semantics/resolve-names-utils.cpp @@ -376,25 +376,35 @@ static void PropagateSaveAttr(const EquivalenceSet &src, EquivalenceSet &dst) { void EquivalenceSets::AddToSet(const parser::Designator &designator) { if (CheckDesignator(designator)) { - Symbol &symbol{*currObject_.symbol}; - if (!currSet_.empty()) { - // check this symbol against first of set for compatibility - Symbol &first{currSet_.front().symbol}; - CheckCanEquivalence(designator.source, first, symbol) && - CheckCanEquivalence(designator.source, symbol, first); - } - auto subscripts{currObject_.subscripts}; - if (subscripts.empty() && symbol.IsObjectArray()) { - // record a whole array as its first element - for (const ShapeSpec &spec : symbol.get().shape()) { - auto &lbound{spec.lbound().GetExplicit().value()}; - subscripts.push_back(evaluate::ToInt64(lbound).value()); + if (Symbol * symbol{currObject_.symbol}) { + if (!currSet_.empty()) { + // check this symbol against first of set for compatibility + Symbol &first{currSet_.front().symbol}; + CheckCanEquivalence(designator.source, first, *symbol) && + CheckCanEquivalence(designator.source, *symbol, first); + } + auto subscripts{currObject_.subscripts}; + if (subscripts.empty()) { + if (const ArraySpec * shape{symbol->GetShape()}; + shape && shape->IsExplicitShape()) { + // record a whole array as its first element + for (const ShapeSpec &spec : *shape) { + if (auto lbound{spec.lbound().GetExplicit()}) { + if (auto lbValue{evaluate::ToInt64(*lbound)}) { + subscripts.push_back(*lbValue); + continue; + } + } + subscripts.clear(); // error recovery + break; + } + } } + auto substringStart{currObject_.substringStart}; + currSet_.emplace_back( + *symbol, subscripts, substringStart, designator.source); + PropagateSaveAttr(currSet_.back(), currSet_); } - auto substringStart{currObject_.substringStart}; - currSet_.emplace_back( - symbol, subscripts, substringStart, designator.source); - PropagateSaveAttr(currSet_.back(), currSet_); } currObject_ = {}; } diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index a46c0f378d5d0b..2622fa1e507474 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -6227,7 +6227,7 @@ void DeclarationVisitor::CheckEquivalenceSets() { } for (const parser::EquivalenceObject &object : *set) { const auto &designator{object.v.value()}; - // The designator was not resolved when it was encountered so do it now. + // The designator was not resolved when it was encountered, so do it now. // AnalyzeExpr causes array sections to be changed to substrings as needed Walk(designator); if (AnalyzeExpr(context(), designator)) { diff --git a/flang/lib/Semantics/symbol.cpp b/flang/lib/Semantics/symbol.cpp index 381905b89fb2dd..3eb120fd962faa 100644 --- a/flang/lib/Semantics/symbol.cpp +++ b/flang/lib/Semantics/symbol.cpp @@ -385,9 +385,17 @@ bool Symbol::IsFuncResult() const { details_); } +const ArraySpec *Symbol::GetShape() const { + if (const auto *details{std::get_if(&details_)}) { + return &details->shape(); + } else { + return nullptr; + } +} + bool Symbol::IsObjectArray() const { - const auto *details{std::get_if(&details_)}; - return details && details->IsArray(); + const ArraySpec *shape{GetShape()}; + return shape && !shape->empty(); } bool Symbol::IsSubprogram() const {