const Symbol &last{ref.GetLastSymbol()};
const Symbol &symbol{BypassGeneric(last).GetUltimate()};
if (semantics::IsProcedure(symbol)) {
+ if (symbol.attrs().test(semantics::Attr::ABSTRACT)) {
+ Say("Abstract procedure interface '%s' may not be used as a designator"_err_en_US,
+ last.name());
+ }
if (auto *component{std::get_if<Component>(&ref.u)}) {
return Expr<SomeType>{ProcedureDesignator{std::move(*component)}};
} else if (!std::holds_alternative<SymbolRef>(ref.u)) {
// re-resolve name to the specific procedure
name.symbol = const_cast<Symbol *>(resolution);
}
+ } else if (IsProcedure(ultimate) &&
+ ultimate.attrs().test(semantics::Attr::ABSTRACT)) {
+ Say("Abstract procedure interface '%s' may not be referenced"_err_en_US,
+ name.source);
} else {
resolution = symbol;
}
if (!symbol->has<GenericDetails>()) {
CheckImplicitNoneExternal(name.source, *symbol);
}
- if (symbol->has<SubprogramDetails>() &&
- symbol->attrs().test(Attr::ABSTRACT)) {
- Say(name, "Abstract interface '%s' may not be called"_err_en_US);
- } else if (IsProcedure(*symbol) || symbol->has<DerivedTypeDetails>() ||
+ if (IsProcedure(*symbol) || symbol->has<DerivedTypeDetails>() ||
symbol->has<AssocEntityDetails>()) {
// Symbols with DerivedTypeDetails and AssocEntityDetails are accepted
// here as procedure-designators because this means the related
--- /dev/null
+! RUN: %python %S/test_errors.py %s %flang_fc1
+! Test misuse of abstract interfaces
+program test
+ abstract interface
+ subroutine abstract
+ end subroutine
+ end interface
+ procedure(abstract), pointer :: p
+ !ERROR: Abstract procedure interface 'abstract' may not be referenced
+ call abstract
+ !ERROR: Abstract procedure interface 'abstract' may not be used as a designator
+ p => abstract
+ !ERROR: Abstract procedure interface 'abstract' may not be used as a designator
+ call foo(abstract)
+ !ERROR: Abstract procedure interface 'abstract' may not be used as a designator
+ print *, associated(p, abstract)
+end
abstract interface
subroutine foo
end subroutine
+ subroutine foo2
+ end subroutine
end interface
procedure() :: a
subroutine bar
end subroutine
subroutine test
- !ERROR: Abstract interface 'foo' may not be called
- call foo()
- !ERROR: Abstract interface 'f' may not be called
+ !ERROR: Abstract procedure interface 'foo2' may not be referenced
+ call foo2()
+ !ERROR: Abstract procedure interface 'f' may not be referenced
x = f()
end subroutine
end module