diff options
author | Peter Klausler <35819229+klausler@users.noreply.github.com> | 2024-05-23 13:31:25 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-23 13:31:25 -0700 |
commit | 70d1844abebb786c1510f72f79558ff3e8710d39 (patch) | |
tree | c9cde39ed9eee0951c9fbbcc93c5f4209d3cdac8 /flang/lib/Semantics/resolve-names-utils.cpp | |
parent | 208544fc70d2cfd5b2c13232a267048108da1978 (diff) | |
download | llvm-70d1844abebb786c1510f72f79558ff3e8710d39.zip llvm-70d1844abebb786c1510f72f79558ff3e8710d39.tar.gz llvm-70d1844abebb786c1510f72f79558ff3e8710d39.tar.bz2 |
[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 https://github.com/llvm/llvm-project/issues/92636.
Diffstat (limited to 'flang/lib/Semantics/resolve-names-utils.cpp')
-rw-r--r-- | flang/lib/Semantics/resolve-names-utils.cpp | 44 |
1 files changed, 27 insertions, 17 deletions
diff --git a/flang/lib/Semantics/resolve-names-utils.cpp b/flang/lib/Semantics/resolve-names-utils.cpp index 3ca460b..e27a543 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<ObjectEntityDetails>().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_ = {}; } |