@@ -33,6 +33,8 @@ using characteristics::DummyProcedure;
3333using characteristics::FunctionResult;
3434using characteristics::Procedure;
3535
36+ class DistinguishabilityHelper ;
37+
3638class CheckHelper {
3739public:
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
38863906void 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};
0 commit comments