Dear All,

I have upgraded this patch slightly to fix PR58085 as well. I would
judge this to be completely safe because the fixes depend on the new
bit flag for both PRs.

Bootstrapped and regtested on FC17/x86_64 - OK for 4.9 immediately and trunk?

Paul

2014-04-12  Paul Thomas  <pa...@gcc.gnu.org>

    PR fortran/60717
    PR fortran/58085
   * trans.h: Add 'use_offset' bitfield to gfc_se.
    * trans-array.c (gfc_conv_expr_descriptor): Use 'use_offset'
    as a trigger to unconditionally recalculate the offset for
    array slices and constant arrays.
    trans-expr.c (gfc_conv_intrinsic_to_class): Use it.
    trans-stmt.c (trans_associate_var): Ditto.
    (gfc_conv_procedure_call): Ditto.

2014-04-12  Paul Thomas  <pa...@gcc.gnu.org>

    PR fortran/60717
    * gfortran.dg/unlimited_polymorphic_17.f90: New test.

    PR fortran/58085
    * gfortran.dg/associate_15.f90: New test.

On 12 April 2014 10:30, Jakub Jelinek <ja...@redhat.com> wrote:
> On Sat, Apr 12, 2014 at 07:27:00AM +0200, Paul Richard Thomas wrote:
>> I know that you are probably snowed under with requests like this!  I
>> was away on a business trip when Mikael's approval below came and had
>> intended to apply it to 4.9 aka trunk today. Is it OK with you if I
>> slip it into 4.9 or should I let it go until after the release?
>
> I'd prefer to put it in after the release, especially for non-regressions
> or regressions that aren't regressions from 4.8.2.
> 4.9.1 will be probably 2 months away from 4.9.0, and many people use release
> branch snapshots anyway, but I'd prefer to avoid any risks of slipping the
> release further.
>
>         Jakub



-- 
The knack of flying is learning how to throw yourself at the ground and miss.
       --Hitchhikers Guide to the Galaxy
Index: gcc/fortran/trans-array.c
===================================================================
*** gcc/fortran/trans-array.c   (revision 209322)
--- gcc/fortran/trans-array.c   (working copy)
*************** gfc_conv_expr_descriptor (gfc_se *se, gf
*** 6807,6814 ****
  
        /* Set offset for assignments to pointer only to zero if it is not
           the full array.  */
!       if (se->direct_byref
!         && info->ref && info->ref->u.ar.type != AR_FULL)
        base = gfc_index_zero_node;
        else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
        base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre);
--- 6807,6815 ----
  
        /* Set offset for assignments to pointer only to zero if it is not
           the full array.  */
!       if ((se->direct_byref || se->use_offset)
!         && ((info->ref && info->ref->u.ar.type != AR_FULL)
!             || (expr->expr_type == EXPR_ARRAY && se->use_offset)))
        base = gfc_index_zero_node;
        else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
        base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre);
*************** gfc_conv_expr_descriptor (gfc_se *se, gf
*** 6893,6905 ****
                                    stride, info->stride[n]);
  
          if (se->direct_byref
!             && info->ref
!             && info->ref->u.ar.type != AR_FULL)
            {
              base = fold_build2_loc (input_location, MINUS_EXPR,
                                      TREE_TYPE (base), base, stride);
            }
!         else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
            {
              tmp = gfc_conv_array_lbound (desc, n);
              tmp = fold_build2_loc (input_location, MINUS_EXPR,
--- 6894,6906 ----
                                    stride, info->stride[n]);
  
          if (se->direct_byref
!             && ((info->ref && info->ref->u.ar.type != AR_FULL)
!                 || (expr->expr_type == EXPR_ARRAY && se->use_offset)))
            {
              base = fold_build2_loc (input_location, MINUS_EXPR,
                                      TREE_TYPE (base), base, stride);
            }
!         else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)) || se->use_offset)
            {
              tmp = gfc_conv_array_lbound (desc, n);
              tmp = fold_build2_loc (input_location, MINUS_EXPR,
*************** gfc_conv_expr_descriptor (gfc_se *se, gf
*** 6935,6942 ****
        gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
                                subref_array_target, expr);
  
!       if ((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
          && !se->data_not_needed)
        {
          /* Set the offset.  */
          gfc_conv_descriptor_offset_set (&loop.pre, parm, base);
--- 6936,6944 ----
        gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
                                subref_array_target, expr);
  
!       if (((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
           && !se->data_not_needed)
+         || (se->use_offset && base != NULL_TREE))
        {
          /* Set the offset.  */
          gfc_conv_descriptor_offset_set (&loop.pre, parm, base);
Index: gcc/fortran/trans-expr.c
===================================================================
*** gcc/fortran/trans-expr.c    (revision 209322)
--- gcc/fortran/trans-expr.c    (working copy)
*************** gfc_conv_intrinsic_to_class (gfc_se *par
*** 593,598 ****
--- 593,599 ----
        else
        {
          parmse->ss = ss;
+         parmse->use_offset = 1;
          gfc_conv_expr_descriptor (parmse, e);
          gfc_add_modify (&parmse->pre, ctree, parmse->expr);
        }
*************** gfc_conv_procedure_call (gfc_se * se, gf
*** 4378,4383 ****
--- 4379,4385 ----
                        || CLASS_DATA (fsym)->attr.codimension))
            {
              /* Pass a class array.  */
+             parmse.use_offset = 1;
              gfc_conv_expr_descriptor (&parmse, e);
  
              /* If an ALLOCATABLE dummy argument has INTENT(OUT) and is
Index: gcc/fortran/trans-stmt.c
===================================================================
*** gcc/fortran/trans-stmt.c    (revision 209322)
--- gcc/fortran/trans-stmt.c    (working copy)
*************** trans_associate_var (gfc_symbol *sym, gf
*** 1170,1185 ****
        /* If association is to an expression, evaluate it and create temporary.
         Otherwise, get descriptor of target for pointer assignment.  */
        gfc_init_se (&se, NULL);
!       if (sym->assoc->variable)
        {
          se.direct_byref = 1;
          se.expr = desc;
        }
        gfc_conv_expr_descriptor (&se, e);
  
        /* If we didn't already do the pointer assignment, set associate-name
         descriptor to the one generated for the temporary.  */
!       if (!sym->assoc->variable)
        {
          int dim;
  
--- 1170,1187 ----
        /* If association is to an expression, evaluate it and create temporary.
         Otherwise, get descriptor of target for pointer assignment.  */
        gfc_init_se (&se, NULL);
!       if (sym->assoc->variable || e->expr_type == EXPR_ARRAY)
        {
          se.direct_byref = 1;
+         se.use_offset = 1;
          se.expr = desc;
        }
+ 
        gfc_conv_expr_descriptor (&se, e);
  
        /* If we didn't already do the pointer assignment, set associate-name
         descriptor to the one generated for the temporary.  */
!       if (!sym->assoc->variable && e->expr_type != EXPR_ARRAY)
        {
          int dim;
  
Index: gcc/fortran/trans.h
===================================================================
*** gcc/fortran/trans.h (revision 209322)
--- gcc/fortran/trans.h (working copy)
*************** typedef struct gfc_se
*** 87,92 ****
--- 87,96 ----
       args alias.  */
    unsigned force_tmp:1;
  
+   /* Unconditionally calculate offset for array segments and constant
+      arrays in gfc_conv_expr_descriptor.  */
+   unsigned use_offset:1;
+ 
    unsigned want_coarray:1;
  
    /* Scalarization parameters.  */
Index: gcc/testsuite/gfortran.dg/associate_15.f90
===================================================================
*** gcc/testsuite/gfortran.dg/associate_15.f90  (revision 0)
--- gcc/testsuite/gfortran.dg/associate_15.f90  (working copy)
***************
*** 0 ****
--- 1,40 ----
+ ! { dg-do run }
+ ! Test the fix for PR58085, where the offset for 'x' was set to zero,
+ ! rather than -1.
+ !
+ ! Contributed by Vladimir Fuka  <vladimir.f...@gmail.com>
+ !
+ module foo
+ contains
+   function bar (arg) result (res)
+     integer arg, res(3)
+     res = [arg, arg+1, arg +2]
+   end function
+ end module
+   use foo
+   real d(3,3)
+   integer a,b,c
+   character(48) line1, line2
+   associate (x=>shape(d))
+     a = x(1)
+     b = x(2)
+     write (line1, *) a, b
+     write (line2, *) x
+     if (trim (line1) .ne. trim (line2)) call abort
+   end associate
+   associate (x=>[1,2])
+     a = x(1)
+     b = x(2)
+     write (line1, *) a, b
+     write (line2, *) x
+     if (trim (line1) .ne. trim (line2)) call abort
+   end associate
+   associate (x=>bar(5)) ! make sure that we haven't broken function 
association
+     a = x(1)
+     b = x(2)
+     c = x(3)
+     write (line1, *) a, b, c
+     write (line2, *) x
+     if (trim (line1) .ne. trim (line2)) call abort
+   end associate
+ end
Index: gcc/testsuite/gfortran.dg/unlimited_polymorphic_17.f90
===================================================================
*** gcc/testsuite/gfortran.dg/unlimited_polymorphic_17.f90      (revision 0)
--- gcc/testsuite/gfortran.dg/unlimited_polymorphic_17.f90      (working copy)
***************
*** 0 ****
--- 1,51 ----
+ ! { dg-do run }
+ ! Tests fix for PR60717 in which offsets in recursive calls below
+ ! were not being set correctly.
+ !
+ ! Reported on comp.lang.fortran by Thomas Schnurrenberger
+ !
+ module m
+   implicit none
+   real :: chksum0 = 0, chksum1 = 0, chksum2 = 0
+ contains
+   recursive subroutine show_real(a)
+     real, intent(in) :: a(:)
+     if (size (a) > 0) then
+       chksum0 = a(1) + chksum0
+       call show_real (a(2:))
+     end if
+     return
+   end subroutine show_real
+   recursive subroutine show_generic1(a)
+     class(*), intent(in) :: a(:)
+     if (size (a) > 0) then
+       select type (a)
+       type is (real)
+         chksum1 = a(1) + chksum1
+       end select
+       call show_generic1 (a(2:)) ! recursive call outside SELECT TYPE
+     end if
+     return
+   end subroutine show_generic1
+   recursive subroutine show_generic2(a)
+     class(*), intent(in) :: a(:)
+     if (size (a) > 0) then
+       select type (a)
+       type is (real)
+         chksum2 = a(1) + chksum2
+         call show_generic2 (a(2:)) ! recursive call inside SELECT TYPE
+       end select
+     end if
+     return
+   end subroutine show_generic2
+ end module m
+ program test
+   use :: m
+   implicit none
+   real :: array(1:6) = (/ 0, 1, 2, 3, 4, 5 /)
+   call show_real (array)
+   call show_generic1 (array)
+   call show_generic2 (array)
+   if (chksum0 .ne. chksum1) call abort
+   if (chksum0 .ne. chksum2) call abort
+ end program test

Reply via email to