diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index f5bbced783fc7..ff5ae4af866dd 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -7480,16 +7480,17 @@ void ResolveNamesVisitor::CreateGeneric(const parser::GenericSpec &x) { if (existing) { Symbol &ultimate{existing->GetUltimate()}; if (auto *existingGeneric{ultimate.detailsIf()}) { - if (const auto *existingUse{existing->detailsIf()}) { - // Create a local copy of a use associated generic so that - // it can be locally extended without corrupting the original. - genericDetails.CopyFrom(*existingGeneric); - if (existingGeneric->specific()) { - genericDetails.set_specific(*existingGeneric->specific()); - } - AddGenericUse(genericDetails, existing->name(), existingUse->symbol()); - } else if (&existing->owner() == &currScope()) { - if (existing == &ultimate) { + if (&existing->owner() == &currScope()) { + if (const auto *existingUse{existing->detailsIf()}) { + // Create a local copy of a use associated generic so that + // it can be locally extended without corrupting the original. + genericDetails.CopyFrom(*existingGeneric); + if (existingGeneric->specific()) { + genericDetails.set_specific(*existingGeneric->specific()); + } + AddGenericUse( + genericDetails, existing->name(), existingUse->symbol()); + } else if (existing == &ultimate) { // Extending an extant generic in the same scope info.Resolve(existing); return; @@ -7497,6 +7498,8 @@ void ResolveNamesVisitor::CreateGeneric(const parser::GenericSpec &x) { // Host association of a generic is handled elsewhere CHECK(existing->has()); } + } else { + // Create a new generic for this scope. } } else if (ultimate.has() || ultimate.has()) { diff --git a/flang/test/Semantics/symbol25.f90 b/flang/test/Semantics/symbol25.f90 new file mode 100644 index 0000000000000..ac3dd37ef92eb --- /dev/null +++ b/flang/test/Semantics/symbol25.f90 @@ -0,0 +1,60 @@ +! RUN: %python %S/test_symbols.py %s %flang_fc1 +! Exercise generic redefinitions in inner procedures with conflicting subprograms. +!DEF: /m Module +module m + !DEF: /m/generic PUBLIC (Subroutine) Generic + interface generic + !DEF: /m/specific1 PUBLIC (Subroutine) Subprogram + module procedure :: specific1 + end interface +contains + !REF: /m/specific1 + subroutine specific1 + print *, 1 + end subroutine + !DEF: /m/specific2 PUBLIC (Subroutine) Subprogram + subroutine specific2 + print *, 2 + end subroutine + !DEF: /m/test PUBLIC (Subroutine) Subprogram + subroutine test + !REF: /m/specific1 + call generic + end subroutine + !DEF: /m/outer PUBLIC (Subroutine) Subprogram + subroutine outer + !DEF: /m/outer/inner1 (Subroutine) Subprogram + call inner1 + contains + !REF: /m/outer/inner1 + subroutine inner1 + !DEF: /m/outer/inner1/generic (Subroutine) Generic + interface generic + !REF: /m/specific2 + module procedure :: specific2 + end interface + !REF: /m/specific2 + call generic + end subroutine inner1 + end subroutine outer +end module m +!DEF: /main MainProgram +program main + !REF: /m + use :: m + !REF: /m/specific1 + call generic + !DEF: /main/inner2 (Subroutine) Subprogram + call inner2 +contains + !REF: /main/inner2 + subroutine inner2 + !DEF: /main/inner2/generic (Subroutine) Generic + interface generic + !DEF: /main/specific2 (Subroutine) Use + module procedure :: specific2 + end interface + !REF: /main/specific2 + call generic + end subroutine inner2 +end program