@@ -2552,11 +2552,12 @@ auto ExpressionAnalyzer::AnalyzeProcedureComponentRef(
25522552 }
25532553 return true ;
25542554 }};
2555- auto pair{
2556- ResolveGeneric ( generic, arguments, adjustment, isSubroutine)};
2557- sym = pair. first ;
2555+ auto result{ ResolveGeneric (
2556+ generic, arguments, adjustment, isSubroutine, SymbolVector{} )};
2557+ sym = result. specific ;
25582558 if (!sym) {
2559- EmitGenericResolutionError (generic, pair.second , isSubroutine);
2559+ EmitGenericResolutionError (generic, result.failedDueToAmbiguity ,
2560+ isSubroutine, arguments, result.tried );
25602561 return std::nullopt ;
25612562 }
25622563 // re-resolve the name to the specific binding
@@ -2886,10 +2887,10 @@ const Symbol *ExpressionAnalyzer::ResolveForward(const Symbol &symbol) {
28862887
28872888// Resolve a call to a generic procedure with given actual arguments.
28882889// adjustActuals is called on procedure bindings to handle pass arg.
2889- std::pair< const Symbol *, bool > ExpressionAnalyzer::ResolveGeneric (
2890- const Symbol &symbol , const ActualArguments &actuals ,
2891- const AdjustActuals &adjustActuals , bool isSubroutine,
2892- bool mightBeStructureConstructor) {
2890+ auto ExpressionAnalyzer::ResolveGeneric ( const Symbol &symbol,
2891+ const ActualArguments &actuals , const AdjustActuals &adjustActuals ,
2892+ bool isSubroutine, SymbolVector &&tried , bool mightBeStructureConstructor)
2893+ -> GenericResolution {
28932894 const Symbol &ultimate{symbol.GetUltimate ()};
28942895 // Check for a match with an explicit INTRINSIC
28952896 const Symbol *explicitIntrinsic{nullptr };
@@ -2948,7 +2949,7 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
29482949 // cannot be unambiguously distinguished
29492950 // Underspecified external procedure actual arguments can
29502951 // also lead to ambiguity.
2951- return {nullptr , true /* due to ambiguity */ };
2952+ return {nullptr , true /* due to ambiguity */ , std::move (tried) };
29522953 }
29532954 }
29542955 if (!procedure->IsElemental ()) {
@@ -2959,6 +2960,8 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
29592960 }
29602961 crtMatchingDistance = ComputeCudaMatchingDistance (
29612962 context_.languageFeatures (), *procedure, localActuals);
2963+ } else {
2964+ tried.push_back (*specific);
29622965 }
29632966 }
29642967 }
@@ -3038,11 +3041,12 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
30383041 // Check parent derived type
30393042 if (const auto *parentScope{symbol.owner ().GetDerivedTypeParent ()}) {
30403043 if (const Symbol * extended{parentScope->FindComponent (symbol.name ())}) {
3041- auto pair {ResolveGeneric (
3042- *extended, actuals, adjustActuals, isSubroutine , false )};
3043- if (pair. first ) {
3044- return pair ;
3044+ auto result {ResolveGeneric (*extended, actuals, adjustActuals,
3045+ isSubroutine, std::move (tried) , false )};
3046+ if (result. specific != nullptr ) {
3047+ return result ;
30453048 }
3049+ tried = std::move (result.tried );
30463050 }
30473051 }
30483052 // Structure constructor?
@@ -3054,14 +3058,15 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
30543058 if (!symbol.owner ().IsGlobal () && !symbol.owner ().IsDerivedType ()) {
30553059 if (const Symbol *
30563060 outer{symbol.owner ().parent ().FindSymbol (symbol.name ())}) {
3057- auto pair {ResolveGeneric (*outer, actuals, adjustActuals, isSubroutine,
3058- mightBeStructureConstructor)};
3059- if (pair. first ) {
3060- return pair ;
3061+ auto result {ResolveGeneric (*outer, actuals, adjustActuals, isSubroutine,
3062+ std::move (tried), mightBeStructureConstructor)};
3063+ if (result. specific ) {
3064+ return result ;
30613065 }
3066+ tried = std::move (result.tried );
30623067 }
30633068 }
3064- return {nullptr , false };
3069+ return {nullptr , false , std::move (tried) };
30653070}
30663071
30673072const Symbol &ExpressionAnalyzer::AccessSpecific (
@@ -3098,16 +3103,39 @@ const Symbol &ExpressionAnalyzer::AccessSpecific(
30983103 }
30993104}
31003105
3101- void ExpressionAnalyzer::EmitGenericResolutionError (
3102- const Symbol &symbol, bool dueToAmbiguity, bool isSubroutine) {
3103- Say (dueToAmbiguity
3104- ? " The actual arguments to the generic procedure '%s' matched multiple specific procedures, perhaps due to use of NULL() without MOLD= or an actual procedure with an implicit interface" _err_en_US
3105- : semantics::IsGenericDefinedOp (symbol)
3106- ? " No specific procedure of generic operator '%s' matches the actual arguments" _err_en_US
3107- : isSubroutine
3108- ? " No specific subroutine of generic '%s' matches the actual arguments" _err_en_US
3109- : " No specific function of generic '%s' matches the actual arguments" _err_en_US,
3110- symbol.name ());
3106+ void ExpressionAnalyzer::EmitGenericResolutionError (const Symbol &symbol,
3107+ bool dueToAmbiguity, bool isSubroutine, ActualArguments &arguments,
3108+ const SymbolVector &tried) {
3109+ if (auto *msg{Say (dueToAmbiguity
3110+ ? " The actual arguments to the generic procedure '%s' matched multiple specific procedures, perhaps due to use of NULL() without MOLD= or an actual procedure with an implicit interface" _err_en_US
3111+ : semantics::IsGenericDefinedOp (symbol)
3112+ ? " No specific procedure of generic operator '%s' matches the actual arguments" _err_en_US
3113+ : isSubroutine
3114+ ? " No specific subroutine of generic '%s' matches the actual arguments" _err_en_US
3115+ : " No specific function of generic '%s' matches the actual arguments" _err_en_US,
3116+ symbol.name ())}) {
3117+ parser::ContextualMessages &messages{GetContextualMessages ()};
3118+ semantics::Scope &scope{context_.FindScope (messages.at ())};
3119+ for (const Symbol &specific : tried) {
3120+ if (auto procChars{characteristics::Procedure::Characterize (
3121+ specific, GetFoldingContext ())}) {
3122+ if (procChars->HasExplicitInterface ()) {
3123+ if (auto reasons{semantics::CheckExplicitInterface (*procChars,
3124+ arguments, context_, &scope, /* intrinsic=*/ nullptr ,
3125+ /* allocActualArgumentConversions=*/ false ,
3126+ /* extentErrors=*/ false ,
3127+ /* ignoreImplicitVsExplicit=*/ false )};
3128+ !reasons.empty ()) {
3129+ reasons.AttachTo (
3130+ msg->Attach (specific.name (),
3131+ " Specific procedure '%s' does not match the actual arguments because" _en_US,
3132+ specific.name ()),
3133+ parser::Severity::None);
3134+ }
3135+ }
3136+ }
3137+ }
3138+ }
31113139}
31123140
31133141auto ExpressionAnalyzer::GetCalleeAndArguments (
@@ -3146,12 +3174,14 @@ auto ExpressionAnalyzer::GetCalleeAndArguments(const parser::Name &name,
31463174 bool isGenericInterface{ultimate.has <semantics::GenericDetails>()};
31473175 bool isExplicitIntrinsic{ultimate.attrs ().test (semantics::Attr::INTRINSIC)};
31483176 const Symbol *resolution{nullptr };
3177+ SymbolVector tried;
31493178 if (isGenericInterface || isExplicitIntrinsic) {
31503179 ExpressionAnalyzer::AdjustActuals noAdjustment;
3151- auto pair{ResolveGeneric (*symbol, arguments, noAdjustment, isSubroutine,
3152- mightBeStructureConstructor)};
3153- resolution = pair.first ;
3154- dueToAmbiguity = pair.second ;
3180+ auto result{ResolveGeneric (*symbol, arguments, noAdjustment, isSubroutine,
3181+ SymbolVector{}, mightBeStructureConstructor)};
3182+ resolution = result.specific ;
3183+ dueToAmbiguity = result.failedDueToAmbiguity ;
3184+ tried = std::move (result.tried );
31553185 if (resolution) {
31563186 if (context_.GetPPCBuiltinsScope () &&
31573187 resolution->name ().ToString ().rfind (" __ppc_" , 0 ) == 0 ) {
@@ -3182,7 +3212,8 @@ auto ExpressionAnalyzer::GetCalleeAndArguments(const parser::Name &name,
31823212 std::move (specificCall->arguments )};
31833213 } else {
31843214 if (isGenericInterface) {
3185- EmitGenericResolutionError (*symbol, dueToAmbiguity, isSubroutine);
3215+ EmitGenericResolutionError (
3216+ *symbol, dueToAmbiguity, isSubroutine, arguments, tried);
31863217 }
31873218 return std::nullopt ;
31883219 }
@@ -4955,8 +4986,10 @@ std::optional<ProcedureRef> ArgumentAnalyzer::GetDefinedAssignmentProc(
49554986 auto restorer{context_.GetContextualMessages ().DiscardMessages ()};
49564987 if (const Symbol *symbol{scope.FindSymbol (oprName)}) {
49574988 ExpressionAnalyzer::AdjustActuals noAdjustment;
4958- proc =
4959- context_.ResolveGeneric (*symbol, actuals_, noAdjustment, true ).first ;
4989+ proc = context_
4990+ .ResolveGeneric (
4991+ *symbol, actuals_, noAdjustment, true , SymbolVector{})
4992+ .specific ;
49604993 if (proc) {
49614994 isProcElemental = IsElementalProcedure (*proc);
49624995 }
@@ -5105,17 +5138,18 @@ const Symbol *ArgumentAnalyzer::FindBoundOp(parser::CharBlock oprName,
51055138 [&](const Symbol &proc, ActualArguments &) {
51065139 return passIndex == GetPassIndex (proc).value_or (-1 );
51075140 }};
5108- auto pair{
5109- context_. ResolveGeneric ( *generic, actuals_, adjustment, isSubroutine)};
5110- if (const Symbol *binding{pair. first }) {
5141+ auto result{context_. ResolveGeneric (
5142+ *generic, actuals_, adjustment, isSubroutine, SymbolVector{} )};
5143+ if (const Symbol *binding{result. specific }) {
51115144 CHECK (binding->has <semantics::ProcBindingDetails>());
51125145 // Use the most recent override of the binding, if any
51135146 return scope->FindComponent (binding->name ());
51145147 } else {
51155148 if (isAmbiguous) {
5116- *isAmbiguous = pair. second ;
5149+ *isAmbiguous = result. failedDueToAmbiguity ;
51175150 }
5118- context_.EmitGenericResolutionError (*generic, pair.second , isSubroutine);
5151+ context_.EmitGenericResolutionError (*generic, result.failedDueToAmbiguity ,
5152+ isSubroutine, actuals_, result.tried );
51195153 }
51205154 }
51215155 return nullptr ;
0 commit comments