From: Mikael Morin <[email protected]>
Fortran-tested on aarch64-unknown-linux-gnu.
OK for mainline?
-- >8 --
In the implementation of the simply contiguous predicate, take into account
class containers when identifying non-contiguous pointers, assumed-rank or
assumed-shape dummies.
The implementation was picking the last component reference in the chain to
return false if it had the pointer but not the contiguous attribute. This
was causing the predicate to return false for a polymorphic contiguous
array, because the last component is the _data component of the class
container. It has the pointer attribute for a non-allocatable dummy or a
pointer, and it hasn't the contiguous attribute which is stored in the
parent entity, that is at the class container level.
Fixing this requires keeping at the same time access to the contiguous
attribute, the pointer attribute and the array type. So this change omits
advancing the last component reference to the next during the walk, if the
next is the _data component of a class container. Then the rest just needs
to discriminate the attribute and array spec query between polymorphic and
non-polymorphic references; for the pointer attribute we can just use the
IS_POINTER macro. Associate names are explicitly excluded at that point so
that we have the opportunity to forward the simply contiguous query to the
associate target for them.
PR fortran/127613
gcc/fortran/ChangeLog:
* expr.cc (gfc_is_simply_contiguous): Track the current type
during the data reference walk and only keep component references
that are not the _data component of a class container. Query the
array type on the _data component of the class container for
polymorphic variables.
gcc/testsuite/ChangeLog:
* gfortran.dg/contiguous_19.f90: New test.
---
gcc/fortran/expr.cc | 32 +++++++++++++++----
gcc/testsuite/gfortran.dg/contiguous_19.f90 | 34 +++++++++++++++++++++
2 files changed, 60 insertions(+), 6 deletions(-)
create mode 100644 gcc/testsuite/gfortran.dg/contiguous_19.f90
diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc
index 68663fe35d1..c234f2573bc 100644
--- a/gcc/fortran/expr.cc
+++ b/gcc/fortran/expr.cc
@@ -6461,13 +6461,25 @@ gfc_is_simply_contiguous (gfc_expr *expr, bool strict,
bool permit_element)
if (!permit_element && expr->rank == 0)
return false;
+ sym = expr->symtree->n.sym;
+ const gfc_typespec *prev_ts = &sym->ts;
for (ref = expr->ref; ref; ref = ref->next)
{
if (ar)
return false; /* Array shall be last part-ref. */
if (ref->type == REF_COMPONENT)
- part_ref = ref;
+ {
+ /* If the reference is to a class container's _data component, keep
+ part_ref pointing to the class container, so that the attributes of
+ both the class container and its _data component can be queried
+ from part_ref. */
+ if (!(prev_ts->type == BT_CLASS
+ && prev_ts->u.derived->attr.is_class
+ && strcmp (ref->u.c.component->name, "_data") == 0))
+ part_ref = ref;
+ prev_ts = &ref->u.c.component->ts;
+ }
else if (ref->type == REF_SUBSTRING)
return false;
else if (ref->type == REF_INQUIRY)
@@ -6476,17 +6488,25 @@ gfc_is_simply_contiguous (gfc_expr *expr, bool strict,
bool permit_element)
ar = &ref->u.ar;
}
- sym = expr->symtree->n.sym;
if ((part_ref
&& part_ref->u.c.component
&& !part_ref->u.c.component->attr.contiguous
&& IS_POINTER (part_ref->u.c.component))
|| (!part_ref
- && expr->ts.type != BT_CLASS
&& !sym->attr.contiguous
- && (sym->attr.pointer
- || (sym->as && sym->as->type == AS_ASSUMED_RANK)
- || (sym->as && sym->as->type == AS_ASSUMED_SHAPE))))
+ /* Associate names may be associated with a simply contiguous target
+ without having the contiguous attribute set. Skip them here, and
+ handle them below. */
+ && !sym->attr.associate_var
+ && (IS_POINTER (sym)
+ || (sym->ts.type == BT_CLASS
+ && sym->ts.u.derived->attr.is_class
+ && CLASS_DATA (sym)->as
+ && (CLASS_DATA (sym)->as->type == AS_ASSUMED_RANK
+ || CLASS_DATA (sym)->as->type == AS_ASSUMED_SHAPE))
+ || (sym->as
+ && (sym->as->type == AS_ASSUMED_RANK
+ || sym->as->type == AS_ASSUMED_SHAPE)))))
return false;
/* An associate variable may point to a non-contiguous target. */
diff --git a/gcc/testsuite/gfortran.dg/contiguous_19.f90
b/gcc/testsuite/gfortran.dg/contiguous_19.f90
new file mode 100644
index 00000000000..9fec8fc46bc
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/contiguous_19.f90
@@ -0,0 +1,34 @@
+! { dg-do compile }
+!
+! PR fortran/127613
+! Check that simply contiguous polymorphic arrays are correctly recognized as
+! such, and that the information correctly propagates to associate names.
+! One associate name used as pointer association target below used to not be
+! recognized as simply contiguous.
+
+program prog
+ implicit none
+ integer, parameter :: n = 3
+ type :: t
+ integer :: c
+ end type
+ type(t), allocatable, target :: x(:,:)
+ integer :: i
+ x = reshape([ (t(i*i), i=1,n*n) ], [n,n])
+ call sub1(x)
+contains
+ subroutine sub1(z)
+ class(t), contiguous, target :: z(:,:)
+ class(t), contiguous, pointer :: p(:,:)
+ class(t), pointer :: q(:)
+ q(1:n*n) => z
+ associate (a => z)
+ q(1:n*n) => a
+ end associate
+ p => z
+ q(1:n*n) => p
+ associate (b => p)
+ q(1:n*n) => b
+ end associate
+ end subroutine
+end program
--
2.53.0