[flang-commits] [flang] e9088e3 - [flang] When resolving a binding, allow for overriding

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Thu Dec 15 15:09:01 PST 2022


Author: Peter Klausler
Date: 2022-12-15T15:08:48-08:00
New Revision: e9088e3789bb695217e5a6b57bc4d4ca0510bf7b

URL: https://github.com/llvm/llvm-project/commit/e9088e3789bb695217e5a6b57bc4d4ca0510bf7b
DIFF: https://github.com/llvm/llvm-project/commit/e9088e3789bb695217e5a6b57bc4d4ca0510bf7b.diff

LOG: [flang] When resolving a binding, allow for overriding

In type-bound generic resolution, when the actual argument
is monomorphic, resolve the call to the target of the
most recent (i.e., least deeply inherited) override of
the binding, if any.

Differential Revision: https://reviews.llvm.org/D140127

Added: 
    

Modified: 
    flang/lib/Semantics/expression.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index f4a3eb653feef..daf763c440d2f 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -2071,6 +2071,7 @@ auto ExpressionAnalyzer::AnalyzeProcedureComponentRef(
       }
       if (auto *dtExpr{UnwrapExpr<Expr<SomeDerived>>(*base)}) {
         if (sym->has<semantics::GenericDetails>()) {
+          auto dyType{dtExpr->GetType()};
           AdjustActuals adjustment{
               [&](const Symbol &proc, ActualArguments &actuals) {
                 if (!proc.attrs().test(semantics::Attr::NOPASS)) {
@@ -2082,6 +2083,15 @@ auto ExpressionAnalyzer::AnalyzeProcedureComponentRef(
           sym = pair.first;
           if (sym) {
             // re-resolve the name to the specific binding
+            CHECK(sym->has<semantics::ProcBindingDetails>());
+            // 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<Symbol *>(sym);
           } else {
             EmitGenericResolutionError(
@@ -3834,14 +3844,14 @@ std::optional<ProcedureRef> ArgumentAnalyzer::GetDefinedAssignmentProc() {
         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 @@ bool ArgumentAnalyzer::AreConformable() const {
 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<semantics::ProcBindingDetails>());
+      // 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


        


More information about the flang-commits mailing list