public:
explicit ProcBindingDetails(const Symbol &symbol) : symbol_{symbol} {}
const Symbol &symbol() const { return symbol_; }
+ void ReplaceSymbol(const Symbol &symbol) { symbol_ = symbol; }
private:
SymbolRef symbol_; // procedure bound to; may be forward
// Returns a pointer to the function's symbol when true, else null
const Symbol *IsFunctionResultWithSameNameAsFunction(const Symbol &);
bool IsOrContainsEventOrLockComponent(const Symbol &);
-bool CanBeTypeBoundProc(const Symbol *);
+bool CanBeTypeBoundProc(const Symbol &);
// Does a non-PARAMETER symbol have explicit initialization with =value or
// =>target in its declaration (but not in a DATA statement)? (Being
// ALLOCATABLE or having a derived type with default component initialization
expr.u);
}
-// Apply GetUltimate(), then if the symbol is a generic procedure shadowing a
+// Applies GetUltimate(), then if the symbol is a generic procedure shadowing a
// specific procedure of the same name, return it instead.
const Symbol &BypassGeneric(const Symbol &);
}
if (isGeneric()) {
Symbol &genericSymbol{GetGenericSymbol()};
- if (genericSymbol.has<GenericDetails>()) {
- genericSymbol.get<GenericDetails>().AddSpecificProc(
- *symbol, name.source);
+ if (auto *details{genericSymbol.detailsIf<GenericDetails>()}) {
+ details->AddSpecificProc(*symbol, name.source);
} else {
CHECK(context().HasError(genericSymbol));
}
procedure = NoteInterfaceName(procedureName);
}
if (procedure) {
- if (auto *s{
- MakeTypeSymbol(bindingName, ProcBindingDetails{*procedure})}) {
+ const Symbol &bindTo{BypassGeneric(*procedure)};
+ if (auto *s{MakeTypeSymbol(bindingName, ProcBindingDetails{bindTo})}) {
SetPassNameOn(*s);
if (GetAttrs().test(Attr::DEFERRED)) {
context().SetError(*s);
auto &bindingName{std::get<parser::Name>(declaration.t)};
if (Symbol * binding{FindInScope(bindingName)}) {
if (auto *details{binding->detailsIf<ProcBindingDetails>()}) {
- const Symbol *procedure{FindSubprogram(details->symbol())};
+ const Symbol &ultimate{details->symbol().GetUltimate()};
+ const Symbol &procedure{BypassGeneric(ultimate)};
+ if (&procedure != &ultimate) {
+ details->ReplaceSymbol(procedure);
+ }
if (!CanBeTypeBoundProc(procedure)) {
if (details->symbol().name() != binding->name()) {
Say(binding->name(),
}
// Check this symbol suitable as a type-bound procedure - C769
-bool CanBeTypeBoundProc(const Symbol *symbol) {
- if (!symbol || IsDummy(*symbol) || IsProcedurePointer(*symbol)) {
+bool CanBeTypeBoundProc(const Symbol &symbol) {
+ if (IsDummy(symbol) || IsProcedurePointer(symbol)) {
return false;
- } else if (symbol->has<SubprogramNameDetails>()) {
- return symbol->owner().kind() == Scope::Kind::Module;
- } else if (auto *details{symbol->detailsIf<SubprogramDetails>()}) {
- return symbol->owner().kind() == Scope::Kind::Module ||
- details->isInterface();
- } else if (const auto *proc{symbol->detailsIf<ProcEntityDetails>()}) {
- return !symbol->attrs().test(Attr::INTRINSIC) &&
+ } else if (symbol.has<SubprogramNameDetails>()) {
+ return symbol.owner().kind() == Scope::Kind::Module;
+ } else if (auto *details{symbol.detailsIf<SubprogramDetails>()}) {
+ if (details->isInterface()) {
+ return !symbol.attrs().test(Attr::ABSTRACT);
+ } else {
+ return symbol.owner().kind() == Scope::Kind::Module;
+ }
+ } else if (const auto *proc{symbol.detailsIf<ProcEntityDetails>()}) {
+ return !symbol.attrs().test(Attr::INTRINSIC) &&
proc->HasExplicitInterface();
} else {
return false;
subroutine foo
end subroutine
end interface
+ abstract interface
+ subroutine absfoo
+ end subroutine
+ end interface
integer :: i
type t1
integer :: c
!ERROR: 's3' must be either an accessible module procedure or an external procedure with an explicit interface
procedure, nopass :: s3
procedure, nopass :: foo
+ !ERROR: 'absfoo' must be either an accessible module procedure or an external procedure with an explicit interface
+ procedure, nopass :: absfoo
!ERROR: 'bar' must be either an accessible module procedure or an external procedure with an explicit interface
procedure, nopass :: bar
!ERROR: 'i' must be either an accessible module procedure or an external procedure with an explicit interface