Oh, well, now with attachments. I am sorry.

- Andre

On Mon, 1 Feb 2016 13:20:24 +0100
Andre Vehreschild <ve...@gmx.de> wrote:

> Hi all,
> 
> here is the backport of the patch for pr67451 for gcc-5. Because the
> structure of the allocate() in trunk is quite different the patch looks
> somewhat different, too, but essentially does the same.
> 
> Bootstrapped and regtests ok on x86_64-linux-gnu/F23.
> 
> Ok for gcc-5-branch?
> 
> Here is the link to the mainline patch:
> https://gcc.gnu.org/ml/fortran/2016-01/msg00093.html
> 
> Regards,
>       Andre
> 
> On Fri, 29 Jan 2016 19:17:24 +0100
> Andre Vehreschild <ve...@gmx.de> wrote:
> 
> > Hi all,
> > 
> > attached is a patch to fix a regression in current gfortran when a
> > coarray is used in the source=-expression of an allocate(). The ICE was
> > caused by the class information, i.e., _vptr and so on, not at the
> > expected place. The patch fixes this.
> > 
> > The patch also fixes pr69418, which I will flag as a duplicate in a
> > second.
> > 
> > Bootstrapped and regtested ok on x86_64-linux-gnu/F23.
> > 
> > Ok for trunk?
> > 
> > Backport to gcc-5 is pending, albeit more difficult, because the
> > allocate() implementation on 5 is not as advanced the one in 6.
> > 
> > Regards,
> >     Andre  
> 
> 


-- 
Andre Vehreschild * Email: vehre ad gmx dot de 
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 4c368a8..0daa631 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -1019,6 +1019,7 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited)
   tree fcn;
   tree fcn_type;
   tree from_data;
+  tree from_class_base = NULL;
   tree from_len;
   tree to_data;
   tree to_len;
@@ -1035,21 +1036,41 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited)
   from_len = to_len = NULL_TREE;
 
   if (from != NULL_TREE)
-    fcn = gfc_class_vtab_copy_get (from);
+    {
+      /* Check that from is a class.  When the class is part of a coarray,
+	 then from is a common pointer and is to be used as is.  */
+      tmp = POINTER_TYPE_P (TREE_TYPE (from)) && !DECL_P (from)
+	  ? TREE_OPERAND (from, 0) : from;
+      if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
+	  || (DECL_P (tmp) && GFC_DECL_CLASS (tmp)))
+	{
+	  from_class_base = from;
+	  from_data = gfc_class_data_get (from_class_base);
+	}
+      else
+	{
+	  /* For arrays two component_refs can be present.  */
+	  if (TREE_CODE (tmp) == COMPONENT_REF)
+	    tmp = TREE_OPERAND (tmp, 0);
+	  if (TREE_CODE (tmp) == COMPONENT_REF)
+	    tmp = TREE_OPERAND (tmp, 0);
+	  from_class_base = tmp;
+	  from_data = from;
+	}
+      fcn = gfc_class_vtab_copy_get (from_class_base);
+    }
   else
-    fcn = gfc_class_vtab_copy_get (to);
+    {
+      fcn = gfc_class_vtab_copy_get (to);
+      from_data = gfc_class_vtab_def_init_get (to);
+    }
 
   fcn_type = TREE_TYPE (TREE_TYPE (fcn));
 
-  if (from != NULL_TREE)
-      from_data = gfc_class_data_get (from);
-  else
-    from_data = gfc_class_vtab_def_init_get (to);
-
   if (unlimited)
     {
-      if (from != NULL_TREE && unlimited)
-	from_len = gfc_class_len_get (from);
+      if (from_class_base != NULL_TREE)
+	from_len = gfc_class_len_get (from_class_base);
       else
 	from_len = integer_zero_node;
     }
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 0be92cd..9c1f920 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -5180,7 +5180,7 @@ gfc_trans_allocate (gfc_code * code)
      _vptr, _len and element_size for expr3.  */
   if (code->expr3)
     {
-      bool vtab_needed = false;
+      bool vtab_needed = false, is_coarray = gfc_is_coarray (code->expr3);
       /* expr3_tmp gets the tree when code->expr3.mold is set, i.e.,
 	 the expression is only needed to get the _vptr, _len a.s.o.  */
       tree expr3_tmp = NULL_TREE;
@@ -5245,7 +5245,8 @@ gfc_trans_allocate (gfc_code * code)
 		{
 		  tree var;
 
-		  tmp = build_fold_indirect_ref_loc (input_location,
+		  tmp = is_coarray ? se.expr
+				  : build_fold_indirect_ref_loc (input_location,
 						     se.expr);
 
 		  /* We need a regular (non-UID) symbol here, therefore give a
@@ -5297,6 +5298,16 @@ gfc_trans_allocate (gfc_code * code)
 	  else if (expr3_tmp != NULL_TREE
 		   && (VAR_P (expr3_tmp) ||!code->expr3->ref))
 	    tmp = gfc_class_vptr_get (expr3_tmp);
+	  else if (is_coarray && expr3 != NULL_TREE)
+	    {
+	      /* Get the ref to coarray's data.  May be wrapped in a
+		 NOP_EXPR.  */
+	      tmp = POINTER_TYPE_P (TREE_TYPE (expr3)) ? TREE_OPERAND (expr3, 0)
+						       : tmp;
+	      /* Get to the base variable, i.e., strip _data.data.  */
+	      tmp = TREE_OPERAND (TREE_OPERAND (tmp, 0), 0);
+	      tmp = gfc_class_vptr_get (tmp);
+	    }
 	  else
 	    {
 	      rhs = gfc_find_and_cut_at_last_class_ref (code->expr3);
diff --git a/gcc/testsuite/gfortran.dg/coarray_allocate_2.f08 b/gcc/testsuite/gfortran.dg/coarray_allocate_2.f08
new file mode 100644
index 0000000..7a712a9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_allocate_2.f08
@@ -0,0 +1,26 @@
+! { dg-do run }
+! { dg-options "-fcoarray=single" }
+!
+! Contributed by Ian Harvey  <ian_har...@bigpond.com>
+! Extended by Andre Vehreschild  <ve...@gcc.gnu.org>
+! to test that coarray references in allocate work now
+! PR fortran/67451
+
+  program main
+    implicit none
+    type foo
+      integer :: bar = 99
+    end type
+    class(foo), allocatable :: foobar[:]
+    class(foo), allocatable :: some_local_object
+    allocate(foobar[*])
+
+    allocate(some_local_object, source=foobar)
+
+    if (.not. allocated(foobar)) call abort()
+    if (.not. allocated(some_local_object)) call abort()
+
+    deallocate(some_local_object)
+    deallocate(foobar)
+  end program
+
diff --git a/gcc/testsuite/gfortran.dg/coarray_allocate_3.f08 b/gcc/testsuite/gfortran.dg/coarray_allocate_3.f08
new file mode 100644
index 0000000..b9413b6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_allocate_3.f08
@@ -0,0 +1,28 @@
+! { dg-do run }
+! { dg-options "-fcoarray=single" }
+!
+! Contributed by Ian Harvey  <ian_har...@bigpond.com>
+! Extended by Andre Vehreschild  <ve...@gcc.gnu.org>
+! to test that coarray references in allocate work now
+! PR fortran/67451
+
+  program main
+    implicit none
+    type foo
+      integer :: bar = 99
+    end type
+    class(foo), dimension(:), allocatable :: foobar[:]
+    class(foo), dimension(:), allocatable :: some_local_object
+    allocate(foobar(10)[*])
+
+    allocate(some_local_object(10), source=foobar)
+
+    if (.not. allocated(foobar)) call abort()
+    if (lbound(foobar, 1) /= 1 .OR. ubound(foobar, 1) /= 10) call abort()
+    if (.not. allocated(some_local_object)) call abort()
+    if (any(some_local_object(:)%bar /= [99, 99,  99, 99, 99, 99, 99, 99, 99, 99])) call abort()
+
+    deallocate(some_local_object)
+    deallocate(foobar)
+  end program
+
diff --git a/gcc/testsuite/gfortran.dg/coarray_allocate_4.f08 b/gcc/testsuite/gfortran.dg/coarray_allocate_4.f08
new file mode 100644
index 0000000..a36d796
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_allocate_4.f08
@@ -0,0 +1,43 @@
+! { dg-do run }
+! { dg-options "-fcoarray=single" }
+!
+! Contributed by Gerhard Steinmetz  <gerhard.steinmetz.fort...@t-online.de>
+!               Andre Vehreschild <ve...@gcc.gnu.org>
+! Check that PR fortran/69451 is fixed.
+
+program main
+
+implicit none
+
+type foo
+end type
+
+class(foo), allocatable :: p[:]
+class(foo), pointer :: r
+class(*), allocatable, target :: z
+
+allocate(p[*])
+
+call s(p, z)
+select type (z)
+  class is (foo) 
+        r => z
+  class default
+     call abort()
+end select
+
+if (.not. associated(r)) call abort()
+
+deallocate(r)
+deallocate(p)
+
+contains
+
+subroutine s(x, z) 
+   class(*) :: x[*]
+   class(*), allocatable:: z
+   allocate (z, source=x)
+end
+
+end
+
gcc/testsuite/ChangeLog:

2016-02-01  Andre Vehreschild  <ve...@gcc.gnu.org>

        PR fortran/67451
        PR fortran/69418
        * gfortran.dg/coarray_allocate_2.f08: New test.
        * gfortran.dg/coarray_allocate_3.f08: New test.
        * gfortran.dg/coarray_allocate_4.f08: New test.


gcc/fortran/ChangeLog:

2016-02-01  Andre Vehreschild  <ve...@gcc.gnu.org>

        PR fortran/67451
        PR fortran/69418
        * trans-expr.c (gfc_copy_class_to_class): For coarrays just the
        pointer is passed.  Take it as is without trying to deref the
        _data component.
        * trans-stmt.c (gfc_trans_allocate): Take care of coarrays as
        argument to source=-expression.

Reply via email to