@@ -48,8 +48,8 @@ struct ModHeader {
4848};
4949
5050static std::optional<SourceName> GetSubmoduleParent (const parser::Program &);
51- static void CollectSymbols (
52- const Scope &, SymbolVector &, SymbolVector &, SourceOrderedSymbolSet & );
51+ static void CollectSymbols (const Scope &, SymbolVector &, SymbolVector &,
52+ SourceOrderedSymbolSet &, UnorderedSymbolSet * );
5353static void PutPassName (llvm::raw_ostream &, const std::optional<SourceName> &);
5454static void PutInit (llvm::raw_ostream &, const Symbol &, const MaybeExpr &,
5555 const parser::Expr *, SemanticsContext &);
@@ -131,7 +131,7 @@ static std::string ModFileName(const SourceName &name,
131131 return ancestorName.empty () ? result : ancestorName + ' -' + result;
132132}
133133
134- // Write the module file for symbol, which must be a module or submodule.
134+ // Writes the module file for symbol, which must be a module or submodule.
135135void ModFileWriter::Write (const Symbol &symbol) {
136136 const auto &module {symbol.get <ModuleDetails>()};
137137 if (symbol.test (Symbol::Flag::ModFile) || module .moduleFileHash ()) {
@@ -143,21 +143,30 @@ void ModFileWriter::Write(const Symbol &symbol) {
143143 std::string path{context_.moduleDirectory () + ' /' +
144144 ModFileName (symbol.name (), ancestorName, context_.moduleFileSuffix ())};
145145
146- std::set<std::string> hermeticModuleNames;
147- hermeticModuleNames.insert (symbol.name ().ToString ());
148146 UnorderedSymbolSet additionalModules;
147+ UnorderedSymbolSet dependenceClosure;
148+ if (hermeticModuleFileOutput_) {
149+ dependenceClosure = CollectAllDependences (
150+ DEREF (symbol.scope ()), IncludeOriginalSymbols | FollowUseAssociations);
151+ }
149152 PutSymbols (DEREF (symbol.scope ()),
150- hermeticModuleFileOutput_ ? &additionalModules : nullptr );
153+ hermeticModuleFileOutput_ ? &additionalModules : nullptr ,
154+ hermeticModuleFileOutput_ ? &dependenceClosure : nullptr );
155+ std::set<std::string> emittedModuleNames;
156+ emittedModuleNames.insert (symbol.name ().ToString ());
151157 auto asStr{GetAsString (symbol)};
158+
159+ // Emit additional modules for a hermetic module file
152160 while (!additionalModules.empty ()) {
153161 UnorderedSymbolSet nextPass{std::move (additionalModules)};
154162 additionalModules.clear ();
155163 for (const Symbol &modSym : nextPass) {
156164 if (!modSym.owner ().IsIntrinsicModules () &&
157- hermeticModuleNames.find (modSym.name ().ToString ()) ==
158- hermeticModuleNames.end ()) {
159- hermeticModuleNames.insert (modSym.name ().ToString ());
160- PutSymbols (DEREF (modSym.scope ()), &additionalModules);
165+ emittedModuleNames.find (modSym.name ().ToString ()) ==
166+ emittedModuleNames.end ()) {
167+ emittedModuleNames.insert (modSym.name ().ToString ());
168+ PutSymbols (
169+ DEREF (modSym.scope ()), &additionalModules, &dependenceClosure);
161170 asStr += GetAsString (modSym);
162171 }
163172 }
@@ -178,7 +187,8 @@ void ModFileWriter::WriteClosure(llvm::raw_ostream &out, const Symbol &symbol,
178187 !nonIntrinsicModulesWritten.insert (symbol).second ) {
179188 return ;
180189 }
181- PutSymbols (DEREF (symbol.scope ()), /* hermeticModules=*/ nullptr );
190+ PutSymbols (DEREF (symbol.scope ()), /* hermeticModules=*/ nullptr ,
191+ /* dependenceClosure=*/ nullptr );
182192 needsBuf_.clear (); // omit module checksums
183193 auto str{GetAsString (symbol)};
184194 for (auto depRef : std::move (usedNonIntrinsicModules_)) {
@@ -231,10 +241,11 @@ static void HarvestSymbolsNeededFromOtherModules(
231241 }
232242}
233243
234- void ModFileWriter::PrepareRenamings (const Scope &scope) {
244+ void ModFileWriter::PrepareRenamings (
245+ const Scope &scope, const UnorderedSymbolSet *dependenceClosure) {
235246 // Identify use-associated symbols already in scope under some name
236247 std::map<const Symbol *, const Symbol *> useMap;
237- for (const auto &[name , symbolRef] : scope) {
248+ for (const auto &[_ , symbolRef] : scope) {
238249 const Symbol *symbol{&*symbolRef};
239250 while (const auto *hostAssoc{symbol->detailsIf <HostAssocDetails>()}) {
240251 symbol = &hostAssoc->symbol ();
@@ -249,38 +260,42 @@ void ModFileWriter::PrepareRenamings(const Scope &scope) {
249260 // Establish any necessary renamings of symbols in other modules
250261 // to their names in this scope, creating those new names when needed.
251262 auto &renamings{context_.moduleFileOutputRenamings ()};
252- for (SymbolRef s : symbolsNeeded) {
253- if (s-> owner ().kind () != Scope::Kind::Module) {
263+ for (const Symbol &sym : symbolsNeeded) {
264+ if (sym. owner ().kind () != Scope::Kind::Module) {
254265 // Not a USE'able name from a module's top scope;
255266 // component, binding, dummy argument, &c.
256267 continue ;
257268 }
258- const Scope *sMod {FindModuleContaining (s-> owner ())};
269+ const Scope *sMod {FindModuleContaining (sym. owner ())};
259270 if (!sMod || sMod == &scope) {
260271 continue ;
261272 }
262- if (auto iter{useMap. find (&*s)}; iter != useMap. end ()) {
263- renamings. emplace (&*s, iter-> second -> name ());
273+ if (dependenceClosure &&
274+ dependenceClosure-> find (sym) == dependenceClosure-> end ()) {
264275 continue ;
265276 }
266- SourceName rename{s->name ()};
267- if (const Symbol * found{scope.FindSymbol (s->name ())}) {
268- if (found == &*s) {
277+ if (auto iter{useMap.find (&sym)}; iter != useMap.end ()) {
278+ renamings.emplace (&sym, iter->second ->name ());
279+ continue ;
280+ }
281+ SourceName rename{sym.name ()};
282+ if (const Symbol *found{scope.FindSymbol (sym.name ())}) {
283+ if (found == &sym) {
269284 continue ; // available in scope
270285 }
271286 if (const auto *generic{found->detailsIf <GenericDetails>()}) {
272- if (generic->derivedType () == &*s || generic->specific () == &*s ) {
287+ if (generic->derivedType () == &sym || generic->specific () == &sym ) {
273288 continue ;
274289 }
275290 } else if (found->has <UseDetails>()) {
276- if (&found->GetUltimate () == &*s ) {
291+ if (&found->GetUltimate () == &sym ) {
277292 continue ; // already use-associated with same name
278293 }
279294 }
280- if (&s-> owner () != &found->owner ()) { // Symbol needs renaming
295+ if (&sym. owner () != &found->owner ()) { // Symbol needs renaming
281296 rename = scope.context ().SaveTempName (
282297 DEREF (sMod ->symbol ()).name ().ToString () + " $" +
283- s-> name ().ToString ());
298+ sym. name ().ToString ());
284299 }
285300 }
286301 // Symbol is used in this scope but not visible under its name
@@ -290,25 +305,26 @@ void ModFileWriter::PrepareRenamings(const Scope &scope) {
290305 uses_ << " use " ;
291306 }
292307 uses_ << DEREF (sMod ->symbol ()).name () << " ,only:" ;
293- if (rename != s-> name ()) {
308+ if (rename != sym. name ()) {
294309 uses_ << rename << " =>" ;
295- renamings.emplace (&s-> GetUltimate (), rename);
310+ renamings.emplace (&sym. GetUltimate (), rename);
296311 }
297- uses_ << s-> name () << ' \n ' ;
312+ uses_ << sym. name () << ' \n ' ;
298313 useExtraAttrs_ << " private::" << rename << ' \n ' ;
299314 }
300315}
301316
302317// Put out the visible symbols from scope.
303- void ModFileWriter::PutSymbols (
304- const Scope &scope, UnorderedSymbolSet *hermeticModules) {
318+ void ModFileWriter::PutSymbols (const Scope &scope,
319+ UnorderedSymbolSet *hermeticModules,
320+ UnorderedSymbolSet *dependenceClosure) {
305321 SymbolVector sorted;
306322 SymbolVector uses;
307323 auto &renamings{context_.moduleFileOutputRenamings ()};
308324 auto previousRenamings{std::move (renamings)};
309- PrepareRenamings (scope);
325+ PrepareRenamings (scope, dependenceClosure );
310326 SourceOrderedSymbolSet modules;
311- CollectSymbols (scope, sorted, uses, modules);
327+ CollectSymbols (scope, sorted, uses, modules, dependenceClosure );
312328 // Write module files for dependences first so that their
313329 // hashes are known.
314330 for (const Symbol &mod : modules) {
@@ -792,12 +808,17 @@ void ModFileWriter::PutUseExtraAttr(
792808// Collect the symbols of this scope sorted by their original order, not name.
793809// Generics and namelists are exceptions: they are sorted after other symbols.
794810void CollectSymbols (const Scope &scope, SymbolVector &sorted,
795- SymbolVector &uses, SourceOrderedSymbolSet &modules) {
811+ SymbolVector &uses, SourceOrderedSymbolSet &modules,
812+ UnorderedSymbolSet *dependenceClosure) {
796813 SymbolVector namelist, generics;
797814 auto symbols{scope.GetSymbols ()};
798815 std::size_t commonSize{scope.commonBlocks ().size ()};
799816 sorted.reserve (symbols.size () + commonSize);
800817 for (const Symbol &symbol : symbols) {
818+ if (dependenceClosure &&
819+ dependenceClosure->find (symbol) == dependenceClosure->end ()) {
820+ continue ; // needless for the main module
821+ }
801822 const auto *generic{symbol.detailsIf <GenericDetails>()};
802823 if (generic) {
803824 uses.insert (uses.end (), generic->uses ().begin (), generic->uses ().end ());
0 commit comments