Index: flang/lib/Semantics/program-tree.h =================================================================== --- flang/lib/Semantics/program-tree.h +++ flang/lib/Semantics/program-tree.h @@ -30,6 +30,8 @@ class ProgramTree { public: using EntryStmtList = std::list>; + using GenericSpecList = + std::list>; // Build the ProgramTree rooted at one of these program units. static ProgramTree Build(const parser::ProgramUnit &); @@ -71,10 +73,9 @@ const parser::ExecutionPart *exec() const { return exec_; } std::list &children() { return children_; } const std::list &children() const { return children_; } - const std::list> & - entryStmts() const { - return entryStmts_; - } + const EntryStmtList &entryStmts() const { return entryStmts_; } + const GenericSpecList &genericSpecs() const { return genericSpecs_; } + Symbol::Flag GetSubpFlag() const; bool IsModule() const; // Module or Submodule bool HasModulePrefix() const; // in function or subroutine stmt @@ -82,6 +83,7 @@ void set_scope(Scope &); void AddChild(ProgramTree &&); void AddEntry(const parser::EntryStmt &); + void AddGeneric(const parser::GenericSpec &); template ProgramTree &set_stmt(const parser::Statement &stmt) { @@ -102,6 +104,7 @@ const parser::ExecutionPart *exec_{nullptr}; std::list children_; EntryStmtList entryStmts_; + GenericSpecList genericSpecs_; Scope *scope_{nullptr}; const parser::CharBlock *endStmt_{nullptr}; bool isSpecificationPartResolved_{false}; Index: flang/lib/Semantics/program-tree.cpp =================================================================== --- flang/lib/Semantics/program-tree.cpp +++ flang/lib/Semantics/program-tree.cpp @@ -44,6 +44,37 @@ } } +// Collects generics that define simple names that could include +// identically-named subprograms as specific procedures. +static void GetGenerics( + ProgramTree &node, const parser::SpecificationPart &spec) { + for (const auto &decl : + std::get>(spec.t)) { + if (const auto *spec{ + std::get_if(&decl.u)}) { + if (const auto *generic{std::get_if< + parser::Statement>>( + &spec->u)}) { + const parser::GenericStmt &genericStmt{generic->statement.value()}; + const auto &genericSpec{std::get(genericStmt.t)}; + node.AddGeneric(genericSpec); + } else if (const auto *interface{ + std::get_if>( + &spec->u)}) { + const parser::InterfaceBlock &interfaceBlock{interface->value()}; + const parser::InterfaceStmt &interfaceStmt{ + std::get>(interfaceBlock.t) + .statement}; + const auto *genericSpec{ + std::get_if>(&interfaceStmt.u)}; + if (genericSpec && genericSpec->has_value()) { + node.AddGeneric(**genericSpec); + } + } + } + } +} + template static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) { const auto &spec{std::get(x.t)}; @@ -53,6 +84,7 @@ ProgramTree node{name, spec, &exec}; GetEntryStmts(node, spec); GetEntryStmts(node, exec); + GetGenerics(node, spec); if (subps) { for (const auto &subp : std::get>(subps->t)) { @@ -75,6 +107,7 @@ const auto &spec{std::get(x.t)}; const auto &subps{std::get>(x.t)}; ProgramTree node{name, spec}; + GetGenerics(node, spec); if (subps) { for (const auto &subp : std::get>(subps->t)) { @@ -230,4 +263,8 @@ entryStmts_.emplace_back(entryStmt); } +void ProgramTree::AddGeneric(const parser::GenericSpec &generic) { + genericSpecs_.emplace_back(generic); +} + } // namespace Fortran::semantics Index: flang/lib/Semantics/resolve-names.cpp =================================================================== --- flang/lib/Semantics/resolve-names.cpp +++ flang/lib/Semantics/resolve-names.cpp @@ -7054,6 +7054,18 @@ symbol.set(child.GetSubpFlag()); } } + for (const auto &generic : node.genericSpecs()) { + if (const auto *name{std::get_if(&generic->u)}) { + if (currScope().find(name->source) != currScope().end()) { + // If this scope has both a generic interface and a contained + // subprogram with the same name, create the generic's symbol + // now so that any other generics of the same name that are pulled + // into scope later via USE association will properly merge instead + // of raising a bogus error due a conflict with the subprogram. + CreateGeneric(*generic); + } + } + } } // Push a new scope for this node or return false on error. Index: flang/test/Semantics/resolve18.f90 =================================================================== --- flang/test/Semantics/resolve18.f90 +++ flang/test/Semantics/resolve18.f90 @@ -182,3 +182,29 @@ function f13() end function f13 end module m13 + +! Not an error +module m14 + interface gen1 + module procedure s + end interface + generic :: gen2 => s + contains + subroutine s(x) + integer(1) :: x + end subroutine s +end module m14 +module m15 + use m14 + interface gen1 + module procedure gen1 + end interface + generic :: gen2 => gen2 + contains + subroutine gen1(x) + integer(2) :: x + end subroutine gen1 + subroutine gen2(x) + integer(4) :: x + end subroutine gen2 +end module m15