@@ -2834,13 +2834,12 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
2834
2834
// Check for generic or explicit INTRINSIC of the same name in outer scopes.
2835
2835
// See 15.5.5.2 for details.
2836
2836
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;
2844
2843
}
2845
2844
}
2846
2845
}
@@ -3635,13 +3634,13 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Concat &x) {
3635
3634
// The Name represents a user-defined intrinsic operator.
3636
3635
// If the actuals match one of the specific procedures, return a function ref.
3637
3636
// 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 ) {
3640
3639
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 ));
3645
3644
} else {
3646
3645
return std::nullopt;
3647
3646
}
@@ -4453,38 +4452,45 @@ MaybeExpr ArgumentAnalyzer::TryDefinedOp(
4453
4452
parser::Messages buffer;
4454
4453
auto restorer{context_.GetContextualMessages ().SetMessages (buffer)};
4455
4454
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) {
4457
4458
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;
4466
4462
} 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
+ }
4469
4476
}
4470
4477
}
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);
4471
4486
}
4472
4487
for (std::size_t passIndex{0 }; passIndex < actuals_.size (); ++passIndex) {
4473
4488
buffer.clear ();
4474
4489
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);
4488
4494
}
4489
4495
}
4490
4496
}
@@ -4655,7 +4661,8 @@ std::optional<ProcedureRef> ArgumentAnalyzer::GetDefinedAssignmentProc() {
4655
4661
}
4656
4662
for (std::size_t i{0 }; !proc && i < actuals_.size (); ++i) {
4657
4663
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 )}) {
4659
4666
if (CheckAccessibleSymbol (scope, DEREF (generic))) {
4660
4667
// ignore inaccessible type-bound ASSIGNMENT(=) generic
4661
4668
} else if (const Symbol *
0 commit comments