Skip to content

Commit

Permalink
[flang] Fix USE with homonymous renaming
Browse files Browse the repository at this point in the history
Fortran requires that a USE with renaming prevent the USE'd symbol
from also being associated into a scope without renaming.  The
implementation in name resolution gets confused in the case of
a USE with renaming using the same name ("x => x").  Clean things
up.  Fixes LLVM bug #63397.

Differential Revision: https://reviews.llvm.org/D153452
  • Loading branch information
klausler committed Jun 22, 2023
1 parent 252d1c4 commit ce8effc
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 18 deletions.
33 changes: 15 additions & 18 deletions flang/lib/Semantics/resolve-names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -789,8 +789,8 @@ class ModuleVisitor : public virtual ScopeHandler {
SourceName, SourceName, Symbol &localSymbol, const Symbol &useSymbol);
void AddUse(const GenericSpecInfo &);
// If appropriate, erase a previously USE-associated symbol
void EraseRenamedSymbol(const Symbol &);
// Record a name appearing in a USE rename clause
void EraseRenamedUse(const Symbol *);
// Record a name appearing as the target of a USE rename clause
void AddUseRename(const SourceName &name) {
useRenames_.emplace(std::make_pair(name, useModuleScope_));
}
Expand Down Expand Up @@ -2775,11 +2775,8 @@ bool ModuleVisitor::Pre(const parser::Only &x) {
bool ModuleVisitor::Pre(const parser::Rename::Names &x) {
const auto &localName{std::get<0>(x.t)};
const auto &useName{std::get<1>(x.t)};
AddUseRename(useName.source);
SymbolRename rename{AddUse(localName.source, useName.source)};
if (rename.use && localName.source != useName.source) {
EraseRenamedSymbol(*rename.use);
}
AddUseRename(useName.source);
Resolve(useName, rename.use);
Resolve(localName, rename.local);
return false;
Expand All @@ -2797,9 +2794,6 @@ bool ModuleVisitor::Pre(const parser::Rename::Operators &x) {
"Logical constant '%s' may not be used as a defined operator"_err_en_US);
} else {
SymbolRename rename{AddUse(localInfo.symbolName(), useInfo.symbolName())};
if (rename.use) {
EraseRenamedSymbol(*rename.use);
}
useInfo.Resolve(rename.use);
localInfo.Resolve(rename.local);
}
Expand Down Expand Up @@ -2910,17 +2904,20 @@ static bool ConvertToUseError(
}
}

// If a symbol has previously been USE-associated and did not appear in a USE
// ONLY clause, erase it from the current scope. This is needed when a name
// appears in a USE rename clause.
void ModuleVisitor::EraseRenamedSymbol(const Symbol &useSymbol) {
const SourceName &name{useSymbol.name()};
// If a symbol has previously been USE-associated and did not appear in
// an ONLY clause or renaming, erase it from the current scope. This is
// necessary when a name appears as the target of a later USE rename clause.
void ModuleVisitor::EraseRenamedUse(const Symbol *useSymbol) {
if (!useSymbol) {
return;
}
const SourceName &name{useSymbol->name()};
if (const Symbol * symbol{FindInScope(name)}) {
if (auto *useDetails{symbol->detailsIf<UseDetails>()}) {
if (const auto *useDetails{symbol->detailsIf<UseDetails>()}) {
const Symbol &moduleSymbol{useDetails->symbol()};
if (moduleSymbol.name() == name &&
moduleSymbol.owner() == useSymbol.owner() && IsUseRenamed(name) &&
!IsUseOnly(name)) {
moduleSymbol.owner() == useSymbol->owner() && !IsUseOnly(name) &&
!IsUseRenamed(name)) {
EraseSymbol(*symbol);
}
}
Expand All @@ -2930,7 +2927,7 @@ void ModuleVisitor::EraseRenamedSymbol(const Symbol &useSymbol) {
void ModuleVisitor::DoAddUse(SourceName location, SourceName localName,
Symbol &localSymbol, const Symbol &useSymbol) {
if (localName != useSymbol.name()) {
EraseRenamedSymbol(useSymbol);
EraseRenamedUse(&useSymbol);
}
if (auto *details{localSymbol.detailsIf<UseErrorDetails>()}) {
details->add_occurrence(location, *useModuleScope_);
Expand Down
6 changes: 6 additions & 0 deletions flang/test/Semantics/modfile41.f90
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,9 @@ subroutine testUse12
!ERROR: 'a' is use-associated from module 'm4' and cannot be re-declared
integer :: a = 2
end
subroutine testUse13
use m1, a => a
use m1, z => a ! should not erase 'a', it was renamed
!ERROR: 'a' is use-associated from module 'm1' and cannot be re-declared
integer :: a = 13
end

0 comments on commit ce8effc

Please sign in to comment.