diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 4720932780472..077bee930675e 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -646,12 +646,18 @@ class ScopeHandler : public ImplicitRulesVisitor { } if (symbol->CanReplaceDetails(details)) { // update the existing symbol - CheckDuplicatedAttrs(name, *symbol, attrs); - SetExplicitAttrs(*symbol, attrs); if constexpr (std::is_same_v) { // Dummy argument defined by explicit interface? details.set_isDummy(IsDummy(*symbol)); + if (symbol->has()) { + // Bare "EXTERNAL" dummy replaced with explicit INTERFACE + context().Warn(common::LanguageFeature::RedundantAttribute, name, + "Dummy argument '%s' was declared earlier as EXTERNAL"_warn_en_US, + name); + } } + CheckDuplicatedAttrs(name, *symbol, attrs); + SetExplicitAttrs(*symbol, attrs); symbol->set_details(std::move(details)); return *symbol; } else if constexpr (std::is_same_v) { diff --git a/flang/lib/Semantics/symbol.cpp b/flang/lib/Semantics/symbol.cpp index a6b402c48d4ff..ea7eeac80a2d9 100644 --- a/flang/lib/Semantics/symbol.cpp +++ b/flang/lib/Semantics/symbol.cpp @@ -330,8 +330,14 @@ bool Symbol::CanReplaceDetails(const Details &details) const { common::visitors{ [](const UseErrorDetails &) { return true; }, [&](const ObjectEntityDetails &) { return has(); }, - [&](const ProcEntityDetails &) { return has(); }, + [&](const ProcEntityDetails &x) { return has(); }, [&](const SubprogramDetails &) { + if (const auto *oldProc{detailsIf()}) { + // Can replace bare "EXTERNAL dummy" with explicit INTERFACE + return oldProc->isDummy() && !oldProc->procInterface() && + attrs().test(Attr::EXTERNAL) && !test(Flag::Function) && + !test(Flag::Subroutine); + } return has() || has(); }, [&](const DerivedTypeDetails &) { @@ -339,14 +345,12 @@ bool Symbol::CanReplaceDetails(const Details &details) const { return derived && derived->isForwardReferenced(); }, [&](const UseDetails &x) { - const auto *use{this->detailsIf()}; + const auto *use{detailsIf()}; return use && use->symbol() == x.symbol(); }, - [&](const HostAssocDetails &) { - return this->has(); - }, + [&](const HostAssocDetails &) { return has(); }, [&](const UserReductionDetails &) { - return this->has(); + return has(); }, [](const auto &) { return false; }, }, diff --git a/flang/test/Semantics/resolve20.f90 b/flang/test/Semantics/resolve20.f90 index 8b8d190206689..f1a1a30cc714e 100644 --- a/flang/test/Semantics/resolve20.f90 +++ b/flang/test/Semantics/resolve20.f90 @@ -89,4 +89,12 @@ subroutine test !ERROR: Abstract procedure interface 'f' may not be referenced x = f() end subroutine + subroutine baz(foo) + external foo + interface + !WARNING: Dummy argument 'foo' was declared earlier as EXTERNAL [-Wredundant-attribute] + subroutine foo(x) + end + end interface + end end module