Skip to content

Commit

Permalink
[flang] Submodule names can clash only with submodule names (#67361)
Browse files Browse the repository at this point in the history
Name resolution creates symbols for submodules in their parents' scopes.
This can lead to bogus errors about name clashes between submodule names
and other entities in the parents' scopes.

Create symbols for submodules but do not add them to a scope's
dictionary.
  • Loading branch information
klausler committed Oct 16, 2023
1 parent ea7e50c commit e200b0e
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 15 deletions.
43 changes: 31 additions & 12 deletions flang/lib/Semantics/mod-file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1183,30 +1183,49 @@ Scope *ModFileReader::Read(const SourceName &name,
}
Scope &topScope{isIntrinsic.value_or(false) ? context_.intrinsicModulesScope()
: context_.globalScope()};
if (!ancestor) {
Symbol *moduleSymbol{nullptr};
if (!ancestor) { // module, not submodule
parentScope = &topScope;
auto pair{parentScope->try_emplace(name, UnknownDetails{})};
if (!pair.second) {
return nullptr;
}
moduleSymbol = &*pair.first->second;
moduleSymbol->set(Symbol::Flag::ModFile);
} else if (std::optional<SourceName> parent{GetSubmoduleParent(parseTree)}) {
// submodule with submodule parent
parentScope = Read(*parent, false /*not intrinsic*/, ancestor, silent);
} else {
// submodule with module parent
parentScope = ancestor;
}
auto pair{parentScope->try_emplace(name, UnknownDetails{})};
if (!pair.second) {
return nullptr;
}
// Process declarations from the module file
Symbol &modSymbol{*pair.first->second};
modSymbol.set(Symbol::Flag::ModFile);
bool wasInModuleFile{context_.foldingContext().inModuleFile()};
context_.foldingContext().set_inModuleFile(true);
ResolveNames(context_, parseTree, topScope);
context_.foldingContext().set_inModuleFile(wasInModuleFile);
CHECK(modSymbol.has<ModuleDetails>());
CHECK(modSymbol.test(Symbol::Flag::ModFile));
if (isIntrinsic.value_or(false)) {
modSymbol.attrs().set(Attr::INTRINSIC);
if (!moduleSymbol) {
// Submodule symbols' storage are owned by their parents' scopes,
// but their names are not in their parents' dictionaries -- we
// don't want to report bogus errors about clashes between submodule
// names and other objects in the parent scopes.
if (Scope * submoduleScope{ancestor->FindSubmodule(name)}) {
moduleSymbol = submoduleScope->symbol();
if (moduleSymbol) {
moduleSymbol->set(Symbol::Flag::ModFile);
}
}
}
if (moduleSymbol) {
CHECK(moduleSymbol->has<ModuleDetails>());
CHECK(moduleSymbol->test(Symbol::Flag::ModFile));
if (isIntrinsic.value_or(false)) {
moduleSymbol->attrs().set(Attr::INTRINSIC);
}
return moduleSymbol->scope();
} else {
return nullptr;
}
return modSymbol.scope();
}

parser::Message &ModFileReader::Say(const SourceName &name,
Expand Down
6 changes: 5 additions & 1 deletion flang/lib/Semantics/resolve-names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3230,7 +3230,11 @@ bool ModuleVisitor::BeginSubmodule(
}

void ModuleVisitor::BeginModule(const parser::Name &name, bool isSubmodule) {
auto &symbol{MakeSymbol(name, ModuleDetails{isSubmodule})};
// Submodule symbols are not visible in their parents' scopes.
Symbol &symbol{isSubmodule ? Resolve(name,
currScope().MakeSymbol(name.source, Attrs{},
ModuleDetails{true}))
: MakeSymbol(name, ModuleDetails{false})};
auto &details{symbol.get<ModuleDetails>()};
PushScope(Scope::Kind::Module, &symbol);
details.set_scope(&currScope());
Expand Down
4 changes: 3 additions & 1 deletion flang/test/Semantics/modproc01.f90
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ module subroutine ms(f)
procedure(mf) :: f
end subroutine
end interface
integer sm
end module
!CHECK: mf, MODULE, PUBLIC (Function): Subprogram isInterface result:TYPE(pdt2(k2=2_4,l2=n)) res (INTEGER(4) n,CHARACTER(n,1) str,TYPE(pdt1(k1=1_4,l1=n)) x1)
!CHECK: pdt1, PUBLIC: DerivedType components: a1
!CHECK: pdt2, PUBLIC: DerivedType components: j2,a2
!CHECK: sm: Module (m)
!CHECK: sm, PUBLIC size=4 offset=0: ObjectEntity type: INTEGER(4)
!CHECK: DerivedType scope: pdt1
!CHECK: a1, ALLOCATABLE: ObjectEntity type: TYPE(pdt2(int(k1,kind=4),int(l1,kind=4)))
!CHECK: k1: TypeParam type:INTEGER(4) Kind
Expand Down Expand Up @@ -128,6 +129,7 @@ program test
!CHECK: mf, MODULE (Function): Use from mf in m
!CHECK: pdt1: Use from pdt1 in m
!CHECK: pdt2: Use from pdt2 in m
!CHECK: sm: Use from sm in m
!CHECK: x size=88 offset=0: ObjectEntity type: TYPE(pdt2(k2=2_4,l2=3_4))
!CHECK: DerivedType scope: size=88 alignment=8 instantiation of pdt2(k2=2_4,l2=3_4)
!CHECK: a2 size=80 offset=8: ObjectEntity type: TYPE(pdt1(k1=2_4,l1=3_4)) shape: 1_8:2_8
Expand Down
1 change: 0 additions & 1 deletion flang/test/Semantics/modproc02.f90
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ module subroutine s(x) ! implicitly typed

!CHECK: Module scope: m size=0 alignment=1 sourceRange=63 bytes
!CHECK: s, MODULE, PUBLIC (Subroutine): Subprogram isInterface (REAL(4) x)
!CHECK: sm: Module (m)
!CHECK: Subprogram scope: s size=4 alignment=4 sourceRange=26 bytes
!CHECK: s (Subroutine): HostAssoc
!CHECK: x (Implicit) size=4 offset=0: ObjectEntity dummy type: REAL(4)
Expand Down

0 comments on commit e200b0e

Please sign in to comment.