File tree Expand file tree Collapse file tree 4 files changed +83
-1
lines changed Expand file tree Collapse file tree 4 files changed +83
-1
lines changed Original file line number Diff line number Diff line change @@ -1416,6 +1416,8 @@ common::IgnoreTKRSet GetIgnoreTKR(const Symbol &);
14161416
14171417std::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_
Original file line number Diff line number Diff 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 },
Original file line number Diff line number Diff 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
Original file line number Diff line number Diff line change 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+
You can’t perform that action at this time.
0 commit comments