diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -2071,6 +2071,7 @@ } if (auto *dtExpr{UnwrapExpr>(*base)}) { if (sym->has()) { + auto dyType{dtExpr->GetType()}; AdjustActuals adjustment{ [&](const Symbol &proc, ActualArguments &actuals) { if (!proc.attrs().test(semantics::Attr::NOPASS)) { @@ -2082,6 +2083,15 @@ sym = pair.first; if (sym) { // re-resolve the name to the specific binding + CHECK(sym->has()); + // Use the most recent override of the binding, if any + CHECK(dyType && dyType->category() == TypeCategory::Derived && + !dyType->IsUnlimitedPolymorphic()); + if (const Symbol *latest{ + DEREF(dyType->GetDerivedTypeSpec().typeSymbol().scope()) + .FindComponent(sym->name())}) { + sym = latest; + } sc.component.symbol = const_cast(sym); } else { EmitGenericResolutionError( @@ -3834,14 +3844,14 @@ context_.EmitGenericResolutionError(*symbol, pair.second, true); } } - for (std::size_t i{0}; i < actuals_.size(); ++i) { + for (std::size_t i{0}; !proc && i < actuals_.size(); ++i) { const Symbol *generic{nullptr}; - if (const Symbol *specific{FindBoundOp(oprName, i, generic, true)}) { + if (const Symbol *binding{FindBoundOp(oprName, i, generic, true)}) { if (const Symbol *resolution{ - GetBindingResolution(GetType(i), *specific)}) { + GetBindingResolution(GetType(i), *binding)}) { proc = resolution; } else { - proc = specific; + proc = binding; passedObjectIndex = i; } } @@ -3924,23 +3934,30 @@ const Symbol *ArgumentAnalyzer::FindBoundOp(parser::CharBlock oprName, int passIndex, const Symbol *&generic, bool isSubroutine) { const auto *type{GetDerivedTypeSpec(GetType(passIndex))}; - if (!type || !type->scope()) { - return nullptr; - } - generic = type->scope()->FindComponent(oprName); - if (!generic) { - return nullptr; - } - ExpressionAnalyzer::AdjustActuals adjustment{ - [&](const Symbol &proc, ActualArguments &) { - return passIndex == GetPassIndex(proc); - }}; - auto pair{ - context_.ResolveGeneric(*generic, actuals_, adjustment, isSubroutine)}; - if (!pair.first) { - context_.EmitGenericResolutionError(*generic, pair.second, isSubroutine); + const semantics::Scope *scope{type ? type->scope() : nullptr}; + if (scope) { + // Use the original type definition's scope, since PDT + // instantiations don't have redundant copies of bindings or + // generics. + scope = DEREF(scope->derivedTypeSpec()).typeSymbol().scope(); + } + generic = scope ? scope->FindComponent(oprName) : nullptr; + if (generic) { + ExpressionAnalyzer::AdjustActuals adjustment{ + [&](const Symbol &proc, ActualArguments &) { + return passIndex == GetPassIndex(proc); + }}; + auto pair{ + context_.ResolveGeneric(*generic, actuals_, adjustment, isSubroutine)}; + if (const Symbol *binding{pair.first}) { + CHECK(binding->has()); + // Use the most recent override of the binding, if any + return scope->FindComponent(binding->name()); + } else { + context_.EmitGenericResolutionError(*generic, pair.second, isSubroutine); + } } - return pair.first; + return nullptr; } // If there is an implicit conversion between intrinsic types, make it explicit