[flang] Better handling of merged generics
authorTim Keith <tkeith@nvidia.com>
Fri, 13 Sep 2019 21:27:33 +0000 (14:27 -0700)
committerTim Keith <tkeith@nvidia.com>
Fri, 13 Sep 2019 21:27:33 +0000 (14:27 -0700)
If a generic name is use-associated from two different modules and they
both have a specific procedure or both have a derived type with the same
name, report it as an error.

Original-commit: flang-compiler/f18@42369af96d3cca7ca2050592e728e04de8124bd8
Reviewed-on: https://github.com/flang-compiler/f18/pull/741
Tree-same-pre-rewrite: false

flang/lib/semantics/resolve-names.cc
flang/test/semantics/resolve17.f90

index 502a421..3a58b5a 100644 (file)
@@ -2023,12 +2023,29 @@ void ModuleVisitor::AddUse(
         useSymbol.has<GenericDetails>()) {
       // use-associating generics with the same names: merge them into a
       // new generic in this scope
-      auto genericDetails{ultimate.get<GenericDetails>()};
-      genericDetails.set_useDetails(*useDetails);
-      genericDetails.CopyFrom(useSymbol.get<GenericDetails>());
+      auto generic1{ultimate.get<GenericDetails>()};
+      generic1.set_useDetails(*useDetails);
+      // useSymbol has specific g and so does generic1
+      auto &generic2{useSymbol.get<GenericDetails>()};
+      if (generic1.specific() && generic2.specific() &&
+          generic1.specific() != generic2.specific()) {
+        Say(location,
+            "Generic interface '%s' has ambiguous specific procedures"
+            " from modules '%s' and '%s'"_err_en_US,
+            localSymbol.name(), useDetails->module().name(),
+            useSymbol.owner().GetName().value());
+      } else if (generic1.derivedType() && generic2.derivedType() &&
+          generic1.derivedType() != generic2.derivedType()) {
+        Say(location,
+            "Generic interface '%s' has ambiguous derived types"
+            " from modules '%s' and '%s'"_err_en_US,
+            localSymbol.name(), useDetails->module().name(),
+            useSymbol.owner().GetName().value());
+      } else {
+        generic1.CopyFrom(generic2);
+      }
       EraseSymbol(localSymbol);
-      MakeSymbol(
-          localSymbol.name(), ultimate.attrs(), std::move(genericDetails));
+      MakeSymbol(localSymbol.name(), ultimate.attrs(), std::move(generic1));
     } else {
       ConvertToUseError(localSymbol, location, *useModuleScope_);
     }
index 567756f..0846a02 100644 (file)
@@ -198,8 +198,23 @@ contains
     real :: x
   end
 end module
+module m9c
+  interface g
+    module procedure g
+  end interface
+contains
+  subroutine g(x)
+    real :: x
+  end
+end module
 ! Merge use-associated generics that have the same symbol (s1)
 subroutine s9
   use m9a
   use m9b
 end
+! Merge use-associate generics each with specific of same name
+subroutine s9c
+  use m9a
+  !ERROR: Generic interface 'g' has ambiguous specific procedures from modules 'm9a' and 'm9c'
+  use m9c
+end