Author: Tim Keith Date: 2021-01-14T16:31:52-08:00 New Revision: d6acf3c2012b00f06a422e8704609676be7729b2
URL: https://github.com/llvm/llvm-project/commit/d6acf3c2012b00f06a422e8704609676be7729b2 DIFF: https://github.com/llvm/llvm-project/commit/d6acf3c2012b00f06a422e8704609676be7729b2.diff LOG: [flang] Fix use-associated procedure in generic When a use-associated procedure was included in a generic, we weren't correctly recording that fact. The ultimate symbol was added rather than the local symbol. Also, improve the message emitted for the specific procedure by mentioning the module it came from. This fixes one of the problems in https://bugs.llvm.org/show_bug.cgi?id=48648. Differential Revision: https://reviews.llvm.org/D94696 Added: Modified: flang/lib/Semantics/resolve-names.cpp flang/test/Semantics/modfile07.f90 flang/test/Semantics/resolve53.f90 Removed: ################################################################################ diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index d66f561fc3c5..cef4f0010302 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -2603,36 +2603,43 @@ void InterfaceVisitor::ResolveSpecificsInGeneric(Symbol &generic) { Say(*name, "Procedure '%s' not found"_err_en_US); continue; } - symbol = &symbol->GetUltimate(); if (symbol == &generic) { if (auto *specific{generic.get<GenericDetails>().specific()}) { symbol = specific; } } - if (!symbol->has<SubprogramDetails>() && - !symbol->has<SubprogramNameDetails>()) { + const Symbol &ultimate{symbol->GetUltimate()}; + if (!ultimate.has<SubprogramDetails>() && + !ultimate.has<SubprogramNameDetails>()) { Say(*name, "'%s' is not a subprogram"_err_en_US); continue; } if (kind == ProcedureKind::ModuleProcedure) { - if (const auto *nd{symbol->detailsIf<SubprogramNameDetails>()}) { + if (const auto *nd{ultimate.detailsIf<SubprogramNameDetails>()}) { if (nd->kind() != SubprogramKind::Module) { Say(*name, "'%s' is not a module procedure"_err_en_US); } } else { // USE-associated procedure - const auto *sd{symbol->detailsIf<SubprogramDetails>()}; + const auto *sd{ultimate.detailsIf<SubprogramDetails>()}; CHECK(sd); - if (symbol->owner().kind() != Scope::Kind::Module || + if (ultimate.owner().kind() != Scope::Kind::Module || sd->isInterface()) { Say(*name, "'%s' is not a module procedure"_err_en_US); } } } - if (!symbolsSeen.insert(*symbol).second) { - Say(name->source, - "Procedure '%s' is already specified in generic '%s'"_err_en_US, - name->source, MakeOpName(generic.name())); + if (!symbolsSeen.insert(ultimate).second) { + if (symbol == &ultimate) { + Say(name->source, + "Procedure '%s' is already specified in generic '%s'"_err_en_US, + name->source, MakeOpName(generic.name())); + } else { + Say(name->source, + "Procedure '%s' from module '%s' is already specified in generic '%s'"_err_en_US, + ultimate.name(), ultimate.owner().GetName().value(), + MakeOpName(generic.name())); + } continue; } details.AddSpecificProc(*symbol, name->source); diff --git a/flang/test/Semantics/modfile07.f90 b/flang/test/Semantics/modfile07.f90 index f3e98bf195f9..878e342ff16a 100644 --- a/flang/test/Semantics/modfile07.f90 +++ b/flang/test/Semantics/modfile07.f90 @@ -598,3 +598,29 @@ module m10d ! end interface ! private::operator(.ne.) !end + +module m11a +contains + subroutine s1() + end +end +!Expect: m11a.mod +!module m11a +!contains +! subroutine s1() +! end +!end + +module m11b + use m11a + interface g + module procedure s1 + end interface +end +!Expect: m11b.mod +!module m11b +! use m11a,only:s1 +! interface g +! procedure::s1 +! end interface +!end diff --git a/flang/test/Semantics/resolve53.f90 b/flang/test/Semantics/resolve53.f90 index 1487873bd86b..64b0d536fa17 100644 --- a/flang/test/Semantics/resolve53.f90 +++ b/flang/test/Semantics/resolve53.f90 @@ -471,11 +471,11 @@ real function f(x) subroutine s1() use m20 interface operator(.not.) - !ERROR: Procedure 'f' is already specified in generic 'OPERATOR(.NOT.)' + !ERROR: Procedure 'f' from module 'm20' is already specified in generic 'OPERATOR(.NOT.)' procedure f end interface interface operator(+) - !ERROR: Procedure 'f' is already specified in generic 'OPERATOR(+)' + !ERROR: Procedure 'f' from module 'm20' is already specified in generic 'OPERATOR(+)' procedure f end interface end subroutine s1 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits