Skip to content

Commit 5a229db

Browse files
authored
[flang] Relax error into a warning (#107489)
The standard requires that a generic interface with the same name as a derived type contain only functions. We generally allow a generic interface to contain both functions and subroutines, since there's never any ambiguity at the point of call; these is helpful when the specific procedures of two generics are combined during USE association. Emit a warning instead of a hard error when a generic interface with the same name as a derived type contains a subroutine to improve portability of code from compilers that don't check for this condition.
1 parent ce39247 commit 5a229db

File tree

3 files changed

+27
-30
lines changed

3 files changed

+27
-30
lines changed

flang/docs/Extensions.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -507,10 +507,7 @@ end
507507
f18 supports them with a portability warning.
508508
* f18 does not enforce a blanket prohibition against generic
509509
interfaces containing a mixture of functions and subroutines.
510-
Apart from some contexts in which the standard requires all of
511-
a particular generic interface to have only all functions or
512-
all subroutines as its specific procedures, we allow both to
513-
appear, unlike several other Fortran compilers.
510+
We allow both to appear, unlike several other Fortran compilers.
514511
This is especially desirable when two generics of the same
515512
name are combined due to USE association and the mixture may
516513
be inadvertent.

flang/lib/Semantics/resolve-names.cpp

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3639,36 +3639,36 @@ void InterfaceVisitor::CheckGenericProcedures(Symbol &generic) {
36393639
}
36403640
return;
36413641
}
3642-
const Symbol &firstSpecific{specifics.front()};
3643-
bool isFunction{firstSpecific.test(Symbol::Flag::Function)};
3644-
bool isBoth{false};
3642+
const Symbol *function{nullptr};
3643+
const Symbol *subroutine{nullptr};
36453644
for (const Symbol &specific : specifics) {
3646-
if (isFunction != specific.test(Symbol::Flag::Function)) { // C1514
3647-
if (context().ShouldWarn(
3645+
if (!function && specific.test(Symbol::Flag::Function)) {
3646+
function = &specific;
3647+
} else if (!subroutine && specific.test(Symbol::Flag::Subroutine)) {
3648+
subroutine = &specific;
3649+
if (details.derivedType() &&
3650+
context().ShouldWarn(
36483651
common::LanguageFeature::SubroutineAndFunctionSpecifics)) {
3652+
SayDerivedType(generic.name(),
3653+
"Generic interface '%s' should only contain functions due to derived type with same name"_warn_en_US,
3654+
*details.derivedType()->GetUltimate().scope());
3655+
}
3656+
}
3657+
if (function && subroutine) {
3658+
if (context().ShouldWarn(common::LanguageFeature::
3659+
SubroutineAndFunctionSpecifics)) { // C1514
36493660
auto &msg{Say(generic.name(),
36503661
"Generic interface '%s' has both a function and a subroutine"_warn_en_US)};
3651-
if (isFunction) {
3652-
msg.Attach(firstSpecific.name(), "Function declaration"_en_US);
3653-
msg.Attach(specific.name(), "Subroutine declaration"_en_US);
3654-
} else {
3655-
msg.Attach(firstSpecific.name(), "Subroutine declaration"_en_US);
3656-
msg.Attach(specific.name(), "Function declaration"_en_US);
3657-
}
3662+
msg.Attach(function->name(), "Function declaration"_en_US);
3663+
msg.Attach(subroutine->name(), "Subroutine declaration"_en_US);
36583664
}
3659-
isFunction = false;
3660-
isBoth = true;
36613665
break;
36623666
}
36633667
}
3664-
if (!isFunction && details.derivedType()) {
3665-
SayDerivedType(generic.name(),
3666-
"Generic interface '%s' may only contain functions due to derived type"
3667-
" with same name"_err_en_US,
3668-
*details.derivedType()->GetUltimate().scope());
3669-
}
3670-
if (!isBoth) {
3671-
generic.set(isFunction ? Symbol::Flag::Function : Symbol::Flag::Subroutine);
3668+
if (function && !subroutine) {
3669+
generic.set(Symbol::Flag::Function);
3670+
} else if (subroutine && !function) {
3671+
generic.set(Symbol::Flag::Subroutine);
36723672
}
36733673
}
36743674

flang/test/Semantics/resolve24.f90

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
! RUN: %python %S/test_errors.py %s %flang_fc1
22
subroutine test1
3-
!ERROR: Generic interface 'foo' has both a function and a subroutine
3+
!WARNING: Generic interface 'foo' has both a function and a subroutine
44
interface foo
55
subroutine s1(x)
66
end subroutine
@@ -12,7 +12,7 @@ function f()
1212
end subroutine
1313

1414
subroutine test2
15-
!ERROR: Generic interface 'foo' has both a function and a subroutine
15+
!WARNING: Generic interface 'foo' has both a function and a subroutine
1616
interface foo
1717
function t2f1(x)
1818
end function
@@ -24,7 +24,7 @@ function t2f2(x, y)
2424
end subroutine
2525

2626
module test3
27-
!ERROR: Generic interface 'foo' has both a function and a subroutine
27+
!WARNING: Generic interface 'foo' has both a function and a subroutine
2828
interface foo
2929
module procedure s
3030
module procedure f
@@ -39,7 +39,7 @@ function f()
3939
subroutine test4
4040
type foo
4141
end type
42-
!ERROR: Generic interface 'foo' may only contain functions due to derived type with same name
42+
!WARNING: Generic interface 'foo' should only contain functions due to derived type with same name
4343
interface foo
4444
subroutine s()
4545
end subroutine

0 commit comments

Comments
 (0)