diff options
Diffstat (limited to 'flang/lib/Semantics/expression.cpp')
| -rw-r--r-- | flang/lib/Semantics/expression.cpp | 114 |
1 files changed, 74 insertions, 40 deletions
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index 4aeb9a4..32aa6b1 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -2552,11 +2552,12 @@ auto ExpressionAnalyzer::AnalyzeProcedureComponentRef( } return true; }}; - auto pair{ - ResolveGeneric(generic, arguments, adjustment, isSubroutine)}; - sym = pair.first; + auto result{ResolveGeneric( + generic, arguments, adjustment, isSubroutine, SymbolVector{})}; + sym = result.specific; if (!sym) { - EmitGenericResolutionError(generic, pair.second, isSubroutine); + EmitGenericResolutionError(generic, result.failedDueToAmbiguity, + isSubroutine, arguments, result.tried); return std::nullopt; } // re-resolve the name to the specific binding @@ -2886,10 +2887,10 @@ const Symbol *ExpressionAnalyzer::ResolveForward(const Symbol &symbol) { // Resolve a call to a generic procedure with given actual arguments. // adjustActuals is called on procedure bindings to handle pass arg. -std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric( - const Symbol &symbol, const ActualArguments &actuals, - const AdjustActuals &adjustActuals, bool isSubroutine, - bool mightBeStructureConstructor) { +auto ExpressionAnalyzer::ResolveGeneric(const Symbol &symbol, + const ActualArguments &actuals, const AdjustActuals &adjustActuals, + bool isSubroutine, SymbolVector &&tried, bool mightBeStructureConstructor) + -> GenericResolution { const Symbol &ultimate{symbol.GetUltimate()}; // Check for a match with an explicit INTRINSIC const Symbol *explicitIntrinsic{nullptr}; @@ -2948,7 +2949,7 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric( // cannot be unambiguously distinguished // Underspecified external procedure actual arguments can // also lead to ambiguity. - return {nullptr, true /* due to ambiguity */}; + return {nullptr, true /* due to ambiguity */, std::move(tried)}; } } if (!procedure->IsElemental()) { @@ -2959,6 +2960,8 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric( } crtMatchingDistance = ComputeCudaMatchingDistance( context_.languageFeatures(), *procedure, localActuals); + } else { + tried.push_back(*specific); } } } @@ -3038,11 +3041,12 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric( // Check parent derived type if (const auto *parentScope{symbol.owner().GetDerivedTypeParent()}) { if (const Symbol * extended{parentScope->FindComponent(symbol.name())}) { - auto pair{ResolveGeneric( - *extended, actuals, adjustActuals, isSubroutine, false)}; - if (pair.first) { - return pair; + auto result{ResolveGeneric(*extended, actuals, adjustActuals, + isSubroutine, std::move(tried), false)}; + if (result.specific != nullptr) { + return result; } + tried = std::move(result.tried); } } // Structure constructor? @@ -3054,14 +3058,15 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric( if (!symbol.owner().IsGlobal() && !symbol.owner().IsDerivedType()) { if (const Symbol * outer{symbol.owner().parent().FindSymbol(symbol.name())}) { - auto pair{ResolveGeneric(*outer, actuals, adjustActuals, isSubroutine, - mightBeStructureConstructor)}; - if (pair.first) { - return pair; + auto result{ResolveGeneric(*outer, actuals, adjustActuals, isSubroutine, + std::move(tried), mightBeStructureConstructor)}; + if (result.specific) { + return result; } + tried = std::move(result.tried); } } - return {nullptr, false}; + return {nullptr, false, std::move(tried)}; } const Symbol &ExpressionAnalyzer::AccessSpecific( @@ -3098,16 +3103,39 @@ const Symbol &ExpressionAnalyzer::AccessSpecific( } } -void ExpressionAnalyzer::EmitGenericResolutionError( - const Symbol &symbol, bool dueToAmbiguity, bool isSubroutine) { - Say(dueToAmbiguity - ? "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 - : semantics::IsGenericDefinedOp(symbol) - ? "No specific procedure of generic operator '%s' matches the actual arguments"_err_en_US - : isSubroutine - ? "No specific subroutine of generic '%s' matches the actual arguments"_err_en_US - : "No specific function of generic '%s' matches the actual arguments"_err_en_US, - symbol.name()); +void ExpressionAnalyzer::EmitGenericResolutionError(const Symbol &symbol, + bool dueToAmbiguity, bool isSubroutine, ActualArguments &arguments, + const SymbolVector &tried) { + if (auto *msg{Say(dueToAmbiguity + ? "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 + : semantics::IsGenericDefinedOp(symbol) + ? "No specific procedure of generic operator '%s' matches the actual arguments"_err_en_US + : isSubroutine + ? "No specific subroutine of generic '%s' matches the actual arguments"_err_en_US + : "No specific function of generic '%s' matches the actual arguments"_err_en_US, + symbol.name())}) { + parser::ContextualMessages &messages{GetContextualMessages()}; + semantics::Scope &scope{context_.FindScope(messages.at())}; + for (const Symbol &specific : tried) { + if (auto procChars{characteristics::Procedure::Characterize( + specific, GetFoldingContext())}) { + if (procChars->HasExplicitInterface()) { + if (auto reasons{semantics::CheckExplicitInterface(*procChars, + arguments, context_, &scope, /*intrinsic=*/nullptr, + /*allocActualArgumentConversions=*/false, + /*extentErrors=*/false, + /*ignoreImplicitVsExplicit=*/false)}; + !reasons.empty()) { + reasons.AttachTo( + msg->Attach(specific.name(), + "Specific procedure '%s' does not match the actual arguments because"_en_US, + specific.name()), + parser::Severity::None); + } + } + } + } + } } auto ExpressionAnalyzer::GetCalleeAndArguments( @@ -3146,12 +3174,14 @@ auto ExpressionAnalyzer::GetCalleeAndArguments(const parser::Name &name, bool isGenericInterface{ultimate.has<semantics::GenericDetails>()}; bool isExplicitIntrinsic{ultimate.attrs().test(semantics::Attr::INTRINSIC)}; const Symbol *resolution{nullptr}; + SymbolVector tried; if (isGenericInterface || isExplicitIntrinsic) { ExpressionAnalyzer::AdjustActuals noAdjustment; - auto pair{ResolveGeneric(*symbol, arguments, noAdjustment, isSubroutine, - mightBeStructureConstructor)}; - resolution = pair.first; - dueToAmbiguity = pair.second; + auto result{ResolveGeneric(*symbol, arguments, noAdjustment, isSubroutine, + SymbolVector{}, mightBeStructureConstructor)}; + resolution = result.specific; + dueToAmbiguity = result.failedDueToAmbiguity; + tried = std::move(result.tried); if (resolution) { if (context_.GetPPCBuiltinsScope() && resolution->name().ToString().rfind("__ppc_", 0) == 0) { @@ -3182,7 +3212,8 @@ auto ExpressionAnalyzer::GetCalleeAndArguments(const parser::Name &name, std::move(specificCall->arguments)}; } else { if (isGenericInterface) { - EmitGenericResolutionError(*symbol, dueToAmbiguity, isSubroutine); + EmitGenericResolutionError( + *symbol, dueToAmbiguity, isSubroutine, arguments, tried); } return std::nullopt; } @@ -4955,8 +4986,10 @@ std::optional<ProcedureRef> ArgumentAnalyzer::GetDefinedAssignmentProc( auto restorer{context_.GetContextualMessages().DiscardMessages()}; if (const Symbol *symbol{scope.FindSymbol(oprName)}) { ExpressionAnalyzer::AdjustActuals noAdjustment; - proc = - context_.ResolveGeneric(*symbol, actuals_, noAdjustment, true).first; + proc = context_ + .ResolveGeneric( + *symbol, actuals_, noAdjustment, true, SymbolVector{}) + .specific; if (proc) { isProcElemental = IsElementalProcedure(*proc); } @@ -5105,17 +5138,18 @@ const Symbol *ArgumentAnalyzer::FindBoundOp(parser::CharBlock oprName, [&](const Symbol &proc, ActualArguments &) { return passIndex == GetPassIndex(proc).value_or(-1); }}; - auto pair{ - context_.ResolveGeneric(*generic, actuals_, adjustment, isSubroutine)}; - if (const Symbol *binding{pair.first}) { + auto result{context_.ResolveGeneric( + *generic, actuals_, adjustment, isSubroutine, SymbolVector{})}; + if (const Symbol *binding{result.specific}) { CHECK(binding->has<semantics::ProcBindingDetails>()); // Use the most recent override of the binding, if any return scope->FindComponent(binding->name()); } else { if (isAmbiguous) { - *isAmbiguous = pair.second; + *isAmbiguous = result.failedDueToAmbiguity; } - context_.EmitGenericResolutionError(*generic, pair.second, isSubroutine); + context_.EmitGenericResolutionError(*generic, result.failedDueToAmbiguity, + isSubroutine, actuals_, result.tried); } } return nullptr; |
