Dear all,

The attached patch fixes PR105658 by forcing an array temporary to be
created. This is required when passing an array component, but this
didn't happen if the dummy argument was an unlimited polymorphic type.

The problem bit of code is in `gfc_conv_expr_descriptor`, near L7828:

      subref_array_target = (is_subref_array (expr)
     && (se->direct_byref
|| expr->ts.type == BT_CHARACTER));
      need_tmp = (gfc_ref_needs_temporary_p (expr->ref)
  && !subref_array_target);

where `need_tmp` is being evaluated to 0.  The logic here isn't clear
to me, and this function is used in several places, which is why I
went with setting `parmse.force_tmp = 1` in `gfc_conv_procedure_call`
and using the same conditional as the later branch for the
non-polymorphic case (near the call to `gfc_conv_subref_array_arg`)

If this patch is ok, please could someone commit it for me? This is my
first patch for GCC, so apologies in advance if the commit message is
missing something.

Tested on x86_64-pc-linux-gnu.

The bug is present in gfortran back to 4.9, so should it also be backported?

Cheers,
Peter

         PR fortran/105658

gcc/fortran/ChangeLog

        * trans-expr.cc (gfc_conv_procedure_call): When passing an
        array component reference of intrinsic type to a procedure
        with an unlimited polymorphic dummy argument, a temporary
        should be created.

gcc/testsuite/ChangeLog

        * gfortran.dg/PR105658.f90: New test.
---
 gcc/fortran/trans-expr.cc              |  8 ++++++++
 gcc/testsuite/gfortran.dg/PR105658.f90 | 25 +++++++++++++++++++++++++
 2 files changed, 33 insertions(+)
 create mode 100644 gcc/testsuite/gfortran.dg/PR105658.f90

diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index a0593b76f18..7fd3047c4e9 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -6439,6 +6439,14 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
       CLASS object for the unlimited polymorphic formal.  */
    gfc_find_vtab (&e->ts);
    gfc_init_se (&parmse, se);
+   /* The actual argument is a component reference to an array
+      of derived types, so we need to force creation of a
+      temporary */
+   if (e->expr_type == EXPR_VARIABLE
+       && is_subref_array (e)
+       && !(fsym && fsym->attr.pointer))
+     parmse.force_tmp = 1;
+
    gfc_conv_intrinsic_to_class (&parmse, e, fsym->ts);

  }
diff --git a/gcc/testsuite/gfortran.dg/PR105658.f90
b/gcc/testsuite/gfortran.dg/PR105658.f90
new file mode 100644
index 00000000000..407ee25f77c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/PR105658.f90
@@ -0,0 +1,25 @@
+! { dg-do compile }
+! { dg-options "-Warray-temporaries" }
+! Test fix for incorrectly passing array component to unlimited
polymorphic procedure
+
+module test_PR105658_mod
+  implicit none
+  type :: foo
+    integer :: member1
+    integer :: member2
+  end type foo
+contains
+  subroutine print_poly(array)
+    class(*), dimension(:), intent(in) :: array
+    select type(array)
+    type is (integer)
+      print*, array
+    end select
+  end subroutine print_poly
+
+  subroutine do_print(thing)
+    type(foo), dimension(3), intent(in) :: thing
+    call print_poly(thing%member1) ! { dg-warning "array temporary" }
+  end subroutine do_print
+
+end module test_PR105658_mod
-- 
2.43.0

Reply via email to