diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md index fb57744c21570..340939baca99f 100644 --- a/flang/docs/Extensions.md +++ b/flang/docs/Extensions.md @@ -507,10 +507,7 @@ end f18 supports them with a portability warning. * f18 does not enforce a blanket prohibition against generic interfaces containing a mixture of functions and subroutines. - Apart from some contexts in which the standard requires all of - a particular generic interface to have only all functions or - all subroutines as its specific procedures, we allow both to - appear, unlike several other Fortran compilers. + We allow both to appear, unlike several other Fortran compilers. This is especially desirable when two generics of the same name are combined due to USE association and the mixture may be inadvertent. diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 2e86e0afc9bd0..b764678357db3 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -3639,36 +3639,36 @@ void InterfaceVisitor::CheckGenericProcedures(Symbol &generic) { } return; } - const Symbol &firstSpecific{specifics.front()}; - bool isFunction{firstSpecific.test(Symbol::Flag::Function)}; - bool isBoth{false}; + const Symbol *function{nullptr}; + const Symbol *subroutine{nullptr}; for (const Symbol &specific : specifics) { - if (isFunction != specific.test(Symbol::Flag::Function)) { // C1514 - if (context().ShouldWarn( + if (!function && specific.test(Symbol::Flag::Function)) { + function = &specific; + } else if (!subroutine && specific.test(Symbol::Flag::Subroutine)) { + subroutine = &specific; + if (details.derivedType() && + context().ShouldWarn( common::LanguageFeature::SubroutineAndFunctionSpecifics)) { + SayDerivedType(generic.name(), + "Generic interface '%s' should only contain functions due to derived type with same name"_warn_en_US, + *details.derivedType()->GetUltimate().scope()); + } + } + if (function && subroutine) { + if (context().ShouldWarn(common::LanguageFeature:: + SubroutineAndFunctionSpecifics)) { // C1514 auto &msg{Say(generic.name(), "Generic interface '%s' has both a function and a subroutine"_warn_en_US)}; - if (isFunction) { - msg.Attach(firstSpecific.name(), "Function declaration"_en_US); - msg.Attach(specific.name(), "Subroutine declaration"_en_US); - } else { - msg.Attach(firstSpecific.name(), "Subroutine declaration"_en_US); - msg.Attach(specific.name(), "Function declaration"_en_US); - } + msg.Attach(function->name(), "Function declaration"_en_US); + msg.Attach(subroutine->name(), "Subroutine declaration"_en_US); } - isFunction = false; - isBoth = true; break; } } - if (!isFunction && details.derivedType()) { - SayDerivedType(generic.name(), - "Generic interface '%s' may only contain functions due to derived type" - " with same name"_err_en_US, - *details.derivedType()->GetUltimate().scope()); - } - if (!isBoth) { - generic.set(isFunction ? Symbol::Flag::Function : Symbol::Flag::Subroutine); + if (function && !subroutine) { + generic.set(Symbol::Flag::Function); + } else if (subroutine && !function) { + generic.set(Symbol::Flag::Subroutine); } } diff --git a/flang/test/Semantics/resolve24.f90 b/flang/test/Semantics/resolve24.f90 index 4af6f202cf4f1..72d6719665bb5 100644 --- a/flang/test/Semantics/resolve24.f90 +++ b/flang/test/Semantics/resolve24.f90 @@ -1,6 +1,6 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 subroutine test1 - !ERROR: Generic interface 'foo' has both a function and a subroutine + !WARNING: Generic interface 'foo' has both a function and a subroutine interface foo subroutine s1(x) end subroutine @@ -12,7 +12,7 @@ function f() end subroutine subroutine test2 - !ERROR: Generic interface 'foo' has both a function and a subroutine + !WARNING: Generic interface 'foo' has both a function and a subroutine interface foo function t2f1(x) end function @@ -24,7 +24,7 @@ function t2f2(x, y) end subroutine module test3 - !ERROR: Generic interface 'foo' has both a function and a subroutine + !WARNING: Generic interface 'foo' has both a function and a subroutine interface foo module procedure s module procedure f @@ -39,7 +39,7 @@ function f() subroutine test4 type foo end type - !ERROR: Generic interface 'foo' may only contain functions due to derived type with same name + !WARNING: Generic interface 'foo' should only contain functions due to derived type with same name interface foo subroutine s() end subroutine