Skip to content

Commit 9162026

Browse files
committed
[flang] Catch type-bound generic with inherited indistinguishable specific
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 9884803 commit 9162026

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 &);
@@ -1857,10 +1861,9 @@ void CheckHelper::CheckGeneric(
18571861
}
18581862

18591863
// Check that the specifics of this generic are distinguishable from each other
1860-
void CheckHelper::CheckSpecifics(
1864+
void CheckHelper::CollectSpecifics(DistinguishabilityHelper &helper,
18611865
const Symbol &generic, const GenericDetails &details) {
18621866
GenericKind kind{details.kind()};
1863-
DistinguishabilityHelper helper{context_};
18641867
for (const Symbol &specific : details.specificProcs()) {
18651868
if (specific.attrs().test(Attr::ABSTRACT)) {
18661869
if (auto *msg{messages_.Say(generic.name(),
@@ -1915,6 +1918,23 @@ void CheckHelper::CheckSpecifics(
19151918
}
19161919
}
19171920
}
1921+
if (const Scope * parent{generic.owner().GetDerivedTypeParent()}) {
1922+
if (const Symbol * inherited{parent->FindComponent(generic.name())}) {
1923+
if (IsAccessible(*inherited, generic.owner().parent())) {
1924+
if (const auto *details{inherited->detailsIf<GenericDetails>()}) {
1925+
// Include specifics of inherited generic of the same name, too
1926+
CollectSpecifics(helper, *inherited, *details);
1927+
}
1928+
}
1929+
}
1930+
}
1931+
}
1932+
1933+
void CheckHelper::CheckSpecifics(
1934+
const Symbol &generic, const GenericDetails &details) {
1935+
GenericKind kind{details.kind()};
1936+
DistinguishabilityHelper helper{context_};
1937+
CollectSpecifics(helper, generic, details);
19181938
helper.Check(generic.owner());
19191939
}
19201940

@@ -3884,10 +3904,11 @@ evaluate::Shape SubprogramMatchHelper::FoldShape(const evaluate::Shape &shape) {
38843904
}
38853905

38863906
void DistinguishabilityHelper::Add(const Symbol &generic, GenericKind kind,
3887-
const Symbol &ultimateSpecific, const Procedure &procedure) {
3888-
if (!context_.HasError(ultimateSpecific)) {
3907+
const Symbol &specific, const Procedure &procedure) {
3908+
const Symbol &ultimate{specific.GetUltimate()};
3909+
if (!context_.HasError(ultimate)) {
38893910
nameToSpecifics_[generic.name()].emplace(
3890-
&ultimateSpecific, ProcedureInfo{kind, procedure});
3911+
&ultimate, ProcedureInfo{kind, procedure});
38913912
}
38923913
}
38933914

@@ -3902,6 +3923,18 @@ void DistinguishabilityHelper::Check(const Scope &scope) {
39023923
const auto &[ultimate, procInfo]{*iter1};
39033924
const auto &[kind, proc]{procInfo};
39043925
for (auto iter2{iter1}; ++iter2 != info.end();) {
3926+
if (&*ultimate == &*iter2->first) {
3927+
continue; // ok, actually the same procedure
3928+
} else if (const auto *binding1{
3929+
ultimate->detailsIf<ProcBindingDetails>()}) {
3930+
if (const auto *binding2{
3931+
iter2->first->detailsIf<ProcBindingDetails>()}) {
3932+
if (&binding1->symbol().GetUltimate() ==
3933+
&binding2->symbol().GetUltimate()) {
3934+
continue; // ok, bindings resolve identically
3935+
}
3936+
}
3937+
}
39053938
auto distinguishable{kind.IsName()
39063939
? evaluate::characteristics::Distinguishable
39073940
: 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)