[flang] Clarify edge case of host association and generic interfaces
authorPeter Klausler <pklausler@nvidia.com>
Tue, 4 Oct 2022 19:11:20 +0000 (12:11 -0700)
committerPeter Klausler <pklausler@nvidia.com>
Thu, 6 Oct 2022 20:10:33 +0000 (13:10 -0700)
Name resolution was mishandling cases of generic interfaces and specific procedures
(sometimes complicatd by use of the same name for each) when the specific procedure
was accessed by means of host association; only the scope of the generic interface
definition was searched for the specific procedure.  Also search enclosing scopes
in the usual way.

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

flang/lib/Semantics/resolve-names.cpp
flang/test/Semantics/generic01.f90

index e748e41..5b7a863 100644 (file)
@@ -7233,8 +7233,8 @@ void ResolveNamesVisitor::CreateGeneric(const parser::GenericSpec &x) {
   Symbol *existing{nullptr};
   // Check all variants of names, e.g. "operator(.ne.)" for "operator(/=)"
   for (const std::string &n : GetAllNames(context(), symbolName)) {
-    if (auto iter{currScope().find(n)}; iter != currScope().end()) {
-      existing = &*iter->second;
+    existing = currScope().FindSymbol(SourceName{n});
+    if (existing) {
       break;
     }
   }
@@ -7249,24 +7249,28 @@ void ResolveNamesVisitor::CreateGeneric(const parser::GenericSpec &x) {
           genericDetails.set_specific(*existingGeneric->specific());
         }
         AddGenericUse(genericDetails, existing->name(), existingUse->symbol());
-      } else if (existing == &ultimate) {
-        // Extending an extant generic in the same scope
-        info.Resolve(existing);
-        return;
-      } else {
-        // Host association of a generic is handled in ResolveGeneric()
-        CHECK(existing->has<HostAssocDetails>());
+      } else if (&existing->owner() == &currScope()) {
+        if (existing == &ultimate) {
+          // Extending an extant generic in the same scope
+          info.Resolve(existing);
+          return;
+        } else {
+          // Host association of a generic is handled elsewhere
+          CHECK(existing->has<HostAssocDetails>());
+        }
       }
     } else if (ultimate.has<SubprogramDetails>() ||
         ultimate.has<SubprogramNameDetails>()) {
       genericDetails.set_specific(*existing);
     } else if (ultimate.has<DerivedTypeDetails>()) {
       genericDetails.set_derivedType(*existing);
-    } else {
+    } else if (&existing->owner() == &currScope()) {
       SayAlreadyDeclared(symbolName, *existing);
       return;
     }
-    EraseSymbol(*existing);
+    if (&existing->owner() == &currScope()) {
+      EraseSymbol(*existing);
+    }
   }
   info.Resolve(&MakeSymbol(symbolName, Attrs{}, std::move(genericDetails)));
 }
index 21132f9..0e79a2f 100644 (file)
@@ -61,24 +61,48 @@ contains
   end subroutine
   subroutine test3
     interface abs
-      module procedure abs_int_redef2 ! override module's use of m1
+      module procedure abs_complex_redef ! extend module's use of m1
     end interface
-    !CHECK: abs_int_redef2(
+    !CHECK: abs_int_redef(
     print *, abs(1)
     !CHECK: 1._4
     print *, abs(1.)
-    !CHECK: 1.41421353816986083984375_4
+    !CHECK: abs_complex_redef(
     print *, abs((1,1))
     !CHECK: abs_noargs(
     print *, abs()
     block
-      use m1, only: abs ! override the override
-      !CHECK: abs_int_redef(
-      print *, abs(1)
+      intrinsic abs ! override the extension
+      !CHECK: 1.41421353816986083984375_4
+      print *, abs((1,1))
     end block
   end subroutine
-  integer function abs_int_redef2(j)
-    integer, intent(in) :: j
-    abs_int_redef2 = j
+  real function abs_complex_redef(z)
+    complex, intent(in) :: z
+    abs_complex_redef = z
   end function
+  subroutine test4
+    !CHECK: abs(
+    print *, abs(1)
+   contains
+    integer function abs(n) ! override module's use of m1
+      integer, intent(in) :: n
+      abs = n
+    end function
+  end subroutine
+end module
+
+module m4
+ contains
+  integer function abs(n)
+    integer, intent(in) :: n
+    abs = n
+  end function
+  subroutine test5
+    interface abs
+      module procedure abs ! same name, host-associated
+    end interface
+    !CHECK: abs(
+    print *, abs(1)
+  end subroutine
 end module