@@ -3963,40 +3963,43 @@ void ModuleVisitor::DoAddUse(SourceName location, SourceName localName,
39633963 }
39643964 }
39653965
3966+ auto AreSameModuleProcOrBothInterfaces{[](const Symbol &p1,
3967+ const Symbol &p2) {
3968+ if (IsProcedure (p1) && !IsPointer (p1) && IsProcedure (p2) &&
3969+ !IsPointer (p2)) {
3970+ auto classification{ClassifyProcedure (p1)};
3971+ if (classification == ClassifyProcedure (p2)) {
3972+ if (classification == ProcedureDefinitionClass::External) {
3973+ const auto *subp1{p1.detailsIf <SubprogramDetails>()};
3974+ const auto *subp2{p2.detailsIf <SubprogramDetails>()};
3975+ return subp1 && subp1->isInterface () && subp2 && subp2->isInterface ();
3976+ } else if (classification == ProcedureDefinitionClass::Module) {
3977+ return AreSameModuleSymbol (p1, p2);
3978+ }
3979+ }
3980+ }
3981+ return false ;
3982+ }};
3983+
39663984 auto AreSameProcedure{[&](const Symbol &p1, const Symbol &p2) {
3967- if (&p1 == &p2) {
3985+ if (&p1. GetUltimate () == &p2. GetUltimate () ) {
39683986 return true ;
39693987 } else if (p1.name () != p2.name ()) {
39703988 return false ;
39713989 } else if (p1.attrs ().test (Attr::INTRINSIC) ||
39723990 p2.attrs ().test (Attr::INTRINSIC)) {
39733991 return p1.attrs ().test (Attr::INTRINSIC) &&
39743992 p2.attrs ().test (Attr::INTRINSIC);
3975- } else if (!IsProcedure (p1) || !IsProcedure (p2)) {
3976- return false ;
3977- } else if (IsPointer (p1) || IsPointer (p2)) {
3978- return false ;
3979- } else if (const auto *subp{p1.detailsIf <SubprogramDetails>()};
3980- subp && !subp->isInterface ()) {
3981- return false ; // defined in module, not an external
3982- } else if (const auto *subp{p2.detailsIf <SubprogramDetails>()};
3983- subp && !subp->isInterface ()) {
3984- return false ; // defined in module, not an external
3993+ } else if (AreSameModuleProcOrBothInterfaces (p1, p2)) {
3994+ // Both are external interfaces, perhaps to the same procedure,
3995+ // or both are module procedures from modules with the same name.
3996+ auto p1Chars{evaluate::characteristics::Procedure::Characterize (
3997+ p1, GetFoldingContext ())};
3998+ auto p2Chars{evaluate::characteristics::Procedure::Characterize (
3999+ p2, GetFoldingContext ())};
4000+ return p1Chars && p2Chars && *p1Chars == *p2Chars;
39854001 } else {
3986- // Both are external interfaces, perhaps to the same procedure
3987- auto class1{ClassifyProcedure (p1)};
3988- auto class2{ClassifyProcedure (p2)};
3989- if (class1 == ProcedureDefinitionClass::External &&
3990- class2 == ProcedureDefinitionClass::External) {
3991- auto chars1{evaluate::characteristics::Procedure::Characterize (
3992- p1, GetFoldingContext ())};
3993- auto chars2{evaluate::characteristics::Procedure::Characterize (
3994- p2, GetFoldingContext ())};
3995- // same procedure interface defined identically in two modules?
3996- return chars1 && chars2 && *chars1 == *chars2;
3997- } else {
3998- return false ;
3999- }
4002+ return false ;
40004003 }
40014004 }};
40024005
@@ -4097,13 +4100,32 @@ void ModuleVisitor::DoAddUse(SourceName location, SourceName localName,
40974100 localSymbol = &newSymbol;
40984101 }
40994102 if (useGeneric) {
4100- // Combine two use-associated generics
4103+ // Combine two use-associated generics.
41014104 localSymbol->attrs () =
41024105 useSymbol.attrs () & ~Attrs{Attr::PUBLIC, Attr::PRIVATE};
41034106 localSymbol->flags () = useSymbol.flags ();
41044107 AddGenericUse (*localGeneric, localName, useUltimate);
4105- localGeneric->clear_derivedType ();
4106- localGeneric->CopyFrom (*useGeneric);
4108+ // Don't duplicate specific procedures.
4109+ std::size_t originalLocalSpecifics{localGeneric->specificProcs ().size ()};
4110+ std::size_t useSpecifics{useGeneric->specificProcs ().size ()};
4111+ CHECK (originalLocalSpecifics == localGeneric->bindingNames ().size ());
4112+ CHECK (useSpecifics == useGeneric->bindingNames ().size ());
4113+ std::size_t j{0 };
4114+ for (const Symbol &useSpecific : useGeneric->specificProcs ()) {
4115+ SourceName useBindingName{useGeneric->bindingNames ()[j++]};
4116+ bool isDuplicate{false };
4117+ std::size_t k{0 };
4118+ for (const Symbol &localSpecific : localGeneric->specificProcs ()) {
4119+ if (localGeneric->bindingNames ()[k++] == useBindingName &&
4120+ AreSameProcedure (localSpecific, useSpecific)) {
4121+ isDuplicate = true ;
4122+ break ;
4123+ }
4124+ }
4125+ if (!isDuplicate) {
4126+ localGeneric->AddSpecificProc (useSpecific, useBindingName);
4127+ }
4128+ }
41074129 }
41084130 localGeneric->clear_derivedType ();
41094131 if (combinedDerivedType) {
0 commit comments