From 16e247566db1df18a63965f8b3da7345459c6296 Mon Sep 17 00:00:00 2001
From: Paul Thomas <pault@gcc.gnu.org>
Date: Mon, 4 Feb 2013 22:33:15 +0000
Subject: [PATCH] re PR fortran/56008 ([F03] wrong code with lhs-realloc on
 assignment with derived types having allocatable components)

2013-02-04  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/56008
	PR fortran/47517
	* trans-array.c (gfc_alloc_allocatable_for_assignment): Save
	the lhs descriptor before it is modified for reallocation. Use
	it to deallocate allocatable components in the reallocation
	block.  Nullify allocatable components for newly (re)allocated
	arrays.

2013-02-04  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/56008
	* gfortran.dg/realloc_on _assign_16.f90 : New test.

	PR fortran/47517
	* gfortran.dg/realloc_on _assign_17.f90 : New test.

From-SVN: r195741
---
 gcc/fortran/ChangeLog                         | 10 ++++
 gcc/fortran/trans-array.c                     | 33 +++++++++++++
 gcc/testsuite/ChangeLog                       |  8 ++++
 .../gfortran.dg/realloc_on_assign_16.f90      | 28 +++++++++++
 .../gfortran.dg/realloc_on_assign_17.f90      | 47 +++++++++++++++++++
 5 files changed, 126 insertions(+)
 create mode 100644 gcc/testsuite/gfortran.dg/realloc_on_assign_16.f90
 create mode 100644 gcc/testsuite/gfortran.dg/realloc_on_assign_17.f90

diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 50d7538f9c3f..c22d3d9908f2 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,13 @@
+2013-02-04  Paul Thomas  <pault@gcc.gnu.org>
+
+	PR fortran/56008
+	PR fortran/47517
+	* trans-array.c (gfc_alloc_allocatable_for_assignment): Save
+	the lhs descriptor before it is modified for reallocation. Use
+	it to deallocate allocatable components in the reallocation
+	block.  Nullify allocatable components for newly (re)allocated
+	arrays.
+
 2013-02-04  Mikael Morin  <mikael@gcc.gnu.org>
 
 	PR fortran/54195
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 3e658c0dd338..4553ddc5b537 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -7941,6 +7941,7 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
   tree lbound;
   tree ubound;
   tree desc;
+  tree old_desc;
   tree desc2;
   tree offset;
   tree jump_label1;
@@ -8091,6 +8092,13 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
 			  size1, size2);
   neq_size = gfc_evaluate_now (cond, &fblock);
 
+  /* Deallocation of allocatable components will have to occur on
+     reallocation.  Fix the old descriptor now.  */
+  if ((expr1->ts.type == BT_DERIVED)
+	&& expr1->ts.u.derived->attr.alloc_comp)
+    old_desc = gfc_evaluate_now (desc, &fblock);
+  else
+    old_desc = NULL_TREE;
 
   /* Now modify the lhs descriptor and the associated scalarizer
      variables. F2003 7.4.1.3: "If variable is or becomes an
@@ -8201,12 +8209,30 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
   /* Realloc expression.  Note that the scalarizer uses desc.data
      in the array reference - (*desc.data)[<element>]. */
   gfc_init_block (&realloc_block);
+
+  if ((expr1->ts.type == BT_DERIVED)
+	&& expr1->ts.u.derived->attr.alloc_comp)
+    {
+      tmp = gfc_deallocate_alloc_comp (expr1->ts.u.derived, old_desc,
+				       expr1->rank);
+      gfc_add_expr_to_block (&realloc_block, tmp);
+    }
+
   tmp = build_call_expr_loc (input_location,
 			     builtin_decl_explicit (BUILT_IN_REALLOC), 2,
 			     fold_convert (pvoid_type_node, array1),
 			     size2);
   gfc_conv_descriptor_data_set (&realloc_block,
 				desc, tmp);
+
+  if ((expr1->ts.type == BT_DERIVED)
+	&& expr1->ts.u.derived->attr.alloc_comp)
+    {
+      tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, desc,
+				    expr1->rank);
+      gfc_add_expr_to_block (&realloc_block, tmp);
+    }
+
   realloc_expr = gfc_finish_block (&realloc_block);
 
   /* Only reallocate if sizes are different.  */
@@ -8224,6 +8250,13 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
 				desc, tmp);
   tmp = gfc_conv_descriptor_dtype (desc);
   gfc_add_modify (&alloc_block, tmp, gfc_get_dtype (TREE_TYPE (desc)));
+  if ((expr1->ts.type == BT_DERIVED)
+	&& expr1->ts.u.derived->attr.alloc_comp)
+    {
+      tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, desc,
+				    expr1->rank);
+      gfc_add_expr_to_block (&alloc_block, tmp);
+    }
   alloc_expr = gfc_finish_block (&alloc_block);
 
   /* Malloc if not allocated; realloc otherwise.  */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e6bea3f830fb..548ccc12e642 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2013-02-04  Paul Thomas  <pault@gcc.gnu.org>
+
+	PR fortran/56008
+	* gfortran.dg/realloc_on _assign_16.f90 : New test.
+
+	PR fortran/47517
+	* gfortran.dg/realloc_on _assign_17.f90 : New test.
+
 2013-02-04  Alexander Potapenko <glider@google.com>
             Jack Howarth  <howarth@bromo.med.uc.edu>
 	    Jakub Jelinek  <jakub@redhat.com>
diff --git a/gcc/testsuite/gfortran.dg/realloc_on_assign_16.f90 b/gcc/testsuite/gfortran.dg/realloc_on_assign_16.f90
new file mode 100644
index 000000000000..84af6670f66d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/realloc_on_assign_16.f90
@@ -0,0 +1,28 @@
+! { dg-do run }
+! Test the fix for PR56008
+!
+! Contributed by Stefan Mauerberger  <stefan.mauerberger@gmail.com>
+!
+PROGRAM main
+    !USE MPI
+
+    TYPE :: test_typ
+        REAL, ALLOCATABLE :: a(:)
+    END TYPE
+
+    TYPE(test_typ) :: xx, yy
+    TYPE(test_typ), ALLOCATABLE :: conc(:)
+
+    !CALL MPI_INIT(i)
+
+    xx = test_typ( [1.0,2.0] )
+    yy = test_typ( [4.0,4.9] )
+
+    conc = [ xx, yy ]
+
+    if (any (int (10.0*conc(1)%a) .ne. [10,20])) call abort
+    if (any (int (10.0*conc(2)%a) .ne. [40,49])) call abort
+
+    !CALL MPI_FINALIZE(i)
+
+END PROGRAM main
diff --git a/gcc/testsuite/gfortran.dg/realloc_on_assign_17.f90 b/gcc/testsuite/gfortran.dg/realloc_on_assign_17.f90
new file mode 100644
index 000000000000..61b1e91d6419
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/realloc_on_assign_17.f90
@@ -0,0 +1,47 @@
+! { dg-do run }
+! Test the fix for PR47517
+!
+! Reported by Tobias Burnus  <burnus@gcc.gnu.org>
+! from a testcase by James Van Buskirk
+module mytypes
+   implicit none
+   type label
+      integer, allocatable :: parts(:)
+   end type label
+   type table
+      type(label), allocatable :: headers(:)
+   end type table
+end module mytypes
+
+program allocate_assign
+   use mytypes
+   implicit none
+   integer, parameter :: ik8 = selected_int_kind(18)
+   type(table) x1(2)
+   type(table) x2(3)
+   type(table), allocatable :: x(:)
+   integer i, j, k
+   integer(ik8) s
+   call foo
+   s = 0
+   do k = 1, 10000
+      x = x1
+      s = s+x(2)%headers(2)%parts(2)
+      x = x2
+      s = s+x(2)%headers(2)%parts(2)
+   end do
+   if (s .ne. 40000) call abort
+contains
+!
+! TODO - these assignments lose 1872 bytes on x86_64/FC17
+! This is PR38319
+!
+   subroutine foo
+       x1 = [table([(label([(j,j=1,3)]),i=1,3)]), &
+             table([(label([(j,j=1,4)]),i=1,4)])]
+
+       x2 = [table([(label([(j,j=1,4)]),i=1,4)]), &
+             table([(label([(j,j=1,5)]),i=1,5)]), &
+             table([(label([(j,j=1,6)]),i=1,6)])]
+   end subroutine
+end program allocate_assign
-- 
GitLab