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