Sorry about the premature 'send'.

This one is more or less obvious and is described in the ChangeLog.
The key point is that full or section array references to intrinsic
components were returning a false true from expr.c (is_subref_array).
Returning false if a component is intrinsic and following anything
other than an array element is an obvious remedy.

Bootstrapped and regtested on FC28/x86_64 - OK for trunk and 8-branch?

Paul

2019-01-30  Paul Thomas  <pa...@gcc.gnu.org>

    PR fortran/88685
    * expr.c (is_subref_array): Move the check for class pointer
    dummy arrays to after the reference check. If we haven't seen
    an array reference other than an element and a component is not
    class or derived, return false.

2019-01-30  Paul Thomas  <pa...@gcc.gnu.org>

    PR fortran/88685
    * gfortran.dg/pointer_array_component_3.f90 : New test.
Index: gcc/fortran/expr.c
===================================================================
*** gcc/fortran/expr.c	(revision 268230)
--- gcc/fortran/expr.c	(working copy)
*************** is_subref_array (gfc_expr * e)
*** 1072,1086 ****
    if (e->symtree->n.sym->attr.subref_array_pointer)
      return true;
  
-   if (e->symtree->n.sym->ts.type == BT_CLASS
-       && e->symtree->n.sym->attr.dummy
-       && CLASS_DATA (e->symtree->n.sym)->attr.dimension
-       && CLASS_DATA (e->symtree->n.sym)->attr.class_pointer)
-     return true;
- 
    seen_array = false;
    for (ref = e->ref; ref; ref = ref->next)
      {
        if (ref->type == REF_ARRAY
  	    && ref->u.ar.type != AR_ELEMENT)
  	seen_array = true;
--- 1072,1086 ----
    if (e->symtree->n.sym->attr.subref_array_pointer)
      return true;
  
    seen_array = false;
+ 
    for (ref = e->ref; ref; ref = ref->next)
      {
+       if (!seen_array && ref->type == REF_COMPONENT
+ 	  && (ref->u.c.component->ts.type != BT_CLASS
+ 	      && ref->u.c.component->ts.type != BT_DERIVED))
+ 	return false;
+ 
        if (ref->type == REF_ARRAY
  	    && ref->u.ar.type != AR_ELEMENT)
  	seen_array = true;
*************** is_subref_array (gfc_expr * e)
*** 1089,1094 ****
--- 1089,1101 ----
  	    && ref->type != REF_ARRAY)
  	return seen_array;
      }
+ 
+   if (e->symtree->n.sym->ts.type == BT_CLASS
+       && e->symtree->n.sym->attr.dummy
+       && CLASS_DATA (e->symtree->n.sym)->attr.dimension
+       && CLASS_DATA (e->symtree->n.sym)->attr.class_pointer)
+     return true;
+ 
    return false;
  }
  
Index: gcc/testsuite/gfortran.dg/pointer_array_component_3.f90
===================================================================
*** gcc/testsuite/gfortran.dg/pointer_array_component_3.f90	(nonexistent)
--- gcc/testsuite/gfortran.dg/pointer_array_component_3.f90	(working copy)
***************
*** 0 ****
--- 1,36 ----
+ ! { dg-do run }
+ !
+ ! Test the fix for PR88685, in which the component array references in 'doit'
+ ! were being ascribed to the class pointer 'Cls' itself so that the stride
+ ! measure between elements was wrong.
+ !
+ ! Contributed by Antony Lewis  <ant...@cosmologist.info>
+ !
+ program tester
+   implicit none
+   Type TArr
+     integer, allocatable :: CL(:)
+   end Type TArr
+ 
+   type(TArr), allocatable, target :: arr(:,:)
+   class(TArr), pointer:: Cls(:,:)
+   integer i
+ 
+   allocate(arr(1,1))
+   allocate(arr(1,1)%CL(3))
+   arr(1,1)%CL=-1
+   cls => arr
+   call doit(cls)
+   if (any (arr(1,1)%cl .ne. [3,2,1])) stop 3
+ contains
+   subroutine doit(cls)
+     class(TArr), pointer :: Cls(:,:)
+ 
+     cls(1,1)%CL(1) = 3
+     cls(1,1)%CL(2:3) = [2,1]
+ 
+     if (any (Cls(1,1)%CL .ne. [3,2,1])) stop 1
+     if (Cls(1,1)%CL(2) .ne. 2) stop 2
+ 
+   end subroutine doit
+ end program tester

Reply via email to