@@ -3962,40 +3962,43 @@ void ModuleVisitor::DoAddUse(SourceName location, SourceName localName,
3962
3962
}
3963
3963
}
3964
3964
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
+
3965
3983
auto AreSameProcedure{[&](const Symbol &p1, const Symbol &p2) {
3966
- if (&p1 == &p2) {
3984
+ if (&p1. GetUltimate () == &p2. GetUltimate () ) {
3967
3985
return true ;
3968
3986
} else if (p1.name () != p2.name ()) {
3969
3987
return false ;
3970
3988
} else if (p1.attrs ().test (Attr::INTRINSIC) ||
3971
3989
p2.attrs ().test (Attr::INTRINSIC)) {
3972
3990
return p1.attrs ().test (Attr::INTRINSIC) &&
3973
3991
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;
3984
4000
} 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 ;
3999
4002
}
4000
4003
}};
4001
4004
@@ -4096,13 +4099,32 @@ void ModuleVisitor::DoAddUse(SourceName location, SourceName localName,
4096
4099
localSymbol = &newSymbol;
4097
4100
}
4098
4101
if (useGeneric) {
4099
- // Combine two use-associated generics
4102
+ // Combine two use-associated generics.
4100
4103
localSymbol->attrs () =
4101
4104
useSymbol.attrs () & ~Attrs{Attr::PUBLIC, Attr::PRIVATE};
4102
4105
localSymbol->flags () = useSymbol.flags ();
4103
4106
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
+ }
4106
4128
}
4107
4129
localGeneric->clear_derivedType ();
4108
4130
if (combinedDerivedType) {
0 commit comments