fortran: [PR125535] wrong-code for implied-do with allocatable-component

When a nested implied-do array constructor called a transformational
intrinsic (e.g. RESHAPE) whose result type has allocatable components, the
argument temporaries were freed before the result's allocatable components
were deep-copied, causing a heap-use-after-free and wrong runtime values.

Transformational library functions such as RESHAPE do a shallow byte-copy
of the source array into the result, so the result's component pointers
alias those of the argument temporaries. Freeing the temporaries first
and then copying yielded use-after-free.

Move gfc_add_block_to_block (&se->pre, &post) to after the deep-copy
loop, so that the result's allocatable components are copied while the
source storage is still live.

Assisted by: Claude Sonnet 4.6

	PR fortran/125535

gcc/fortran/ChangeLog:

	* trans-expr.cc (gfc_conv_procedure_call): Move post block append
	to after the deep copy of allocatable components for transformational
	intrinsics, so that argument temporaries are not freed before the
	result components are copied.

gcc/testsuite/ChangeLog:

	* gfortran.dg/implied_do_alloc_comp_1.f90: New test.
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index c808c1b..00925f2 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -9069,12 +9069,10 @@
   /* Follow the function call with the argument post block.  */
   if (byref)
     {
-      gfc_add_block_to_block (&se->pre, &post);
-
       /* Transformational functions of derived types with allocatable
-	 components must have the result allocatable components copied when the
-	 argument is actually given.  This is unnecessry for REDUCE because the
-	 wrapper for the OPERATION function takes care of this.  */
+	 components must have the result allocatable components copied
+	 BEFORE the argument post block is appended.  Copying the result
+	 first, then freeing the argument, gives the correct order.  */
       arg = expr->value.function.actual;
       if (result && arg && expr->rank
 	  && isym && isym->transformational
@@ -9102,6 +9100,8 @@
 					    NULL, GFC_CAF_COARRAY_NOCOARRAY);
 	  gfc_add_expr_to_block (&se->pre, tmp);
 	}
+
+      gfc_add_block_to_block (&se->pre, &post);
     }
   else
     {
diff --git a/gcc/testsuite/gfortran.dg/implied_do_alloc_comp_1.f90 b/gcc/testsuite/gfortran.dg/implied_do_alloc_comp_1.f90
new file mode 100644
index 0000000..8f0ae49
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/implied_do_alloc_comp_1.f90
@@ -0,0 +1,39 @@
+! { dg-do run }
+! Test that a nested implied-do array constructor with a derived-type
+! constructor whose argument uses an outer loop variable produces correct
+! results when the derived type has an allocatable component.
+!
+! PR fortran/125535
+
+module m
+  implicit none
+  type :: t
+    real, allocatable :: v(:)
+  end type
+contains
+  pure function make(x) result(r)
+    real, intent(in) :: x(:)
+    type(t) :: r
+    r%v = x
+  end function
+end module
+
+program implied_do_alloc_comp
+  use m
+  implicit none
+  integer, parameter :: n=3, k=2
+  type(t), allocatable :: a(:,:)
+  real :: h(k, n)
+  integer :: i, j
+
+  h(1,:) = [10., 20., 30.]
+  h(2,:) = [11., 21., 31.]
+
+  ! Nested implied-do where inner DT constructor uses outer variable i.
+  ! Without the fix this produces heap-use-after-free and wrong values.
+  a = reshape([([(make(h(:,i)), j=1,1)], i=1,n)], [1,n])
+
+  if (any(a(1,1)%v /= h(:,1))) stop 1
+  if (any(a(1,2)%v /= h(:,2))) stop 2
+  if (any(a(1,3)%v /= h(:,3))) stop 3
+end program