Skip to content

[flang] Fix bogus error on aliased derived type #69959

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 31, 2023
Merged

Conversation

klausler
Copy link
Contributor

When a derived type definition is visible by two or more names in the same scope due to USE renaming, any generic ASSIGNMENT(=) or OPERATOR() bindings in the type will produce incorrect error messages about indistinguishable specific procedures. This is due to the use of a std::vector<> to hold a sequence of symbols and some derived information for the specific procedures of the generic name. Change to a std::map<> indexed by the ultimate symbol of each specific so that duplicates cannot arise.

@klausler klausler requested a review from psteinfeld October 23, 2023 18:44
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:semantics labels Oct 23, 2023
@llvmbot
Copy link
Member

llvmbot commented Oct 23, 2023

@llvm/pr-subscribers-flang-semantics

Author: Peter Klausler (klausler)

Changes

When a derived type definition is visible by two or more names in the same scope due to USE renaming, any generic ASSIGNMENT(=) or OPERATOR() bindings in the type will produce incorrect error messages about indistinguishable specific procedures. This is due to the use of a std::vector<> to hold a sequence of symbols and some derived information for the specific procedures of the generic name. Change to a std::map<> indexed by the ultimate symbol of each specific so that duplicates cannot arise.


Full diff: https://github.com/llvm/llvm-project/pull/69959.diff

2 Files Affected:

  • (modified) flang/lib/Semantics/check-declarations.cpp (+13-13)
  • (modified) flang/test/Semantics/generic07.f90 (+23-3)
diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index 2c2866d590ae5a4..45fd9dc28fe560c 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -198,10 +198,10 @@ class DistinguishabilityHelper {
   SemanticsContext &context_;
   struct ProcedureInfo {
     GenericKind kind;
-    const Symbol &symbol;
     const Procedure &procedure;
   };
-  std::map<SourceName, std::vector<ProcedureInfo>> nameToInfo_;
+  std::map<SourceName, std::map<const Symbol *, ProcedureInfo>>
+      nameToSpecifics_;
 };
 
 void CheckHelper::Check(const ParamValue &value, bool canBeAssumed) {
@@ -3441,26 +3441,26 @@ evaluate::Shape SubprogramMatchHelper::FoldShape(const evaluate::Shape &shape) {
 }
 
 void DistinguishabilityHelper::Add(const Symbol &generic, GenericKind kind,
-    const Symbol &specific, const Procedure &procedure) {
-  if (!context_.HasError(specific)) {
-    nameToInfo_[generic.name()].emplace_back(
-        ProcedureInfo{kind, specific, procedure});
+    const Symbol &ultimateSpecific, const Procedure &procedure) {
+  if (!context_.HasError(ultimateSpecific)) {
+    nameToSpecifics_[generic.name()].emplace(
+        &ultimateSpecific, ProcedureInfo{kind, procedure});
   }
 }
 
 void DistinguishabilityHelper::Check(const Scope &scope) {
-  for (const auto &[name, info] : nameToInfo_) {
-    auto count{info.size()};
-    for (std::size_t i1{0}; i1 < count - 1; ++i1) {
-      const auto &[kind, symbol, proc]{info[i1]};
-      for (std::size_t i2{i1 + 1}; i2 < count; ++i2) {
+  for (const auto &[name, info] : nameToSpecifics_) {
+    for (auto iter1{info.begin()}; iter1 != info.end(); ++iter1) {
+      const auto &[ultimate, procInfo]{*iter1};
+      const auto &[kind, proc]{procInfo};
+      for (auto iter2{iter1}; ++iter2 != info.end();) {
         auto distinguishable{kind.IsName()
                 ? evaluate::characteristics::Distinguishable
                 : evaluate::characteristics::DistinguishableOpOrAssign};
         if (!distinguishable(
-                context_.languageFeatures(), proc, info[i2].procedure)) {
+                context_.languageFeatures(), proc, iter2->second.procedure)) {
           SayNotDistinguishable(GetTopLevelUnitContaining(scope), name, kind,
-              symbol, info[i2].symbol);
+              *ultimate, *iter2->first);
         }
       }
     }
diff --git a/flang/test/Semantics/generic07.f90 b/flang/test/Semantics/generic07.f90
index 885697e4b5a9783..e7486c02a7d2ba1 100644
--- a/flang/test/Semantics/generic07.f90
+++ b/flang/test/Semantics/generic07.f90
@@ -1,5 +1,5 @@
 ! RUN: %python %S/test_errors.py %s %flang_fc1
-module m
+module m1
   type :: t1
     sequence
     real :: x
@@ -29,8 +29,28 @@ subroutine s4a(x)
   end
 end
 
+module m2
+  type t10
+    integer n
+   contains
+    procedure :: f
+    generic:: operator(+) => f
+  end type
+ contains
+  elemental type(t10) function f(x,y)
+    class(t10), intent(in) :: x, y
+    f%n = x%n + y%n
+  end
+end
+
+module m3
+  use m2, only: rt10 => t10
+end
+
 program test
-  use m, only: s1a, s2a, s3a, s4a
+  use m1, only: s1a, s2a, s3a, s4a
+  use m2, only: t10
+  use m3, only: rt10 ! alias for t10, ensure no distinguishability error
   type :: t1
     sequence
     integer :: x ! distinct type
@@ -54,7 +74,7 @@ program test
   interface distinguishable3
     procedure :: s1a, s1b
   end interface
-  !ERROR: Generic 'indistinguishable' may not have specific procedures 's2a' and 's2b' as their interfaces are not distinguishable
+  !ERROR: Generic 'indistinguishable' may not have specific procedures 's2b' and 's2a' as their interfaces are not distinguishable
   interface indistinguishable
     procedure :: s2a, s2b
   end interface

Copy link
Contributor

@psteinfeld psteinfeld left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All builds and tests correctly and looks good.

When a derived type definition is visible by two or more names in the same
scope due to USE renaming, any generic ASSIGNMENT(=) or OPERATOR()
bindings in the type will produce incorrect error messages about
indistinguishable specific procedures.  This is due to the use of
a std::vector<> to hold a sequence of symbols and some derived information
for the specific procedures of the generic name.  Change to a std::map<>
indexed by the ultimate symbol of each specific so that duplicates
cannot arise.
@klausler klausler merged commit e87cdda into llvm:main Oct 31, 2023
@klausler klausler deleted the steve2 branch October 31, 2023 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:semantics flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants