[flang-commits] [flang] ce6dd97 - [flang] Fix analyzed form of type-bound assignment

Tim Keith via flang-commits flang-commits at lists.llvm.org
Mon Sep 14 10:00:08 PDT 2020


Author: Tim Keith
Date: 2020-09-14T09:59:51-07:00
New Revision: ce6dd973ac556a326c38bd7667b4fb448f215d09

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

LOG: [flang] Fix analyzed form of type-bound assignment

Change the analyzed form of type-bound assignment to match that of call
statements. Resolve the binding name to a specific subprogram when
possible by using `GetBindingResolution`. Otherwise leave it as a
type-bound procedure call.

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

Added: 
    flang/test/Semantics/defined-ops.f90

Modified: 
    flang/lib/Semantics/expression.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index ae53559ea5db..fcce08db6ef6 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -1684,7 +1684,6 @@ auto ExpressionAnalyzer::AnalyzeProcedureComponentRef(
     const parser::ProcComponentRef &pcr, ActualArguments &&arguments)
     -> std::optional<CalleeAndArguments> {
   const parser::StructureComponent &sc{pcr.v.thing};
-  const auto &name{sc.component.source};
   if (MaybeExpr base{Analyze(sc.base)}) {
     if (const Symbol * sym{sc.component.symbol}) {
       if (auto *dtExpr{UnwrapExpr<Expr<SomeDerived>>(*base)}) {
@@ -1722,7 +1721,7 @@ auto ExpressionAnalyzer::AnalyzeProcedureComponentRef(
           }
         }
       }
-      Say(name,
+      Say(sc.component.source,
           "Base of procedure component reference is not a derived-type object"_err_en_US);
     }
   }
@@ -2940,18 +2939,26 @@ std::optional<ProcedureRef> ArgumentAnalyzer::GetDefinedAssignmentProc() {
       context_.EmitGenericResolutionError(*symbol);
     }
   }
-  for (std::size_t passIndex{0}; passIndex < actuals_.size(); ++passIndex) {
-    if (const Symbol * specific{FindBoundOp(oprName, passIndex)}) {
-      proc = specific;
+  int passedObjectIndex{-1};
+  for (std::size_t i{0}; i < actuals_.size(); ++i) {
+    if (const Symbol * specific{FindBoundOp(oprName, i)}) {
+      if (const Symbol *
+          resolution{GetBindingResolution(GetType(i), *specific)}) {
+        proc = resolution;
+      } else {
+        proc = specific;
+        passedObjectIndex = i;
+      }
     }
   }
-  if (proc) {
-    ActualArguments actualsCopy{actuals_};
-    actualsCopy[1]->Parenthesize();
-    return ProcedureRef{ProcedureDesignator{*proc}, std::move(actualsCopy)};
-  } else {
+  if (!proc) {
     return std::nullopt;
   }
+  ActualArguments actualsCopy{actuals_};
+  if (passedObjectIndex >= 0) {
+    actualsCopy[passedObjectIndex]->set_isPassedObject();
+  }
+  return ProcedureRef{ProcedureDesignator{*proc}, std::move(actualsCopy)};
 }
 
 void ArgumentAnalyzer::Dump(llvm::raw_ostream &os) {

diff  --git a/flang/test/Semantics/defined-ops.f90 b/flang/test/Semantics/defined-ops.f90
new file mode 100644
index 000000000000..24e72677c6eb
--- /dev/null
+++ b/flang/test/Semantics/defined-ops.f90
@@ -0,0 +1,88 @@
+! RUN: %f18 -funparse %s 2>&1 | FileCheck %s
+
+! Check the analyzed form of a defined operator or assignment.
+
+! Type-bound defined assignment
+module m1
+  type :: t
+  contains
+    procedure :: b1 => s1
+    procedure, pass(y) :: b2 => s2
+    generic :: assignment(=) => b1, b2
+  end type
+contains
+  subroutine s1(x, y)
+    class(t), intent(out) :: x
+    integer, intent(in) :: y
+  end
+  subroutine s2(x, y)
+    real, intent(out) :: x
+    class(t), intent(in) :: y
+  end
+  subroutine test1(x)
+    type(t) :: x
+    real :: a
+    !CHECK: CALL s1(x,1_4)
+    x = 1
+    !CHECK: CALL s2(a,x)
+    a = x
+  end
+  subroutine test2(x)
+    class(t) :: x
+    real :: a
+    !CHECK: CALL x%b1(1_4)
+    x = 1
+    !CHECK: CALL x%b2(a)
+    a = x
+  end
+end
+
+! Type-bound operator
+module m2
+  type :: t2
+  contains
+    procedure, pass(x2) :: b2 => f
+    generic :: operator(+) => b2
+  end type
+contains
+  integer pure function f(x1, x2)
+    class(t2), intent(in) :: x1
+    class(t2), intent(in) :: x2
+  end
+  subroutine test2(x, y)
+    class(t2) :: x
+    type(t2) :: y
+    !CHECK: i=f(x,y)
+    i = x + y
+    !CHECK: i=x%b2(y)
+    i = y + x
+  end
+end module
+
+! Non-type-bound assignment and operator
+module m3
+  type t
+  end type
+  interface assignment(=)
+    subroutine s1(x, y)
+      import
+      class(t), intent(out) :: x
+      integer, intent(in) :: y
+    end
+  end interface
+  interface operator(+)
+    integer function f(x, y)
+      import
+      class(t), intent(in) :: x, y
+    end
+  end interface
+contains
+  subroutine test(x, y)
+    class(t) :: x, y
+    !CHECK: CALL s1(x,2_4)
+    x = 2
+    !CHECK: i=f(x,y)
+    i = x + y
+  end
+end
+


        


More information about the flang-commits mailing list