diff --git a/flang/include/flang/Semantics/scope.h b/flang/include/flang/Semantics/scope.h --- a/flang/include/flang/Semantics/scope.h +++ b/flang/include/flang/Semantics/scope.h @@ -108,6 +108,10 @@ const_iterator cbegin() const { return symbols_.cbegin(); } const_iterator cend() const { return symbols_.cend(); } + // Return symbols in declaration order (the iterators above are in name order) + SymbolVector GetSymbols() const; + std::vector> GetSymbols(); + iterator find(const SourceName &name); const_iterator find(const SourceName &name) const { return symbols_.find(name); diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -739,6 +739,10 @@ } inline bool operator<(SymbolRef x, SymbolRef y) { return *x < *y; } +inline bool operator<( + common::Reference x, common::Reference y) { + return *x < *y; +} using SymbolSet = std::set; } // namespace Fortran::semantics diff --git a/flang/lib/Semantics/compute-offsets.cpp b/flang/lib/Semantics/compute-offsets.cpp --- a/flang/lib/Semantics/compute-offsets.cpp +++ b/flang/lib/Semantics/compute-offsets.cpp @@ -65,21 +65,12 @@ if (scope.symbol() && scope.IsParameterizedDerivedType()) { return; // only process instantiations of parameterized derived types } - std::vector sorted; - sorted.reserve(scope.size()); - for (auto &pair : scope) { - Symbol &symbol{*pair.second}; - if (!symbol.has() && !symbol.has()) { - sorted.push_back(&symbol); - } - } - // NOTE: these must be sorted in the same order as in .mod files - std::sort(sorted.begin(), sorted.end(), - [](Symbol *x, Symbol *y) { return *x < *y; }); offset_ = 0; align_ = 0; - for (auto *symbol : sorted) { - DoSymbol(*symbol); + for (auto symbol : scope.GetSymbols()) { + if (!symbol->has() && !symbol->has()) { + DoSymbol(*symbol); + } } scope.set_size(offset_); scope.set_align(align_); diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -414,36 +414,25 @@ // Collect the symbols of this scope sorted by their original order, not name. // Namelists are an exception: they are sorted after other symbols. SymbolVector CollectSymbols(const Scope &scope) { - SymbolSet symbols; // to prevent duplicates SymbolVector sorted; SymbolVector namelist; - SymbolVector common; - sorted.reserve(scope.size() + scope.commonBlocks().size()); - for (const auto &pair : scope) { - const Symbol &symbol{*pair.second}; - if (!symbol.test(Symbol::Flag::ParentComp)) { - if (symbols.insert(symbol).second) { - if (symbol.has()) { - namelist.push_back(symbol); - } else { - sorted.push_back(symbol); - } + std::size_t commonSize{scope.commonBlocks().size()}; + auto symbols{scope.GetSymbols()}; + sorted.reserve(symbols.size() + commonSize); + for (SymbolRef symbol : symbols) { + if (!symbol->test(Symbol::Flag::ParentComp)) { + if (symbol->has()) { + namelist.push_back(symbol); + } else { + sorted.push_back(symbol); } } } + sorted.insert(sorted.end(), namelist.begin(), namelist.end()); for (const auto &pair : scope.commonBlocks()) { - const Symbol &symbol{*pair.second}; - if (symbols.insert(symbol).second) { - common.push_back(symbol); - } + sorted.push_back(*pair.second); } - // sort normal symbols, then namelists, then common blocks: - auto cursor{sorted.begin()}; - std::sort(cursor, sorted.end()); - cursor = sorted.insert(sorted.end(), namelist.begin(), namelist.end()); - std::sort(cursor, sorted.end()); - cursor = sorted.insert(sorted.end(), common.begin(), common.end()); - std::sort(cursor, sorted.end()); + std::sort(sorted.end() - commonSize, sorted.end()); return sorted; } diff --git a/flang/lib/Semantics/scope.cpp b/flang/lib/Semantics/scope.cpp --- a/flang/lib/Semantics/scope.cpp +++ b/flang/lib/Semantics/scope.cpp @@ -60,6 +60,25 @@ return children_.emplace_back(*this, kind, symbol); } +template +static std::vector> GetSortedSymbols( + std::map> symbols) { + std::vector> result; + result.reserve(symbols.size()); + for (auto &pair : symbols) { + result.push_back(*pair.second); + } + std::sort(result.begin(), result.end()); + return result; +} + +std::vector> Scope::GetSymbols() { + return GetSortedSymbols(symbols_); +} +SymbolVector Scope::GetSymbols() const { + return GetSortedSymbols(symbols_); +} + Scope::iterator Scope::find(const SourceName &name) { return symbols_.find(name); }