Index: flang/include/flang/Semantics/symbol.h =================================================================== --- flang/include/flang/Semantics/symbol.h +++ flang/include/flang/Semantics/symbol.h @@ -613,24 +613,27 @@ bool IsSubprogram() const; bool IsFromModFile() const; bool HasExplicitInterface() const { - return common::visit(common::visitors{ - [](const SubprogramDetails &) { return true; }, - [](const SubprogramNameDetails &) { return true; }, - [&](const ProcEntityDetails &x) { - return attrs_.test(Attr::INTRINSIC) || - x.HasExplicitInterface(); - }, - [](const ProcBindingDetails &x) { - return x.symbol().HasExplicitInterface(); - }, - [](const UseDetails &x) { - return x.symbol().HasExplicitInterface(); - }, - [](const HostAssocDetails &x) { - return x.symbol().HasExplicitInterface(); - }, - [](const auto &) { return false; }, - }, + return common::visit( + common::visitors{ + [](const SubprogramDetails &) { return true; }, + [](const SubprogramNameDetails &) { return true; }, + [&](const ProcEntityDetails &x) { + return attrs_.test(Attr::INTRINSIC) || x.HasExplicitInterface(); + }, + [](const ProcBindingDetails &x) { + return x.symbol().HasExplicitInterface(); + }, + [](const UseDetails &x) { + return x.symbol().HasExplicitInterface(); + }, + [](const HostAssocDetails &x) { + return x.symbol().HasExplicitInterface(); + }, + [](const GenericDetails &x) { + return x.specific() && x.specific()->HasExplicitInterface(); + }, + [](const auto &) { return false; }, + }, details_); } Index: flang/lib/Evaluate/characteristics.cpp =================================================================== --- flang/lib/Evaluate/characteristics.cpp +++ flang/lib/Evaluate/characteristics.cpp @@ -73,7 +73,9 @@ return common::visit( common::visitors{ [&](const semantics::ProcEntityDetails &proc) { - const semantics::ProcInterface &interface { proc.interface() }; + const semantics::ProcInterface &interface { + proc.interface() + }; if (interface.type()) { return Characterize(*interface.type(), context); } else if (interface.symbol()) { @@ -499,7 +501,9 @@ } return intrinsic; } - const semantics::ProcInterface &interface { proc.interface() }; + const semantics::ProcInterface &interface { + proc.interface() + }; if (const semantics::Symbol * interfaceSymbol{interface.symbol()}) { auto interface { CharacterizeProcedure(*interfaceSymbol, context, seenProcs) @@ -556,6 +560,13 @@ [&](const semantics::HostAssocDetails &assoc) { return CharacterizeProcedure(assoc.symbol(), context, seenProcs); }, + [&](const semantics::GenericDetails &generic) { + if (const semantics::Symbol * specific{generic.specific()}) { + return CharacterizeProcedure(*specific, context, seenProcs); + } else { + return std::optional{}; + } + }, [&](const semantics::EntityDetails &) { context.messages().Say( "Procedure '%s' is referenced before being sufficiently defined in a context where it must be so"_err_en_US, Index: flang/lib/Semantics/check-declarations.cpp =================================================================== --- flang/lib/Semantics/check-declarations.cpp +++ flang/lib/Semantics/check-declarations.cpp @@ -776,7 +776,9 @@ messages_.Say( "An ELEMENTAL subprogram may not have a dummy procedure"_err_en_US); } - const Symbol *interface { details.interface().symbol() }; + const Symbol *interface { + details.interface().symbol() + }; if (!symbol.attrs().test(Attr::INTRINSIC) && (IsElementalProcedure(symbol) || (interface && !interface->attrs().test(Attr::INTRINSIC) && @@ -1513,11 +1515,14 @@ // C760 constraints on the passed-object dummy argument // C757 constraints on procedure pointer components void CheckHelper::CheckPassArg( - const Symbol &proc, const Symbol *interface, const WithPassArg &details) { + const Symbol &proc, const Symbol *interface0, const WithPassArg &details) { if (proc.attrs().test(Attr::NOPASS)) { return; } const auto &name{proc.name()}; + const Symbol *interface { + interface0 ? FindInterface(*interface0) : nullptr + }; if (!interface) { messages_.Say(name, "Procedure component '%s' must have NOPASS attribute or explicit interface"_err_en_US, Index: flang/lib/Semantics/resolve-names.cpp =================================================================== --- flang/lib/Semantics/resolve-names.cpp +++ flang/lib/Semantics/resolve-names.cpp @@ -4850,10 +4850,13 @@ if (!procedure) { procedure = NoteInterfaceName(procedureName); } - if (auto *s{MakeTypeSymbol(bindingName, ProcBindingDetails{*procedure})}) { - SetPassNameOn(*s); - if (GetAttrs().test(Attr::DEFERRED)) { - context().SetError(*s); + if (procedure) { + if (auto *s{ + MakeTypeSymbol(bindingName, ProcBindingDetails{*procedure})}) { + SetPassNameOn(*s); + if (GetAttrs().test(Attr::DEFERRED)) { + context().SetError(*s); + } } } } Index: flang/lib/Semantics/tools.cpp =================================================================== --- flang/lib/Semantics/tools.cpp +++ flang/lib/Semantics/tools.cpp @@ -450,9 +450,25 @@ return common::visit( common::visitors{ [](const ProcEntityDetails &details) { - return details.interface().symbol(); + const Symbol *interface { + details.interface().symbol() + }; + return interface ? FindInterface(*interface) : nullptr; + }, + [](const ProcBindingDetails &details) { + return FindInterface(details.symbol()); + }, + [&](const SubprogramDetails &) { return &symbol; }, + [](const UseDetails &details) { + return FindInterface(details.symbol()); + }, + [](const HostAssocDetails &details) { + return FindInterface(details.symbol()); + }, + [](const GenericDetails &details) { + return details.specific() ? FindInterface(*details.specific()) + : nullptr; }, - [](const ProcBindingDetails &details) { return &details.symbol(); }, [](const auto &) -> const Symbol * { return nullptr; }, }, symbol.details()); @@ -478,6 +494,10 @@ [](const HostAssocDetails &details) { return FindSubprogram(details.symbol()); }, + [](const GenericDetails &details) { + return details.specific() ? FindSubprogram(*details.specific()) + : nullptr; + }, [](const auto &) -> const Symbol * { return nullptr; }, }, symbol.details()); Index: flang/test/Semantics/resolve20.f90 =================================================================== --- flang/test/Semantics/resolve20.f90 +++ flang/test/Semantics/resolve20.f90 @@ -57,7 +57,7 @@ integer :: i contains !ERROR: 'proc' must be an abstract interface or a procedure with an explicit interface - !ERROR: Procedure component 'p1' has invalid interface 'proc' + !ERROR: Procedure component 'p1' must have NOPASS attribute or explicit interface procedure(proc), deferred :: p1 end type t1