Skip to content

Commit a54e8b2

Browse files
authored
[flang] Silence bogus error about insufficiently defined interfaces (#116694)
The interfaces of separate module procedures are sufficiently well defined in a submodule to be used in a local generic interface; the compiler just needed to work a little harder to find them. Fixes #116567.
1 parent d20f55f commit a54e8b2

File tree

4 files changed

+83
-1
lines changed

4 files changed

+83
-1
lines changed

flang/include/flang/Evaluate/tools.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,6 +1416,8 @@ common::IgnoreTKRSet GetIgnoreTKR(const Symbol &);
14161416

14171417
std::optional<int> GetDummyArgumentNumber(const Symbol *);
14181418

1419+
const Symbol *FindAncestorModuleProcedure(const Symbol *symInSubmodule);
1420+
14191421
} // namespace Fortran::semantics
14201422

14211423
#endif // FORTRAN_EVALUATE_TOOLS_H_

flang/lib/Evaluate/characteristics.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -731,11 +731,16 @@ static std::optional<Procedure> CharacterizeProcedure(
731731
return std::optional<Procedure>{};
732732
}
733733
},
734-
[&](const semantics::EntityDetails &) {
734+
[&](const semantics::EntityDetails &x) {
735735
CheckForNested(symbol);
736736
return std::optional<Procedure>{};
737737
},
738738
[&](const semantics::SubprogramNameDetails &) {
739+
if (const semantics::Symbol *
740+
ancestor{FindAncestorModuleProcedure(&symbol)}) {
741+
return CharacterizeProcedure(
742+
*ancestor, context, seenProcs, emitError);
743+
}
739744
CheckForNested(symbol);
740745
return std::optional<Procedure>{};
741746
},

flang/lib/Evaluate/tools.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1990,4 +1990,37 @@ std::optional<int> GetDummyArgumentNumber(const Symbol *symbol) {
19901990
return std::nullopt;
19911991
}
19921992

1993+
// Given a symbol that is a SubprogramNameDetails in a submodule, try to
1994+
// find its interface definition in its module or ancestor submodule.
1995+
const Symbol *FindAncestorModuleProcedure(const Symbol *symInSubmodule) {
1996+
if (symInSubmodule && symInSubmodule->owner().IsSubmodule()) {
1997+
if (const auto *nameDetails{
1998+
symInSubmodule->detailsIf<semantics::SubprogramNameDetails>()};
1999+
nameDetails &&
2000+
nameDetails->kind() == semantics::SubprogramKind::Module) {
2001+
const Symbol *next{symInSubmodule->owner().symbol()};
2002+
while (const Symbol * submodSym{next}) {
2003+
next = nullptr;
2004+
if (const auto *modDetails{
2005+
submodSym->detailsIf<semantics::ModuleDetails>()};
2006+
modDetails && modDetails->isSubmodule() && modDetails->scope()) {
2007+
if (const semantics::Scope & parent{modDetails->scope()->parent()};
2008+
parent.IsSubmodule() || parent.IsModule()) {
2009+
if (auto iter{parent.find(symInSubmodule->name())};
2010+
iter != parent.end()) {
2011+
const Symbol &proc{iter->second->GetUltimate()};
2012+
if (IsProcedure(proc)) {
2013+
return &proc;
2014+
}
2015+
} else if (parent.IsSubmodule()) {
2016+
next = parent.symbol();
2017+
}
2018+
}
2019+
}
2020+
}
2021+
}
2022+
}
2023+
return nullptr;
2024+
}
2025+
19932026
} // namespace Fortran::semantics

flang/test/Semantics/smp-def02.f90

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
!RUN: %flang -fsyntax-only %s 2>&1 | FileCheck --allow-empty %s
2+
!Ensure no bogus error messages about insufficiently defined procedures
3+
!CHECK-NOT: error
4+
5+
module m
6+
interface
7+
module subroutine smp1(a1)
8+
end
9+
end interface
10+
end
11+
12+
submodule(m) sm1
13+
interface
14+
module subroutine smp2(a1,a2)
15+
end
16+
end interface
17+
end
18+
19+
submodule(m:sm1) sm2
20+
interface generic
21+
procedure smp1
22+
procedure smp2
23+
module subroutine smp3(a1,a2,a3)
24+
end
25+
end interface
26+
contains
27+
subroutine local1
28+
call generic(0.)
29+
call generic(0., 1.)
30+
call generic(0., 1., 2.)
31+
end
32+
subroutine local2(a1,a2,a3)
33+
end
34+
module procedure smp1
35+
end
36+
module subroutine smp2(a1,a2)
37+
end
38+
module subroutine smp3(a1,a2,a3)
39+
end
40+
end
41+
42+

0 commit comments

Comments
 (0)