@@ -2904,7 +2904,7 @@ void ModuleVisitor::Post(const parser::UseStmt &x) {
2904
2904
}
2905
2905
for (const auto &[name, symbol] : *useModuleScope_) {
2906
2906
if (symbol->attrs ().test (Attr::PUBLIC) && !IsUseRenamed (symbol->name ()) &&
2907
- (!symbol->attrs ().test (Attr::INTRINSIC) ||
2907
+ (!symbol->implicitAttrs ().test (Attr::INTRINSIC) ||
2908
2908
symbol->has <UseDetails>()) &&
2909
2909
!symbol->has <MiscDetails>() && useNames.count (name) == 0 ) {
2910
2910
SourceName location{x.moduleName .source };
@@ -2998,7 +2998,7 @@ void ModuleVisitor::DoAddUse(SourceName location, SourceName localName,
2998
2998
details->add_occurrence (location, *useModuleScope_);
2999
2999
return ;
3000
3000
}
3001
-
3001
+ const Symbol &useUltimate{useSymbol. GetUltimate ()};
3002
3002
if (localSymbol.has <UnknownDetails>()) {
3003
3003
localSymbol.set_details (UseDetails{localName, useSymbol});
3004
3004
localSymbol.attrs () =
@@ -3010,7 +3010,6 @@ void ModuleVisitor::DoAddUse(SourceName location, SourceName localName,
3010
3010
}
3011
3011
3012
3012
Symbol &localUltimate{localSymbol.GetUltimate ()};
3013
- const Symbol &useUltimate{useSymbol.GetUltimate ()};
3014
3013
if (&localUltimate == &useUltimate) {
3015
3014
// use-associating the same symbol again -- ok
3016
3015
return ;
@@ -3044,37 +3043,42 @@ void ModuleVisitor::DoAddUse(SourceName location, SourceName localName,
3044
3043
checkAmbiguousDerivedType (&useUltimate, localGeneric->derivedType ());
3045
3044
} else if (&useUltimate == &BypassGeneric (localUltimate).GetUltimate ()) {
3046
3045
return ; // nothing to do; used subprogram is local's specific
3046
+ } else if (useUltimate.attrs ().test (Attr::INTRINSIC) &&
3047
+ useUltimate.name () == localSymbol.name ()) {
3048
+ return ; // local generic can extend intrinsic
3047
3049
}
3048
3050
} else if (useGeneric) {
3049
3051
if (localUltimate.has <DerivedTypeDetails>()) {
3050
3052
combine =
3051
3053
checkAmbiguousDerivedType (&localUltimate, useGeneric->derivedType ());
3052
- } else if (&localUltimate == &BypassGeneric (useUltimate).GetUltimate ()) {
3053
- // Local is the specific of the used generic; replace it.
3054
+ } else if (&localUltimate == &BypassGeneric (useUltimate).GetUltimate () ||
3055
+ (localSymbol.attrs ().test (Attr::INTRINSIC) &&
3056
+ localUltimate.name () == useUltimate.name ())) {
3057
+ // Local is the specific of the used generic or an intrinsic with the
3058
+ // same name; replace it.
3054
3059
EraseSymbol (localSymbol);
3055
3060
Symbol &newSymbol{MakeSymbol (localName,
3056
3061
useUltimate.attrs () & ~Attrs{Attr::PUBLIC, Attr::PRIVATE},
3057
3062
UseDetails{localName, useUltimate})};
3058
3063
newSymbol.flags () = useSymbol.flags ();
3059
3064
return ;
3060
3065
}
3066
+ } else if (localUltimate.name () != useUltimate.name ()) {
3067
+ // not the same procedure
3068
+ } else if (localUltimate.attrs ().test (Attr::INTRINSIC) &&
3069
+ useUltimate.attrs ().test (Attr::INTRINSIC)) {
3070
+ return ;
3061
3071
} else {
3062
3072
auto localClass{ClassifyProcedure (localUltimate)};
3063
3073
auto useClass{ClassifyProcedure (useUltimate)};
3064
- if (localClass == useClass &&
3065
- (localClass == ProcedureDefinitionClass::Intrinsic ||
3066
- localClass == ProcedureDefinitionClass::External) &&
3067
- localUltimate.name () == useUltimate.name ()) {
3074
+ if (localClass == ProcedureDefinitionClass::External &&
3075
+ useClass == ProcedureDefinitionClass::External) {
3068
3076
auto localChars{evaluate::characteristics::Procedure::Characterize (
3069
3077
localUltimate, GetFoldingContext ())};
3070
3078
auto useChars{evaluate::characteristics::Procedure::Characterize (
3071
3079
useUltimate, GetFoldingContext ())};
3072
- if (localChars && useChars) {
3073
- if (*localChars == *useChars) {
3074
- // Same intrinsic or external procedure defined identically in two
3075
- // modules
3076
- return ;
3077
- }
3080
+ if (localChars && useChars && *localChars == *useChars) {
3081
+ return ; // same procedure defined identically in two modules
3078
3082
}
3079
3083
}
3080
3084
}
@@ -4794,9 +4798,15 @@ Symbol &DeclarationVisitor::HandleAttributeStmt(
4794
4798
}
4795
4799
}
4796
4800
} else if (symbol && symbol->has <UseDetails>()) {
4797
- Say (currStmtSource ().value (),
4798
- " Cannot change %s attribute on use-associated '%s'" _err_en_US,
4799
- EnumToString (attr), name.source );
4801
+ if (symbol->GetUltimate ().attrs ().test (attr)) {
4802
+ Say (currStmtSource ().value (),
4803
+ " Use-associated '%s' already has '%s' attribute" _warn_en_US,
4804
+ name.source , EnumToString (attr));
4805
+ } else {
4806
+ Say (currStmtSource ().value (),
4807
+ " Cannot change %s attribute on use-associated '%s'" _err_en_US,
4808
+ EnumToString (attr), name.source );
4809
+ }
4800
4810
return *symbol;
4801
4811
}
4802
4812
if (!symbol) {
@@ -6244,8 +6254,8 @@ bool DeclarationVisitor::HandleUnrestrictedSpecificIntrinsicFunction(
6244
6254
// recreated for it later on demand, but capturing its result type here
6245
6255
// will make GetType() return a correct result without having to
6246
6256
// probe the intrinsics table again.
6247
- Symbol &symbol{
6248
- MakeSymbol ( InclusiveScope (), name. source , Attrs{ Attr::INTRINSIC})} ;
6257
+ Symbol &symbol{MakeSymbol ( InclusiveScope (), name. source , Attrs{})};
6258
+ SetImplicitAttr (symbol, Attr::INTRINSIC) ;
6249
6259
CHECK (interface->functionResult .has_value ());
6250
6260
evaluate::DynamicType dyType{
6251
6261
DEREF (interface->functionResult ->GetTypeAndShape ()).type ()};
@@ -7708,8 +7718,8 @@ void ResolveNamesVisitor::HandleProcedureName(
7708
7718
auto *symbol{FindSymbol (NonDerivedTypeScope (), name)};
7709
7719
if (!symbol) {
7710
7720
if (IsIntrinsic (name.source , flag)) {
7711
- symbol =
7712
- & MakeSymbol ( InclusiveScope (), name. source , Attrs{ Attr::INTRINSIC} );
7721
+ symbol = & MakeSymbol ( InclusiveScope (), name. source , Attrs{});
7722
+ SetImplicitAttr (*symbol, Attr::INTRINSIC);
7713
7723
} else if (const auto ppcBuiltinScope =
7714
7724
currScope ().context ().GetPPCBuiltinsScope ()) {
7715
7725
// Check if it is a builtin from the predefined module
@@ -8047,6 +8057,11 @@ void ResolveNamesVisitor::CreateGeneric(const parser::GenericSpec &x) {
8047
8057
} else if (ultimate.has <SubprogramDetails>() ||
8048
8058
ultimate.has <SubprogramNameDetails>()) {
8049
8059
genericDetails.set_specific (*existing);
8060
+ } else if (ultimate.has <ProcEntityDetails>()) {
8061
+ if (existing->name () != symbolName ||
8062
+ !ultimate.attrs ().test (Attr::INTRINSIC)) {
8063
+ genericDetails.set_specific (*existing);
8064
+ }
8050
8065
} else if (ultimate.has <DerivedTypeDetails>()) {
8051
8066
genericDetails.set_derivedType (*existing);
8052
8067
} else if (&existing->owner () == &currScope ()) {
0 commit comments