Skip to content

Commit cbef629

Browse files
authored
[flang] Catch type-bound generic with inherited indistinguishable spe… (#128980)
…cific When checking generic procedures for indistinguishable specific procedures, don't neglect to include specific procedures from any accessible instance of the generic procedure inherited from its parent type.. Fixes #128760.
1 parent c6dd9f4 commit cbef629

File tree

3 files changed

+53
-15
lines changed

3 files changed

+53
-15
lines changed

flang/lib/Semantics/check-declarations.cpp

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ using characteristics::DummyProcedure;
3333
using characteristics::FunctionResult;
3434
using characteristics::Procedure;
3535

36+
class DistinguishabilityHelper;
37+
3638
class CheckHelper {
3739
public:
3840
explicit CheckHelper(SemanticsContext &c) : context_{c} {}
@@ -89,6 +91,8 @@ class CheckHelper {
8991
const SourceName &, const Symbol &, const Procedure &, std::size_t);
9092
bool CheckDefinedAssignment(const Symbol &, const Procedure &);
9193
bool CheckDefinedAssignmentArg(const Symbol &, const DummyArgument &, int);
94+
void CollectSpecifics(
95+
DistinguishabilityHelper &, const Symbol &, const GenericDetails &);
9296
void CheckSpecifics(const Symbol &, const GenericDetails &);
9397
void CheckEquivalenceSet(const EquivalenceSet &);
9498
void CheckEquivalenceObject(const EquivalenceObject &);
@@ -1931,10 +1935,9 @@ void CheckHelper::CheckGeneric(
19311935
}
19321936

19331937
// Check that the specifics of this generic are distinguishable from each other
1934-
void CheckHelper::CheckSpecifics(
1938+
void CheckHelper::CollectSpecifics(DistinguishabilityHelper &helper,
19351939
const Symbol &generic, const GenericDetails &details) {
19361940
GenericKind kind{details.kind()};
1937-
DistinguishabilityHelper helper{context_};
19381941
for (const Symbol &specific : details.specificProcs()) {
19391942
if (specific.attrs().test(Attr::ABSTRACT)) {
19401943
if (auto *msg{messages_.Say(generic.name(),
@@ -1989,6 +1992,23 @@ void CheckHelper::CheckSpecifics(
19891992
}
19901993
}
19911994
}
1995+
if (const Scope * parent{generic.owner().GetDerivedTypeParent()}) {
1996+
if (const Symbol * inherited{parent->FindComponent(generic.name())}) {
1997+
if (IsAccessible(*inherited, generic.owner().parent())) {
1998+
if (const auto *details{inherited->detailsIf<GenericDetails>()}) {
1999+
// Include specifics of inherited generic of the same name, too
2000+
CollectSpecifics(helper, *inherited, *details);
2001+
}
2002+
}
2003+
}
2004+
}
2005+
}
2006+
2007+
void CheckHelper::CheckSpecifics(
2008+
const Symbol &generic, const GenericDetails &details) {
2009+
GenericKind kind{details.kind()};
2010+
DistinguishabilityHelper helper{context_};
2011+
CollectSpecifics(helper, generic, details);
19922012
helper.Check(generic.owner());
19932013
}
19942014

@@ -3947,10 +3967,11 @@ evaluate::Shape SubprogramMatchHelper::FoldShape(const evaluate::Shape &shape) {
39473967
}
39483968

39493969
void DistinguishabilityHelper::Add(const Symbol &generic, GenericKind kind,
3950-
const Symbol &ultimateSpecific, const Procedure &procedure) {
3951-
if (!context_.HasError(ultimateSpecific)) {
3970+
const Symbol &specific, const Procedure &procedure) {
3971+
const Symbol &ultimate{specific.GetUltimate()};
3972+
if (!context_.HasError(ultimate)) {
39523973
nameToSpecifics_[generic.name()].emplace(
3953-
&ultimateSpecific, ProcedureInfo{kind, procedure});
3974+
&ultimate, ProcedureInfo{kind, procedure});
39543975
}
39553976
}
39563977

@@ -3965,6 +3986,18 @@ void DistinguishabilityHelper::Check(const Scope &scope) {
39653986
const auto &[ultimate, procInfo]{*iter1};
39663987
const auto &[kind, proc]{procInfo};
39673988
for (auto iter2{iter1}; ++iter2 != info.end();) {
3989+
if (&*ultimate == &*iter2->first) {
3990+
continue; // ok, actually the same procedure
3991+
} else if (const auto *binding1{
3992+
ultimate->detailsIf<ProcBindingDetails>()}) {
3993+
if (const auto *binding2{
3994+
iter2->first->detailsIf<ProcBindingDetails>()}) {
3995+
if (&binding1->symbol().GetUltimate() ==
3996+
&binding2->symbol().GetUltimate()) {
3997+
continue; // ok, bindings resolve identically
3998+
}
3999+
}
4000+
}
39684001
auto distinguishable{kind.IsName()
39694002
? evaluate::characteristics::Distinguishable
39704003
: evaluate::characteristics::DistinguishableOpOrAssign};

flang/test/Semantics/generic07.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ program test
7474
interface distinguishable3
7575
procedure :: s1a, s1b
7676
end interface
77-
!ERROR: Generic 'indistinguishable' may not have specific procedures 's2b' and 's2a' as their interfaces are not distinguishable
77+
!ERROR: Generic 'indistinguishable' may not have specific procedures 's2a' and 's2b' as their interfaces are not distinguishable
7878
interface indistinguishable
7979
procedure :: s2a, s2b
8080
end interface

flang/test/Semantics/resolve117.f90

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,28 @@ module m
55
integer, kind :: k = 4
66
real x
77
contains
8-
procedure, nopass :: tbp => sub
9-
generic :: gen => tbp
8+
procedure, nopass :: tbp => sub1
9+
generic :: gen1 => tbp
10+
generic :: gen2 => tbp
1011
end type
1112
type, extends(base1) :: ext1
1213
contains
13-
procedure, nopass :: sub
14+
procedure, nopass :: sub1, sub2
1415
!ERROR: Type parameter, component, or procedure binding 'base1' already defined in this type
15-
generic :: base1 => sub
16+
generic :: base1 => sub1
1617
!ERROR: Type bound generic procedure 'k' may not have the same name as a non-generic symbol inherited from an ancestor type
17-
generic :: k => sub
18+
generic :: k => sub1
1819
!ERROR: Type bound generic procedure 'x' may not have the same name as a non-generic symbol inherited from an ancestor type
19-
generic :: x => sub
20+
generic :: x => sub1
2021
!ERROR: Type bound generic procedure 'tbp' may not have the same name as a non-generic symbol inherited from an ancestor type
21-
generic :: tbp => sub
22-
generic :: gen => sub ! ok
22+
generic :: tbp => sub1
23+
generic :: gen1 => sub1 ! ok
24+
!ERROR: Generic 'gen2' may not have specific procedures 'tbp' and 'sub2' as their interfaces are not distinguishable
25+
generic :: gen2 => sub2
2326
end type
2427
contains
25-
subroutine sub
28+
subroutine sub1
29+
end
30+
subroutine sub2
2631
end
2732
end

0 commit comments

Comments
 (0)