[flang] Fix bug in IMPLICIT NONE(EXTERNAL)

We were only checking the restrictions of IMPLICIT NONE(EXTERNAL) when a
procedure name is first encountered. But it can also happen with an
existing symbol, e.g. if an external function's return type is declared
before is it called. This change adds a check in that branch too.

Differential Revision: https://reviews.llvm.org/D93552
This commit is contained in:
Tim Keith 2020-12-18 17:43:51 -08:00
parent 44f399ccc1
commit bf0870d864
2 changed files with 18 additions and 4 deletions

View file

@ -1364,6 +1364,7 @@ private:
void CheckImport(const SourceName &, const SourceName &);
void HandleCall(Symbol::Flag, const parser::Call &);
void HandleProcedureName(Symbol::Flag, const parser::Name &);
bool CheckImplicitNoneExternal(const SourceName &, const Symbol &);
bool SetProcFlag(const parser::Name &, Symbol &, Symbol::Flag);
void ResolveSpecificationParts(ProgramTree &);
void AddSubpNames(ProgramTree &);
@ -5853,10 +5854,7 @@ void ResolveNamesVisitor::HandleProcedureName(
return;
}
if (!symbol->attrs().test(Attr::INTRINSIC)) {
if (isImplicitNoneExternal() && !symbol->attrs().test(Attr::EXTERNAL)) {
Say(name,
"'%s' is an external procedure without the EXTERNAL"
" attribute in a scope with IMPLICIT NONE(EXTERNAL)"_err_en_US);
if (!CheckImplicitNoneExternal(name.source, *symbol)) {
return;
}
MakeExternal(*symbol);
@ -5877,6 +5875,7 @@ void ResolveNamesVisitor::HandleProcedureName(
if (!SetProcFlag(name, *symbol, flag)) {
return; // reported error
}
CheckImplicitNoneExternal(name.source, *symbol);
if (IsProcedure(*symbol) || symbol->has<DerivedTypeDetails>() ||
symbol->has<ObjectEntityDetails>() ||
symbol->has<AssocEntityDetails>()) {
@ -5895,6 +5894,18 @@ void ResolveNamesVisitor::HandleProcedureName(
}
}
bool ResolveNamesVisitor::CheckImplicitNoneExternal(
const SourceName &name, const Symbol &symbol) {
if (isImplicitNoneExternal() && !symbol.attrs().test(Attr::EXTERNAL) &&
!symbol.attrs().test(Attr::INTRINSIC) && !symbol.HasExplicitInterface()) {
Say(name,
"'%s' is an external procedure without the EXTERNAL"
" attribute in a scope with IMPLICIT NONE(EXTERNAL)"_err_en_US);
return false;
}
return true;
}
// Variant of HandleProcedureName() for use while skimming the executable
// part of a subprogram to catch calls to dummy procedures that are part
// of the subprogram's interface, and to mark as procedures any symbols

View file

@ -1,9 +1,12 @@
! RUN: %S/test_errors.sh %s %t %f18
implicit none(external)
external x
integer :: f, i
call x
!ERROR: 'y' is an external procedure without the EXTERNAL attribute in a scope with IMPLICIT NONE(EXTERNAL)
call y
!ERROR: 'f' is an external procedure without the EXTERNAL attribute in a scope with IMPLICIT NONE(EXTERNAL)
i = f()
block
!ERROR: 'z' is an external procedure without the EXTERNAL attribute in a scope with IMPLICIT NONE(EXTERNAL)
call z