[flang] Fix .mod file for symbols with same name as generic
authorTim Keith <tkeith@nvidia.com>
Tue, 26 Feb 2019 21:08:59 +0000 (13:08 -0800)
committerGitHub <noreply@github.com>
Thu, 28 Feb 2019 18:38:17 +0000 (10:38 -0800)
When a generic has the same name as a module procedure or derived type,
the latter weren't being written to the `.mod` file. Fix that by calling
`PutSymbol()` on those symbols from the generic. Change `PutSymbol()` to
accept `Symbol *` to make that more convenient.

Original-commit: flang-compiler/f18@1778efe981812b1d1d1b684647c72085f44c3209
Reviewed-on: https://github.com/flang-compiler/f18/pull/305
Tree-same-pre-rewrite: false

flang/lib/semantics/mod-file.cc
flang/lib/semantics/mod-file.h
flang/lib/semantics/symbol.h
flang/test/semantics/modfile07.f90

index d70b3ea..1f0d38f 100644 (file)
@@ -125,7 +125,7 @@ std::string ModFileWriter::GetAsString(const Symbol &symbol) {
 void ModFileWriter::PutSymbols(const Scope &scope) {
   std::stringstream typeBindings;  // stuff after CONTAINS in derived type
   for (const auto *symbol : CollectSymbols(scope)) {
-    PutSymbol(typeBindings, *symbol);
+    PutSymbol(typeBindings, symbol);
   }
   if (auto str{typeBindings.str()}; !str.empty()) {
     decls_ << "contains\n" << str;
@@ -135,37 +135,44 @@ void ModFileWriter::PutSymbols(const Scope &scope) {
 // Emit a symbol to decls_, except for bindings in a derived type (type-bound
 // procedures, type-bound generics, final procedures) which go to typeBindings.
 void ModFileWriter::PutSymbol(
-    std::stringstream &typeBindings, const Symbol &symbol) {
+    std::stringstream &typeBindings, const Symbol *symbol) {
+  if (symbol == nullptr) {
+    return;
+  }
   std::visit(
       common::visitors{
           [&](const ModuleDetails &) { /* should be current module */ },
-          [&](const DerivedTypeDetails &) { PutDerivedType(symbol); },
-          [&](const SubprogramDetails &) { PutSubprogram(symbol); },
-          [&](const GenericDetails &) { PutGeneric(symbol); },
-          [&](const UseDetails &) { PutUse(symbol); },
+          [&](const DerivedTypeDetails &) { PutDerivedType(*symbol); },
+          [&](const SubprogramDetails &) { PutSubprogram(*symbol); },
+          [&](const GenericDetails &x) {
+            PutGeneric(*symbol);
+            PutSymbol(typeBindings, x.specific());
+            PutSymbol(typeBindings, x.derivedType());
+          },
+          [&](const UseDetails &) { PutUse(*symbol); },
           [](const UseErrorDetails &) {},
           [&](const ProcBindingDetails &x) {
-            bool deferred{symbol.attrs().test(Attr::DEFERRED)};
+            bool deferred{symbol->attrs().test(Attr::DEFERRED)};
             typeBindings << "procedure";
             if (deferred) {
               PutLower(typeBindings << '(', x.symbol()) << ')';
             }
             PutPassName(typeBindings, x.passName());
-            PutAttrs(typeBindings, symbol.attrs());
-            PutLower(typeBindings << "::", symbol);
-            if (!deferred && x.symbol().name() != symbol.name()) {
+            PutAttrs(typeBindings, symbol->attrs());
+            PutLower(typeBindings << "::", *symbol);
+            if (!deferred && x.symbol().name() != symbol->name()) {
               PutLower(typeBindings << "=>", x.symbol());
             }
             typeBindings << '\n';
           },
           [&](const GenericBindingDetails &x) {
             for (const auto *proc : x.specificProcs()) {
-              PutLower(typeBindings << "generic::", symbol);
+              PutLower(typeBindings << "generic::", *symbol);
               PutLower(typeBindings << "=>", *proc) << '\n';
             }
           },
           [&](const NamelistDetails &x) {
-            PutLower(decls_ << "namelist/", symbol);
+            PutLower(decls_ << "namelist/", *symbol);
             char sep{'/'};
             for (const auto *object : x.objects()) {
               PutLower(decls_ << sep, *object);
@@ -174,26 +181,26 @@ void ModFileWriter::PutSymbol(
             decls_ << '\n';
           },
           [&](const CommonBlockDetails &x) {
-            PutLower(decls_ << "common/", symbol);
+            PutLower(decls_ << "common/", *symbol);
             char sep = '/';
             for (const auto *object : x.objects()) {
               PutLower(decls_ << sep, *object);
               sep = ',';
             }
             decls_ << '\n';
-            if (symbol.attrs().test(Attr::BIND_C)) {
-              PutAttrs(decls_, symbol.attrs(), x.bindName(), ""s);
-              PutLower(decls_ << "::/", symbol) << "/\n";
+            if (symbol->attrs().test(Attr::BIND_C)) {
+              PutAttrs(decls_, symbol->attrs(), x.bindName(), ""s);
+              PutLower(decls_ << "::/", *symbol) << "/\n";
             }
           },
           [&](const FinalProcDetails &) {
-            PutLower(typeBindings << "final::", symbol) << '\n';
+            PutLower(typeBindings << "final::", *symbol) << '\n';
           },
           [](const HostAssocDetails &) {},
           [](const MiscDetails &) {},
-          [&](const auto &) { PutEntity(decls_, symbol); },
+          [&](const auto &) { PutEntity(decls_, *symbol); },
       },
-      symbol.details());
+      symbol->details());
 }
 
 void ModFileWriter::PutDerivedType(const Symbol &typeSymbol) {
index 6b08c79..38d7bc0 100644 (file)
@@ -51,7 +51,7 @@ private:
   void Write(const Symbol &);
   std::string GetAsString(const Symbol &);
   void PutSymbols(const Scope &);
-  void PutSymbol(std::stringstream &, const Symbol &);
+  void PutSymbol(std::stringstream &, const Symbol *);
   void PutDerivedType(const Symbol &);
   void PutSubprogram(const Symbol &);
   void PutGeneric(const Symbol &);
index 8b5fdec..e88deef 100644 (file)
@@ -371,6 +371,7 @@ public:
   void add_specificProc(const Symbol &proc) { specificProcs_.push_back(&proc); }
 
   Symbol *specific() { return specific_; }
+  const Symbol *specific() const { return specific_; }
   void set_specific(Symbol &specific);
 
   // Derived type with same name as generic, if any.
index ec6843e..a1ca7ce 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (c) 2018, NVIDIA CORPORATION.  All rights reserved.
+! Copyright (c) 2018-2019, NVIDIA CORPORATION.  All rights reserved.
 !
 ! Licensed under the Apache License, Version 2.0 (the "License");
 ! you may not use this file except in compliance with the License.
@@ -37,6 +37,19 @@ contains
   end
 end
 
+module m2
+  interface foo
+    procedure foo
+  end interface
+  type :: foo
+    real :: x
+  end type
+contains
+  complex function foo()
+    foo = 1.0
+  end
+end
+
 !Expect: m.mod
 !module m
 ! generic::foo=>s1,s2
@@ -59,3 +72,15 @@ end
 !  integer(4)::x
 ! end
 !end
+
+!Expect: m2.mod
+!module m2
+! generic::foo=>foo
+! type::foo
+!  real(4)::x
+! end type
+!contains
+! function foo()
+!  complex(4)::foo
+! end
+!end