Skip to content

Commit e062b9c

Browse files
authored
[flang] Downgrade error to warning for consistency (#157191)
When a procedure name is declared EXTERNAL and then followed up with an explicit INTERFACE, the compiler emits an error when the procedure is a dummy procedure but only a warning otherwise. Since the EXTERNAL statement is harmless in both cases, accept the case of a dummy procedure as well for consistency. Fixes #157162.
1 parent de5f9fa commit e062b9c

File tree

3 files changed

+26
-8
lines changed

3 files changed

+26
-8
lines changed

flang/lib/Semantics/resolve-names.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -646,12 +646,18 @@ class ScopeHandler : public ImplicitRulesVisitor {
646646
}
647647
if (symbol->CanReplaceDetails(details)) {
648648
// update the existing symbol
649-
CheckDuplicatedAttrs(name, *symbol, attrs);
650-
SetExplicitAttrs(*symbol, attrs);
651649
if constexpr (std::is_same_v<SubprogramDetails, D>) {
652650
// Dummy argument defined by explicit interface?
653651
details.set_isDummy(IsDummy(*symbol));
652+
if (symbol->has<ProcEntityDetails>()) {
653+
// Bare "EXTERNAL" dummy replaced with explicit INTERFACE
654+
context().Warn(common::LanguageFeature::RedundantAttribute, name,
655+
"Dummy argument '%s' was declared earlier as EXTERNAL"_warn_en_US,
656+
name);
657+
}
654658
}
659+
CheckDuplicatedAttrs(name, *symbol, attrs);
660+
SetExplicitAttrs(*symbol, attrs);
655661
symbol->set_details(std::move(details));
656662
return *symbol;
657663
} else if constexpr (std::is_same_v<UnknownDetails, D>) {

flang/lib/Semantics/symbol.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -330,23 +330,27 @@ bool Symbol::CanReplaceDetails(const Details &details) const {
330330
common::visitors{
331331
[](const UseErrorDetails &) { return true; },
332332
[&](const ObjectEntityDetails &) { return has<EntityDetails>(); },
333-
[&](const ProcEntityDetails &) { return has<EntityDetails>(); },
333+
[&](const ProcEntityDetails &x) { return has<EntityDetails>(); },
334334
[&](const SubprogramDetails &) {
335+
if (const auto *oldProc{detailsIf<ProcEntityDetails>()}) {
336+
// Can replace bare "EXTERNAL dummy" with explicit INTERFACE
337+
return oldProc->isDummy() && !oldProc->procInterface() &&
338+
attrs().test(Attr::EXTERNAL) && !test(Flag::Function) &&
339+
!test(Flag::Subroutine);
340+
}
335341
return has<SubprogramNameDetails>() || has<EntityDetails>();
336342
},
337343
[&](const DerivedTypeDetails &) {
338344
const auto *derived{this->detailsIf<DerivedTypeDetails>()};
339345
return derived && derived->isForwardReferenced();
340346
},
341347
[&](const UseDetails &x) {
342-
const auto *use{this->detailsIf<UseDetails>()};
348+
const auto *use{detailsIf<UseDetails>()};
343349
return use && use->symbol() == x.symbol();
344350
},
345-
[&](const HostAssocDetails &) {
346-
return this->has<HostAssocDetails>();
347-
},
351+
[&](const HostAssocDetails &) { return has<HostAssocDetails>(); },
348352
[&](const UserReductionDetails &) {
349-
return this->has<UserReductionDetails>();
353+
return has<UserReductionDetails>();
350354
},
351355
[](const auto &) { return false; },
352356
},

flang/test/Semantics/resolve20.f90

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,12 @@ subroutine test
8989
!ERROR: Abstract procedure interface 'f' may not be referenced
9090
x = f()
9191
end subroutine
92+
subroutine baz(foo)
93+
external foo
94+
interface
95+
!WARNING: Dummy argument 'foo' was declared earlier as EXTERNAL [-Wredundant-attribute]
96+
subroutine foo(x)
97+
end
98+
end interface
99+
end
92100
end module

0 commit comments

Comments
 (0)