[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@33a10d6238
Reviewed-on: https://github.com/flang-compiler/f18/pull/177
Tree-same-pre-rewrite: false
This commit is contained in:
Tim Keith 2018-09-07 15:39:20 -07:00
parent 78c62eaf02
commit 7ebbe7dca4
6 changed files with 29 additions and 47 deletions

View File

@ -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<const Symbol *> 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<TypeParamDetails>()) {
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<const Symbol *> CollectSymbols(const Scope &scope) {
std::set<const Symbol *> symbols; // to prevent duplicates
std::vector<const Symbol *> 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); },

View File

@ -47,9 +47,6 @@ public:
bool WriteAll();
private:
using symbolSet = std::set<const Symbol *>;
using symbolVector = std::vector<const Symbol *>;
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 &);

View File

@ -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 &);

View File

@ -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

View File

@ -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

View File

@ -36,6 +36,7 @@ end
!Expect: m1.mod
!module m1
!integer::x1
!integer,private::x2
!end
!Expect: m2.mod