[flang] Fix .mod file for symbols with same name as generic

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@1778efe981
Reviewed-on: https://github.com/flang-compiler/f18/pull/305
Tree-same-pre-rewrite: false
This commit is contained in:
Tim Keith 2019-02-26 13:08:59 -08:00 committed by GitHub
parent 9a497ddbad
commit 563e65ded1
4 changed files with 54 additions and 21 deletions

View 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) {

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

View 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.

View 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