Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flang] Submodule names can clash only with submodule names #67361

Merged
merged 1 commit into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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