Skip to content

Commit b2ba43a

Browse files
authored
[flang] Refine checking of type-bound generics (#129292)
I merged a patch yesterday (#128980) that strengthened error detection of indistinguishable specific procedures in a type-bound generic procedure, and broke a couple of tests. Refine the check so that it doesn't flag valid cases of overridden bindings, and add a thorough test with all of the boundary cases that I can think of.
1 parent dfc5f37 commit b2ba43a

File tree

2 files changed

+109
-6
lines changed

2 files changed

+109
-6
lines changed

flang/lib/Semantics/check-declarations.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3998,26 +3998,33 @@ void DistinguishabilityHelper::Check(const Scope &scope) {
39983998
const auto &[ultimate, procInfo]{*iter1};
39993999
const auto &[kind, proc]{procInfo};
40004000
for (auto iter2{iter1}; ++iter2 != info.end();) {
4001-
if (&*ultimate == &*iter2->first) {
4002-
continue; // ok, actually the same procedure
4001+
const auto &[ultimate2, procInfo2]{*iter2};
4002+
if (&*ultimate == &*ultimate2) {
4003+
continue; // ok, actually the same procedure/binding
40034004
} else if (const auto *binding1{
40044005
ultimate->detailsIf<ProcBindingDetails>()}) {
40054006
if (const auto *binding2{
4006-
iter2->first->detailsIf<ProcBindingDetails>()}) {
4007+
ultimate2->detailsIf<ProcBindingDetails>()}) {
40074008
if (&binding1->symbol().GetUltimate() ==
40084009
&binding2->symbol().GetUltimate()) {
4009-
continue; // ok, bindings resolve identically
4010+
continue; // ok, (NOPASS) bindings resolve identically
4011+
} else if (ultimate->name() == ultimate2->name()) {
4012+
continue; // override, possibly of DEFERRED
40104013
}
40114014
}
4015+
} else if (ultimate->has<ProcBindingDetails>() &&
4016+
ultimate2->has<ProcBindingDetails>() &&
4017+
ultimate->name() == ultimate2->name()) {
4018+
continue; // override, possibly of DEFERRED
40124019
}
40134020
auto distinguishable{kind.IsName()
40144021
? evaluate::characteristics::Distinguishable
40154022
: evaluate::characteristics::DistinguishableOpOrAssign};
40164023
std::optional<bool> distinct{distinguishable(
4017-
context_.languageFeatures(), proc, iter2->second.procedure)};
4024+
context_.languageFeatures(), proc, procInfo2.procedure)};
40184025
if (!distinct.value_or(false)) {
40194026
SayNotDistinguishable(GetTopLevelUnitContaining(scope), name, kind,
4020-
*ultimate, *iter2->first, distinct.has_value());
4027+
*ultimate, *ultimate2, distinct.has_value());
40214028
}
40224029
}
40234030
}

flang/test/Semantics/generic13.f90

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1
2+
module m1
3+
type, abstract :: ta1
4+
contains
5+
procedure(ta1p1), deferred :: ta1p1
6+
generic :: gen => ta1p1
7+
end type
8+
abstract interface
9+
subroutine ta1p1(x)
10+
import ta1
11+
class(ta1), intent(in) :: x
12+
end
13+
end interface
14+
type :: tb1
15+
contains
16+
procedure tb1p1
17+
generic :: gen => tb1p1
18+
end type
19+
type :: tc1
20+
contains
21+
procedure tc1p1
22+
generic, private :: gen => tc1p1
23+
end type
24+
type :: td1
25+
contains
26+
procedure, nopass :: td1p1
27+
generic :: gen => td1p1
28+
end type
29+
contains
30+
subroutine tb1p1(x)
31+
class(tb1), intent(in) :: x
32+
end
33+
subroutine tb1p2(x)
34+
class(tb1), intent(in) :: x
35+
end
36+
subroutine tc1p1(x)
37+
class(tc1), intent(in) :: x
38+
end
39+
subroutine td1p1
40+
end
41+
end
42+
43+
module m2
44+
use m1
45+
type, extends(ta1) :: ta2a
46+
contains
47+
procedure :: ta1p1 => ta2ap1 ! ok
48+
end type
49+
type, extends(ta1) :: ta2b
50+
contains
51+
procedure :: ta1p1 => ta2bp1
52+
generic :: gen => ta1p1 ! ok, overidden deferred
53+
end type
54+
type, extends(tb1) :: tb2a
55+
contains
56+
generic :: gen => tb1p1 ! ok, same binding
57+
end type
58+
type, extends(tb1) :: tb2b
59+
contains
60+
procedure :: tb1p1 => tb2bp2
61+
generic :: gen => tb1p1 ! ok, overridden
62+
end type
63+
type, extends(tb1) :: tb2c
64+
contains
65+
procedure tb2cp1
66+
!ERROR: Generic 'gen' may not have specific procedures 'tb1p1' and 'tb2cp1' as their interfaces are not distinguishable
67+
generic :: gen => tb2cp1
68+
end type
69+
type, extends(tc1) :: tc2
70+
contains
71+
procedure tc2p1
72+
!ERROR: 'gen' does not have the same accessibility as its previous declaration
73+
generic :: gen => tc2p1
74+
end type
75+
type, extends(td1) :: td2
76+
contains
77+
procedure, nopass :: td2p1 => td1p1
78+
generic :: gen => td2p1 ! ok, same procedure
79+
end type
80+
contains
81+
subroutine ta2ap1(x)
82+
class(ta2a), intent(in) :: x
83+
end
84+
subroutine ta2bp1(x)
85+
class(ta2b), intent(in) :: x
86+
end
87+
subroutine tb2bp2(x)
88+
class(tb2b), intent(in) :: x
89+
end
90+
subroutine tb2cp1(x)
91+
class(tb2c), intent(in) :: x
92+
end
93+
subroutine tc2p1(x)
94+
class(tc2), intent(in) :: x
95+
end
96+
end

0 commit comments

Comments
 (0)