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 @@ -528,6 +528,8 @@ void SayAlreadyDeclared(const parser::Name &, Symbol &); void SayAlreadyDeclared(const SourceName &, Symbol &); void SayAlreadyDeclared(const SourceName &, const SourceName &); + void SayExternalDeclared(const SourceName &, Symbol &); + void SayExternalDeclared(const parser::Name &, Symbol &); void SayWithReason( const parser::Name &, Symbol &, MessageFixedText &&, Message &&); void SayWithDecl(const parser::Name &, Symbol &, MessageFixedText &&); @@ -2153,6 +2155,16 @@ } } +void ScopeHandler::SayExternalDeclared( + const SourceName &name1, Symbol &symbol) { + Say(name1, "EXTERNAL attribute was already specified on '%s'"_warn_en_US); +} + +void ScopeHandler::SayExternalDeclared( + const parser::Name &name1, Symbol &symbol) { + Say(name1, "EXTERNAL attribute was already specified on '%s'"_warn_en_US); +} + void ScopeHandler::SayWithReason(const parser::Name &name, Symbol &symbol, MessageFixedText &&msg1, Message &&msg2) { bool isFatal{msg1.IsFatal()}; @@ -3911,11 +3923,18 @@ // ENTRY's name. We have to replace that symbol in situ to avoid the // obligation to rewrite symbol pointers in the parse tree. if (!symbol.test(subpFlag)) { - Say2(name, - subpFlag == Symbol::Flag::Function - ? "'%s' was previously called as a subroutine"_err_en_US - : "'%s' was previously called as a function"_err_en_US, - symbol, "Previous call of '%s'"_en_US); + // External statments issue an explicit EXTERNAL attribute. + if (symbol.attrs().test(Attr::EXTERNAL) && + !symbol.implicitAttrs().test(Attr::EXTERNAL)) { + // Warn if external statement previously declared. + SayExternalDeclared(name, symbol); + } else { + Say2(name, + subpFlag == Symbol::Flag::Function + ? "'%s' was previously called as a subroutine"_err_en_US + : "'%s' was previously called as a function"_err_en_US, + symbol, "Previous call of '%s'"_en_US); + } } EntityDetails entity; if (proc->type()) { @@ -4333,8 +4352,16 @@ for (const auto &name : x.v) { auto *symbol{FindSymbol(name)}; if (!ConvertToProcEntity(DEREF(symbol))) { - SayWithDecl( - name, *symbol, "EXTERNAL attribute not allowed on '%s'"_err_en_US); + // Check if previous symbol is an interface. + if (auto *details{symbol->detailsIf()}) { + if (details->isInterface()) { + // Warn if interface previously declared. + SayExternalDeclared(name, *symbol); + } + } else { + SayWithDecl( + name, *symbol, "EXTERNAL attribute not allowed on '%s'"_err_en_US); + } } else if (symbol->attrs().test(Attr::INTRINSIC)) { // C840 Say(symbol->name(), "Symbol '%s' cannot have both INTRINSIC and EXTERNAL attributes"_err_en_US, 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 @@ -48,7 +48,7 @@ external :: a, b, c, d !ERROR: EXTERNAL attribute not allowed on 'm' external :: m - !ERROR: EXTERNAL attribute not allowed on 'foo' + !WARNING: EXTERNAL attribute was already specified on 'foo' external :: foo !ERROR: EXTERNAL attribute not allowed on 'bar' external :: bar