Skip to content

Commit af61d08

Browse files
authored
[flang] Handle forward reference to shadowing derived type from IMPLICIT (#87280)
A derived type name in an IMPLICIT statement might be a host association or it might be a forward reference to a local derived type, which may be shadowing a host-associated name. Add a scan over the specification part in search of derived type definitions to determine the right interpretation. Fixes #87215.
1 parent b685597 commit af61d08

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

flang/lib/Semantics/resolve-names.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,6 +1635,8 @@ class ResolveNamesVisitor : public virtual ScopeHandler,
16351635
void FinishDerivedTypeInstantiation(Scope &);
16361636
void ResolveExecutionParts(const ProgramTree &);
16371637
void UseCUDABuiltinNames();
1638+
void HandleDerivedTypesInImplicitStmts(const parser::ImplicitPart &,
1639+
const std::list<parser::DeclarationConstruct> &);
16381640
};
16391641

16401642
// ImplicitRules implementation
@@ -2035,6 +2037,7 @@ bool ImplicitRulesVisitor::Pre(const parser::ImplicitSpec &) {
20352037
}
20362038

20372039
void ImplicitRulesVisitor::Post(const parser::ImplicitSpec &) {
2040+
set_allowForwardReferenceToDerivedType(false);
20382041
EndDeclTypeSpec();
20392042
}
20402043

@@ -8329,6 +8332,67 @@ static bool NeedsExplicitType(const Symbol &symbol) {
83298332
}
83308333
}
83318334

8335+
void ResolveNamesVisitor::HandleDerivedTypesInImplicitStmts(
8336+
const parser::ImplicitPart &implicitPart,
8337+
const std::list<parser::DeclarationConstruct> &decls) {
8338+
// Detect derived type definitions and create symbols for them now if
8339+
// they appear in IMPLICIT statements so that these forward-looking
8340+
// references will not be ambiguous with host associations.
8341+
std::set<SourceName> implicitDerivedTypes;
8342+
for (const auto &ipStmt : implicitPart.v) {
8343+
if (const auto *impl{std::get_if<
8344+
parser::Statement<common::Indirection<parser::ImplicitStmt>>>(
8345+
&ipStmt.u)}) {
8346+
if (const auto *specs{std::get_if<std::list<parser::ImplicitSpec>>(
8347+
&impl->statement.value().u)}) {
8348+
for (const auto &spec : *specs) {
8349+
const auto &declTypeSpec{
8350+
std::get<parser::DeclarationTypeSpec>(spec.t)};
8351+
if (const auto *dtSpec{common::visit(
8352+
common::visitors{
8353+
[](const parser::DeclarationTypeSpec::Type &x) {
8354+
return &x.derived;
8355+
},
8356+
[](const parser::DeclarationTypeSpec::Class &x) {
8357+
return &x.derived;
8358+
},
8359+
[](const auto &) -> const parser::DerivedTypeSpec * {
8360+
return nullptr;
8361+
}},
8362+
declTypeSpec.u)}) {
8363+
implicitDerivedTypes.emplace(
8364+
std::get<parser::Name>(dtSpec->t).source);
8365+
}
8366+
}
8367+
}
8368+
}
8369+
}
8370+
if (!implicitDerivedTypes.empty()) {
8371+
for (const auto &decl : decls) {
8372+
if (const auto *spec{
8373+
std::get_if<parser::SpecificationConstruct>(&decl.u)}) {
8374+
if (const auto *dtDef{
8375+
std::get_if<common::Indirection<parser::DerivedTypeDef>>(
8376+
&spec->u)}) {
8377+
const parser::DerivedTypeStmt &dtStmt{
8378+
std::get<parser::Statement<parser::DerivedTypeStmt>>(
8379+
dtDef->value().t)
8380+
.statement};
8381+
const parser::Name &name{std::get<parser::Name>(dtStmt.t)};
8382+
if (implicitDerivedTypes.find(name.source) !=
8383+
implicitDerivedTypes.end() &&
8384+
!FindInScope(name)) {
8385+
DerivedTypeDetails details;
8386+
details.set_isForwardReferenced(true);
8387+
Resolve(name, MakeSymbol(name, std::move(details)));
8388+
implicitDerivedTypes.erase(name.source);
8389+
}
8390+
}
8391+
}
8392+
}
8393+
}
8394+
}
8395+
83328396
bool ResolveNamesVisitor::Pre(const parser::SpecificationPart &x) {
83338397
const auto &[accDecls, ompDecls, compilerDirectives, useStmts, importStmts,
83348398
implicitPart, decls] = x.t;
@@ -8347,6 +8411,7 @@ bool ResolveNamesVisitor::Pre(const parser::SpecificationPart &x) {
83478411
ClearUseOnly();
83488412
ClearModuleUses();
83498413
Walk(importStmts);
8414+
HandleDerivedTypesInImplicitStmts(implicitPart, decls);
83508415
Walk(implicitPart);
83518416
for (const auto &decl : decls) {
83528417
if (const auto *spec{

flang/test/Semantics/resolve29.f90

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module m1
33
type t1
44
end type
55
type t3
6+
integer t3c
67
end type
78
interface
89
subroutine s1(x)
@@ -64,6 +65,17 @@ subroutine s9()
6465
end type
6566
type(t2) x
6667
end
68+
subroutine s10()
69+
!Forward shadowing derived type in IMPLICIT
70+
!(supported by all other compilers)
71+
implicit type(t1) (c) ! forward shadow
72+
implicit type(t3) (d) ! host associated
73+
type t1
74+
integer a
75+
end type
76+
c%a = 1
77+
d%t3c = 2
78+
end
6779
end module
6880
module m2
6981
integer, parameter :: ck = kind('a')

0 commit comments

Comments
 (0)