From 7ebbe7dca438ddac88d1c3ab726497df0bb28ba9 Mon Sep 17 00:00:00 2001 From: Tim Keith Date: Fri, 7 Sep 2018 15:39:20 -0700 Subject: [PATCH] [flang] Write private symbols to .mod files We were trying to write only symbols that are part of the public API of a module to the .mod file. The problem with that is that submodules need access to the private symbols in their ancestor modules and submodules. For now, just write out all of the symbols, private or otherwise. We could be more precise by omitting some private symbols for modules that don't have separate module procedures and so can't have submodules. Also, the old implementation went into an infinite loop for recursive derived types. This makes CollectSymbols simpler, so have it do both the collecting and sorting. Make it static so that the types don't have to be defined in mod-file.h. Original-commit: flang-compiler/f18@33a10d6238c3b0062c43974114048ccc8cc1f450 Reviewed-on: https://github.com/flang-compiler/f18/pull/177 Tree-same-pre-rewrite: false --- flang/lib/semantics/mod-file.cc | 62 ++++++++++-------------------- flang/lib/semantics/mod-file.h | 5 --- flang/lib/semantics/scope.h | 1 + flang/test/semantics/modfile01.f90 | 3 ++ flang/test/semantics/modfile02.f90 | 4 ++ flang/test/semantics/modfile03.f90 | 1 + 6 files changed, 29 insertions(+), 47 deletions(-) diff --git a/flang/lib/semantics/mod-file.cc b/flang/lib/semantics/mod-file.cc index b93e4c85f23b..403daf3b2e05 100644 --- a/flang/lib/semantics/mod-file.cc +++ b/flang/lib/semantics/mod-file.cc @@ -40,6 +40,7 @@ static constexpr auto magic{"!mod$ v1 sum:"}; static const SourceName *GetSubmoduleParent(const parser::Program &); static std::string ModFilePath( const std::string &, const SourceName &, const std::string &); +static std::vector CollectSymbols(const Scope &); static void PutEntity(std::ostream &, const Symbol &); static void PutObjectEntity(std::ostream &, const Symbol &); static void PutProcEntity(std::ostream &, const Symbol &); @@ -123,50 +124,11 @@ std::string ModFileWriter::GetAsString(const Symbol &symbol) { // Put out the visible symbols from scope. void ModFileWriter::PutSymbols(const Scope &scope) { bool didContains{false}; - for (const auto *symbol : SortSymbols(CollectSymbols(scope))) { + for (const auto *symbol : CollectSymbols(scope)) { PutSymbol(*symbol, didContains); } } -// Sort symbols by their original order, not by name. -ModFileWriter::symbolVector ModFileWriter::SortSymbols( - const ModFileWriter::symbolSet symbols) { - ModFileWriter::symbolVector sorted; - sorted.reserve(symbols.size()); - for (const auto *symbol : symbols) { - sorted.push_back(symbol); - } - auto compare{[](const Symbol *x, const Symbol *y) { - return x->name().begin() < y->name().begin(); - }}; - std::sort(sorted.begin(), sorted.end(), compare); - return sorted; -} - -// Return all symbols needed from this scope. -ModFileWriter::symbolSet ModFileWriter::CollectSymbols(const Scope &scope) { - ModFileWriter::symbolSet symbols; - for (const auto &pair : scope) { - auto *symbol{pair.second}; - // include all components of derived types and other non-private symbols - if (scope.kind() == Scope::Kind::DerivedType || - !symbol->attrs().test(Attr::PRIVATE)) { - symbols.insert(symbol); - // ensure the type symbol is included too, even if private - if (const auto *type{symbol->GetType()}) { - auto category{type->category()}; - if (category == DeclTypeSpec::TypeDerived || - category == DeclTypeSpec::ClassDerived) { - auto *typeSymbol{type->derivedTypeSpec().scope()->symbol()}; - symbols.insert(typeSymbol); - } - } - // TODO: other related symbols, e.g. in initial values - } - } - return symbols; -} - void ModFileWriter::PutSymbol(const Symbol &symbol, bool &didContains) { std::visit( common::visitors{ @@ -216,7 +178,7 @@ void ModFileWriter::PutDerivedType(const Symbol &typeSymbol) { if (details.hasTypeParams()) { bool first{true}; decls_ << '('; - for (const auto *symbol : SortSymbols(CollectSymbols(typeScope))) { + for (const auto *symbol : CollectSymbols(typeScope)) { if (symbol->has()) { PutLower(first ? decls_ : decls_ << ',', *symbol); first = false; @@ -311,10 +273,26 @@ void ModFileWriter::PutUseExtraAttr( } } +// Collect the symbols of this scope sorted by their original order, not name. +std::vector CollectSymbols(const Scope &scope) { + std::set symbols; // to prevent duplicates + std::vector sorted; + sorted.reserve(scope.size()); + for (const auto &pair : scope) { + auto *symbol{pair.second}; + if (symbols.insert(symbol).second) { + sorted.push_back(symbol); + } + } + std::sort(sorted.begin(), sorted.end(), [](const Symbol *x, const Symbol *y) { + return x->name().begin() < y->name().begin(); + }); + return sorted; +} + void PutEntity(std::ostream &os, const Symbol &symbol) { std::visit( common::visitors{ - [&](const EntityDetails &) { PutObjectEntity(os, symbol); }, [&](const ObjectEntityDetails &) { PutObjectEntity(os, symbol); }, [&](const ProcEntityDetails &) { PutProcEntity(os, symbol); }, [&](const TypeParamDetails &) { PutTypeParam(os, symbol); }, diff --git a/flang/lib/semantics/mod-file.h b/flang/lib/semantics/mod-file.h index 091f520da29f..aad20294681a 100644 --- a/flang/lib/semantics/mod-file.h +++ b/flang/lib/semantics/mod-file.h @@ -47,9 +47,6 @@ public: bool WriteAll(); private: - using symbolSet = std::set; - using symbolVector = std::vector; - std::string dir_{"."}; // The mod file consists of uses, declarations, and contained subprograms: std::stringstream uses_; @@ -64,8 +61,6 @@ private: void Write(const Symbol &); std::string GetAsString(const Symbol &); void PutSymbols(const Scope &); - symbolVector SortSymbols(const symbolSet); - symbolSet CollectSymbols(const Scope &); void PutSymbol(const Symbol &, bool &); void PutDerivedType(const Symbol &); void PutSubprogram(const Symbol &); diff --git a/flang/lib/semantics/scope.h b/flang/lib/semantics/scope.h index c786e517d6b1..8db42a4d2581 100644 --- a/flang/lib/semantics/scope.h +++ b/flang/lib/semantics/scope.h @@ -86,6 +86,7 @@ public: iterator find(const SourceName &name); const_iterator find(const SourceName &name) const; size_type erase(const SourceName &); + size_type size() const { return symbols_.size(); } // Look for symbol by name in this scope and host (depending on imports). Symbol *FindSymbol(const SourceName &); diff --git a/flang/test/semantics/modfile01.f90 b/flang/test/semantics/modfile01.f90 index a16b811a8020..73f33254e70b 100644 --- a/flang/test/semantics/modfile01.f90 +++ b/flang/test/semantics/modfile01.f90 @@ -28,9 +28,12 @@ end !Expect: m.mod !module m !integer::i +!integer,private::j !type::t !integer::i !integer,private::j !end type +!type,private::u +!end type !type(t)::x !end diff --git a/flang/test/semantics/modfile02.f90 b/flang/test/semantics/modfile02.f90 index 1841cae3512a..e852221035e7 100644 --- a/flang/test/semantics/modfile02.f90 +++ b/flang/test/semantics/modfile02.f90 @@ -30,5 +30,9 @@ end !type,private::t1 !integer::i !end type +!type,private::t2 +!integer::i +!end type !type(t1)::x1 +!type(t2),private::x2 !end diff --git a/flang/test/semantics/modfile03.f90 b/flang/test/semantics/modfile03.f90 index fb743d0dfa78..91f0009d183f 100644 --- a/flang/test/semantics/modfile03.f90 +++ b/flang/test/semantics/modfile03.f90 @@ -36,6 +36,7 @@ end !Expect: m1.mod !module m1 !integer::x1 +!integer,private::x2 !end !Expect: m2.mod