Wrong array section bounds when passing to an intent-in pointer dummy.

Add code to allow for the creation a new descriptor for array
sections with the correct one based indexing.

Rework the generated descriptors indexing (hopefully) fixing the
wrong offsets generated.

gcc/fortran/ChangeLog:

2020-06-11  José Rui Faustino de Sousa  <jrfsousa@gmail.com>

	PR fortran/52351
	PR fortran/85868
	* trans-array.c (gfc_conv_expr_descriptor): Enable the
	creation of a new descriptor with the correct one based
	indexing for array sections.  Rework array descriptor
	indexing offset calculation.

gcc/testsuite/ChangeLog:

2020-06-11  José Rui Faustino de Sousa  <jrfsousa@gmail.com>

	PR fortran/52351
	PR fortran/85868
	* gfortran.dg/coarray_lib_comm_1.f90: Adjust match test for
	the newly generated descriptor.
	* gfortran.dg/PR85868A.f90: New test.
	* gfortran.dg/PR85868B.f90: New test.
This commit is contained in:
José Rui Faustino de Sousa 2020-06-11 14:14:30 +02:00 committed by Thomas Koenig
parent be11812eef
commit 2ff0f48819
4 changed files with 219 additions and 106 deletions

View File

@ -7201,7 +7201,6 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
tree desc;
stmtblock_t block;
tree start;
tree offset;
int full;
bool subref_array_target = false;
bool deferred_array_component = false;
@ -7272,6 +7271,10 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
full = 1;
else if (se->direct_byref)
full = 0;
else if (info->ref->u.ar.dimen == 0 && !info->ref->next)
full = 1;
else if (info->ref->u.ar.type == AR_SECTION && se->want_pointer)
full = 0;
else
full = gfc_full_array_ref_p (info->ref, NULL);
@ -7508,10 +7511,9 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
tree from;
tree to;
tree base;
bool onebased = false, rank_remap;
tree offset;
ndim = info->ref ? info->ref->u.ar.dimen : ss->dimen;
rank_remap = ss->dimen < ndim;
if (se->want_coarray)
{
@ -7555,10 +7557,10 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl, tmp);
}
/* If we have an array section or are assigning make sure that
the lower bound is 1. References to the full
array should otherwise keep the original bounds. */
if ((!info->ref || info->ref->u.ar.type != AR_FULL) && !se->want_pointer)
/* If we have an array section, are assigning or passing an array
section argument make sure that the lower bound is 1. References
to the full array should otherwise keep the original bounds. */
if (!info->ref || info->ref->u.ar.type != AR_FULL)
for (dim = 0; dim < loop.dimen; dim++)
if (!integer_onep (loop.from[dim]))
{
@ -7622,8 +7624,6 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
if (tmp != NULL_TREE)
gfc_conv_descriptor_span_set (&loop.pre, parm, tmp);
offset = gfc_index_zero_node;
/* The following can be somewhat confusing. We have two
descriptors, a new one and the original array.
{parm, parmtype, dim} refer to the new one.
@ -7637,22 +7637,17 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
tmp = gfc_conv_descriptor_dtype (parm);
gfc_add_modify (&loop.pre, tmp, gfc_get_dtype (parmtype));
/* 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);
else
base = NULL_TREE;
/* The 1st element in the section. */
base = gfc_index_zero_node;
/* The offset from the 1st element in the section. */
offset = gfc_index_zero_node;
for (n = 0; n < ndim; n++)
{
stride = gfc_conv_array_stride (desc, n);
/* Work out the offset. */
/* Work out the 1st element in the section. */
if (info->ref
&& info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
{
@ -7672,13 +7667,14 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
start, tmp);
tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
tmp, stride);
offset = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
offset, tmp);
base = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
base, tmp);
if (info->ref
&& info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
{
/* For elemental dimensions, we only need the offset. */
/* For elemental dimensions, we only need the 1st
element in the section. */
continue;
}
@ -7698,7 +7694,6 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
from = loop.from[dim];
to = loop.to[dim];
onebased = integer_onep (from);
gfc_conv_descriptor_lbound_set (&loop.pre, parm,
gfc_rank_cst[dim], from);
@ -7712,35 +7707,10 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
gfc_array_index_type,
stride, info->stride[n]);
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 = fold_build2_loc (input_location, MINUS_EXPR,
TREE_TYPE (base), base, stride);
}
else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)) || se->use_offset)
{
bool toonebased;
tmp = gfc_conv_array_lbound (desc, n);
toonebased = integer_onep (tmp);
// lb(arr) - from (- start + 1)
tmp = fold_build2_loc (input_location, MINUS_EXPR,
TREE_TYPE (base), tmp, from);
if (onebased && toonebased)
{
tmp = fold_build2_loc (input_location, MINUS_EXPR,
TREE_TYPE (base), tmp, start);
tmp = fold_build2_loc (input_location, PLUS_EXPR,
TREE_TYPE (base), tmp,
gfc_index_one_node);
}
tmp = fold_build2_loc (input_location, MULT_EXPR,
TREE_TYPE (base), tmp,
gfc_conv_array_stride (desc, n));
base = fold_build2_loc (input_location, PLUS_EXPR,
TREE_TYPE (base), tmp, base);
}
tmp = fold_build2_loc (input_location, MULT_EXPR,
TREE_TYPE (offset), stride, from);
offset = fold_build2_loc (input_location, MINUS_EXPR,
TREE_TYPE (offset), offset, tmp);
/* Store the new stride. */
gfc_conv_descriptor_stride_set (&loop.pre, parm,
@ -7763,58 +7733,11 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
gfc_index_zero_node);
else
/* Point the data pointer at the 1st element in the section. */
gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
gfc_get_dataptr_offset (&loop.pre, parm, desc, base,
subref_array_target, expr);
/* Force the offset to be -1, when the lower bound of the highest
dimension is one and the symbol is present and is not a
pointer/allocatable or associated. */
if (((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
&& !se->data_not_needed)
|| (se->use_offset && base != NULL_TREE))
{
/* Set the offset depending on base. */
tmp = rank_remap && !se->direct_byref ?
fold_build2_loc (input_location, PLUS_EXPR,
gfc_array_index_type, base,
offset)
: base;
gfc_conv_descriptor_offset_set (&loop.pre, parm, tmp);
}
else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
&& !se->data_not_needed
&& (!rank_remap || se->use_offset))
{
gfc_conv_descriptor_offset_set (&loop.pre, parm,
gfc_conv_descriptor_offset_get (desc));
}
else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
&& !se->data_not_needed
&& gfc_expr_attr (expr).select_rank_temporary)
{
gfc_conv_descriptor_offset_set (&loop.pre, parm, gfc_index_zero_node);
}
else if (onebased && (!rank_remap || se->use_offset)
&& expr->symtree
&& !(expr->symtree->n.sym && expr->symtree->n.sym->ts.type == BT_CLASS
&& !CLASS_DATA (expr->symtree->n.sym)->attr.class_pointer)
&& !expr->symtree->n.sym->attr.allocatable
&& !expr->symtree->n.sym->attr.pointer
&& !expr->symtree->n.sym->attr.host_assoc
&& !expr->symtree->n.sym->attr.use_assoc)
{
/* Set the offset to -1. */
mpz_t minus_one;
mpz_init_set_si (minus_one, -1);
tmp = gfc_conv_mpz_to_tree (minus_one, gfc_index_integer_kind);
gfc_conv_descriptor_offset_set (&loop.pre, parm, tmp);
}
else
{
/* Only the callee knows what the correct offset it, so just set
it to zero here. */
gfc_conv_descriptor_offset_set (&loop.pre, parm, gfc_index_zero_node);
}
gfc_conv_descriptor_offset_set (&loop.pre, parm, offset);
desc = parm;
}

View File

@ -0,0 +1,47 @@
! { dg-do run }
!
! PR fortran/85868
!
! Contributed by Harald Anlauf <anlauf@gmx.de>
!
program test
implicit none
integer, parameter :: e(*) = [1, 1, -1, -1, 0, 0, 1]
integer, pointer :: t(:), u(:)
integer :: i
allocate (t(-1:5))
do i = -1, 5
t(i) = i
end do
call p (t, e(1)) ! Pointer with lower bound = -1 from allocation
u => t ! Pointer assignment sets same lower bound
call p (u, e(2))
!
u => t(:) ! Pointer assignment with implicit lower bound (1)
call p (u, e(3))
call p (t(:), e(4)) ! Full array, behaves the same
!
call p (t(0:), e(5)) ! Array section
u => t(0:) ! Pointer assignment with implicit lower bound (1)
call p (u, e(6))
u(0:) => t(0:) ! Pointer assignment with given lower bound (0)
call p (u, e(7))
stop
contains
subroutine p (a, v)
integer, pointer, intent(in) :: a(:)
integer, intent(in) :: v
if(a(1)/=v) stop 1001
return
end subroutine p
end program test

View File

@ -0,0 +1,144 @@
program main_p
implicit none
integer, parameter :: n = 10
integer, parameter :: m = 5
integer, parameter :: b = 3
integer, parameter :: t = n+b-1
integer, parameter :: l = 4
integer, parameter :: u = 7
integer, parameter :: s = 3
integer, parameter :: e = (u-l)/s+1
call test_f()
call test_s()
call test_p()
call test_a()
stop
contains
subroutine test_f()
integer, target :: x(n,n)
integer, target :: y(b:t)
integer :: i
x = reshape([(i, i=1,n*n)], [n,n])
y = x(:,m)
call sub_s(x(:,m), y, 1, n, n)
call sub_s(y, x(:,m), b, t, n)
return
end subroutine test_f
subroutine test_s()
integer, target :: x(n,n)
integer, target :: v(e)
integer :: i
x = reshape([(i, i=1,n*n)], [n,n])
v = x(l:u:s,m)
call sub_s(v, v, 1, e, e)
call sub_s(x(l:u:s,m), v, 1, e, e)
call sub_s(v, x(l:u:s,m), 1, e, e)
return
end subroutine test_s
subroutine test_p()
integer, target :: x(n,n)
integer, pointer :: p(:)
integer :: v(e)
integer :: i
x = reshape([(i, i=1,n*n)], [n,n])
v = x(l:u:s,m)
p => x(:,m)
call sub_s(p(l:u:s), v, 1, e, e)
p => x(l:u:s,m)
call sub_s(p, v, 1, e, e)
p(l:) => x(l:u:s,m)
call sub_s(p, v, l, e+l-1, e)
p(l:l+e-1) => x(l:u:s,m)
call sub_s(p, v, l, e+l-1, e)
allocate(p(n))
p(:) = x(:,m)
call sub_s(p(l:u:s), v, 1, e, e)
deallocate(p)
allocate(p(e))
p(:) = x(l:u:s,m)
call sub_s(p, v, 1, e, e)
deallocate(p)
allocate(p(l:l+e-1))
p(:) = x(l:u:s,m)
call sub_s(p, v, l, e+l-1, e)
deallocate(p)
allocate(p(l:l+e-1))
p(l:) = x(l:u:s,m)
call sub_s(p, v, l, e+l-1, e)
deallocate(p)
allocate(p(l:l+e-1))
p(l:l+e-1) = x(l:u:s,m)
call sub_s(p, v, l, e+l-1, e)
deallocate(p)
return
end subroutine test_p
subroutine test_a()
integer :: x(n,n)
integer, allocatable, target :: a(:)
integer :: v(e)
integer :: i
x = reshape([(i, i=1,n*n)], [n,n])
v = x(l:u:s,m)
a = x(:,m)
call sub_s(a(l:u:s), v, 1, e, e)
deallocate(a)
allocate(a(n))
a(:) = x(:,m)
call sub_s(a(l:u:s), v, 1, e, e)
deallocate(a)
a = x(l:u:s,m)
call sub_s(a, v, 1, e, e)
deallocate(a)
allocate(a(e))
a(:) = x(l:u:s,m)
call sub_s(a, v, 1, e, e)
deallocate(a)
allocate(a(l:l+e-1))
a(:) = x(l:u:s,m)
call sub_s(a, v, l, e+l-1, e)
deallocate(a)
allocate(a(l:l+e-1))
a(l:) = x(l:u:s,m)
call sub_s(a, v, l, e+l-1, e)
deallocate(a)
allocate(a(l:l+e-1))
a(l:l+e-1) = x(l:u:s,m)
call sub_s(a, v, l, e+l-1, e)
deallocate(a)
return
end subroutine test_a
subroutine sub_s(a, b, l, u, e)
integer, pointer, intent(in) :: a(:)
integer, intent(in) :: b(:)
integer, intent(in) :: l
integer, intent(in) :: u
integer, intent(in) :: e
integer :: i
if(lbound(a,dim=1)/=l) stop 1001
if(ubound(a,dim=1)/=u) stop 1002
if(any(shape(a)/=[e])) stop 1003
if(size(a, dim=1)/=e) stop 1004
if(size(a)/=size(b)) stop 1005
do i = l, u
if(a(i)/=b(i-l+1)) stop 1006
end do
end subroutine sub_s
end program main_p

View File

@ -38,8 +38,7 @@ B(1:5) = B(3:7)
if (any (A-B /= 0)) STOP 4
end
! { dg-final { scan-tree-dump-times "_gfortran_caf_get \\\(caf_token.0, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) a, 1, &parm.\[0-9\]+, 0B, &parm.\[0-9\]+, 4, 4, 1, 0B\\\);" 2 "original" } }
! { dg-final { scan-tree-dump-times "_gfortran_caf_get \\\(caf_token.0, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) a, 1, &parm.\[0-9\]+, 0B, &p, 4, 4, 1, 0B\\\);" 1 "original" } }
! { dg-final { scan-tree-dump-times "_gfortran_caf_get \\\(caf_token.1, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) b, 1, &parm.\[0-9\]+, 0B, &p, 4, 4, 0, 0B\\\);" 1 "original" } }
! { dg-final { scan-tree-dump-times "_gfortran_caf_get \\\(caf_token.0, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) a, 1, &parm.\[0-9\]+, 0B, &parm.\[0-9\]+, 4, 4, 1, 0B\\\);" 3 "original" } }
! { dg-final { scan-tree-dump-times "_gfortran_caf_get \\\(caf_token.1, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) b, 1, &parm.\[0-9\]+, 0B, &parm.\[0-9\]+, 4, 4, 0, 0B\\\);" 1 "original" } }
! { dg-final { scan-tree-dump-times "_gfortran_caf_sendget \\\(caf_token.0, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) a, 1, &parm.\[0-9\]+, 0B, caf_token.0, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) a, 1, &parm.\[0-9\]+, 0B, 4, 4, 1, 0B\\\);" 1 "original" } }