diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -629,6 +629,10 @@ [](const HostAssocDetails &x) { return x.symbol().HasExplicitInterface(); }, + [](const GenericDetails &x) { + return x.specific() && + x.specific()->HasExplicitInterface(); + }, [](const auto &) { return false; }, }, details_); diff --git a/flang/lib/Evaluate/characteristics.cpp b/flang/lib/Evaluate/characteristics.cpp --- a/flang/lib/Evaluate/characteristics.cpp +++ b/flang/lib/Evaluate/characteristics.cpp @@ -499,7 +499,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) @@ -558,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, diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -1517,11 +1517,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, diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -4869,10 +4869,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); + } } } } diff --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp --- a/flang/lib/Semantics/tools.cpp +++ b/flang/lib/Semantics/tools.cpp @@ -456,9 +456,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()); @@ -484,6 +500,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()); diff --git a/flang/test/Semantics/resolve20.f90 b/flang/test/Semantics/resolve20.f90 --- a/flang/test/Semantics/resolve20.f90 +++ b/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