@@ -2834,13 +2834,12 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
28342834 // Check for generic or explicit INTRINSIC of the same name in outer scopes.
28352835 // See 15.5.5.2 for details.
28362836 if (!symbol.owner ().IsGlobal () && !symbol.owner ().IsDerivedType ()) {
2837- for (const std::string &n : GetAllNames (context_, symbol.name ())) {
2838- if (const Symbol *outer{symbol.owner ().parent ().FindSymbol (n)}) {
2839- auto pair{ResolveGeneric (*outer, actuals, adjustActuals, isSubroutine,
2840- mightBeStructureConstructor)};
2841- if (pair.first ) {
2842- return pair;
2843- }
2837+ if (const Symbol *
2838+ outer{symbol.owner ().parent ().FindSymbol (symbol.name ())}) {
2839+ auto pair{ResolveGeneric (*outer, actuals, adjustActuals, isSubroutine,
2840+ mightBeStructureConstructor)};
2841+ if (pair.first ) {
2842+ return pair;
28442843 }
28452844 }
28462845 }
@@ -3635,13 +3634,13 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Concat &x) {
36353634// The Name represents a user-defined intrinsic operator.
36363635// If the actuals match one of the specific procedures, return a function ref.
36373636// Otherwise report the error in messages.
3638- MaybeExpr ExpressionAnalyzer::AnalyzeDefinedOp (
3639- const parser::Name &name, ActualArguments &&actuals ) {
3637+ MaybeExpr ExpressionAnalyzer::AnalyzeDefinedOp (const parser::Name &name,
3638+ ActualArguments &&actuals, const Symbol *&symbol ) {
36403639 if (auto callee{GetCalleeAndArguments (name, std::move (actuals))}) {
3641- CHECK ( std::holds_alternative< ProcedureDesignator>(callee->u )) ;
3642- return MakeFunctionRef (name. source ,
3643- std::move (std::get<ProcedureDesignator>(callee-> u )),
3644- std::move (callee->arguments ));
3640+ auto &proc{ std::get<evaluate:: ProcedureDesignator>(callee->u )} ;
3641+ symbol = proc. GetSymbol ();
3642+ return MakeFunctionRef (
3643+ name. source , std::move (proc), std::move (callee->arguments ));
36453644 } else {
36463645 return std::nullopt ;
36473646 }
@@ -4453,38 +4452,45 @@ MaybeExpr ArgumentAnalyzer::TryDefinedOp(
44534452 parser::Messages buffer;
44544453 auto restorer{context_.GetContextualMessages ().SetMessages (buffer)};
44554454 const auto &scope{context_.context ().FindScope (source_)};
4456- if (Symbol *symbol{scope.FindSymbol (oprName)}) {
4455+
4456+ auto FoundOne{[&](MaybeExpr &&thisResult, const Symbol &generic,
4457+ const Symbol *resolution) {
44574458 anyPossibilities = true ;
4458- parser::Name name{symbol->name (), symbol};
4459- if (!fatalErrors_) {
4460- result = context_.AnalyzeDefinedOp (name, GetActuals ());
4461- }
4462- if (result) {
4463- inaccessible = CheckAccessibleSymbol (scope, *symbol);
4464- if (inaccessible) {
4465- result.reset ();
4459+ if (thisResult) {
4460+ if (auto thisInaccessible{CheckAccessibleSymbol (scope, generic)}) {
4461+ inaccessible = thisInaccessible;
44664462 } else {
4467- hit.push_back (symbol);
4468- hitBuffer = std::move (buffer);
4463+ bool isElemental{IsElementalProcedure (DEREF (resolution))};
4464+ bool hitsAreNonElemental{
4465+ !hit.empty () && !IsElementalProcedure (DEREF (hit[0 ]))};
4466+ if (isElemental && hitsAreNonElemental) {
4467+ // ignore elemental resolutions in favor of a non-elemental one
4468+ } else {
4469+ if (!isElemental && !hitsAreNonElemental) {
4470+ hit.clear ();
4471+ }
4472+ result = std::move (thisResult);
4473+ hit.push_back (resolution);
4474+ hitBuffer = std::move (buffer);
4475+ }
44694476 }
44704477 }
4478+ }};
4479+
4480+ if (Symbol * generic{scope.FindSymbol (oprName)}; generic && !fatalErrors_) {
4481+ parser::Name name{generic->name (), generic};
4482+ const Symbol *resultSymbol{nullptr };
4483+ MaybeExpr possibleResult{context_.AnalyzeDefinedOp (
4484+ name, ActualArguments{actuals_}, resultSymbol)};
4485+ FoundOne (std::move (possibleResult), *generic, resultSymbol);
44714486 }
44724487 for (std::size_t passIndex{0 }; passIndex < actuals_.size (); ++passIndex) {
44734488 buffer.clear ();
44744489 const Symbol *generic{nullptr };
4475- if (const Symbol *binding{
4476- FindBoundOp (oprName, passIndex, generic, false )}) {
4477- anyPossibilities = true ;
4478- if (MaybeExpr thisResult{TryBoundOp (*binding, passIndex)}) {
4479- if (auto thisInaccessible{
4480- CheckAccessibleSymbol (scope, DEREF (generic))}) {
4481- inaccessible = thisInaccessible;
4482- } else {
4483- result = std::move (thisResult);
4484- hit.push_back (binding);
4485- hitBuffer = std::move (buffer);
4486- }
4487- }
4490+ if (const Symbol *
4491+ binding{FindBoundOp (
4492+ oprName, passIndex, generic, /* isSubroutine=*/ false )}) {
4493+ FoundOne (TryBoundOp (*binding, passIndex), DEREF (generic), binding);
44884494 }
44894495 }
44904496 }
@@ -4655,7 +4661,8 @@ std::optional<ProcedureRef> ArgumentAnalyzer::GetDefinedAssignmentProc() {
46554661 }
46564662 for (std::size_t i{0 }; !proc && i < actuals_.size (); ++i) {
46574663 const Symbol *generic{nullptr };
4658- if (const Symbol *binding{FindBoundOp (oprName, i, generic, true )}) {
4664+ if (const Symbol *
4665+ binding{FindBoundOp (oprName, i, generic, /* isSubroutine=*/ true )}) {
46594666 if (CheckAccessibleSymbol (scope, DEREF (generic))) {
46604667 // ignore inaccessible type-bound ASSIGNMENT(=) generic
46614668 } else if (const Symbol *
0 commit comments