[flang] Write private symbols to .mod files
authorTim Keith <tkeith@nvidia.com>
Fri, 7 Sep 2018 22:39:20 +0000 (15:39 -0700)
committerTim Keith <tkeith@nvidia.com>
Mon, 10 Sep 2018 18:39:03 +0000 (11:39 -0700)
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
flang/lib/semantics/mod-file.h
flang/lib/semantics/scope.h
flang/test/semantics/modfile01.f90
flang/test/semantics/modfile02.f90
flang/test/semantics/modfile03.f90

index b93e4c8..403daf3 100644 (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); },
index 091f520..aad2029 100644 (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 &);
index c786e51..8db42a4 100644 (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 &);
index a16b811..73f3325 100644 (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
index 1841cae..e852221 100644 (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
index fb743d0..91f0009 100644 (file)
@@ -36,6 +36,7 @@ end
 !Expect: m1.mod
 !module m1
 !integer::x1
+!integer,private::x2
 !end
 
 !Expect: m2.mod