PR fortran/58085
PR fortran/60717
* 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-13 Paul Thomas <pault@gcc.gnu.org>
PR fortran/60717
* gfortran.dg/unlimited_polymorphic_17.f90: New test.
PR fortran/58085
* gfortran.dg/associate_15.f90: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_9-branch@209346
138bc75d-0d04-0410-961f-
82ee72b054a4
+2014-04-13 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/58085
+ PR fortran/60717
+ * 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-11 Janne Blomqvist <jb@gcc.gnu.org>
* intrinsic.texi (RANDOM_SEED): Improve example.
/* 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)
+ 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);
stride, info->stride[n]);
if (se->direct_byref
- && info->ref
- && info->ref->u.ar.type != AR_FULL)
+ && ((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)))
+ 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_get_dataptr_offset (&loop.pre, parm, desc, offset,
subref_array_target, expr);
- if ((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
+ 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);
else
{
parmse->ss = ss;
+ parmse->use_offset = 1;
gfc_conv_expr_descriptor (parmse, e);
gfc_add_modify (&parmse->pre, ctree, parmse->expr);
}
|| 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
/* 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)
+ 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)
+ if (!sym->assoc->variable && e->expr_type != EXPR_ARRAY)
{
int dim;
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. */
+2014-04-13 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/60717
+ * gfortran.dg/unlimited_polymorphic_17.f90: New test.
+
+ PR fortran/58085
+ * gfortran.dg/associate_15.f90: New test.
+
2014-04-12 Jerry DeLisle <jvdelisle@gcc.gnu>
PR libfortran/60810
--- /dev/null
+! { 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.fuka@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
--- /dev/null
+! { 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