Hello world,

the patch below fixes a far-reaching wrong-code regression. Regression
tested.  OK for trunk and backport as far as possible?

(I particularly want to get this into gcc 13 while there still is time)

Best regards

        Thomas

PR fortran/115260 - fix data corruption on inline packing/unpacking

This patch fixes a data corruption occuring when a non-contiguous slice of an
allocatable array component was passed to a procedure expecting a g77-style
argument.  The problem was the inline packing (PR fortran/88821) which went
astray gfc_trans_scalar_assign was told to deallocate the argument upon
return.

The solution was to not pass that argument if passing a g77-style array,
in effect a one-liner.

This is a regression which goes back to all supported releases.

gcc/fortran/ChangeLog:

        PR fortran/115260
        * trans-expr.cc (gfc_conv_subref_array_arg): Pass false to
        dealloc argument of gfc_trans_scalar_assign if we are
        converting a g77-style argument.

gcc/testsuite/ChangeLog:

        PR fortran/115260
        * gfortran.dg/pr115260.f90: New test.
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 2f14e8c3f6c..5e4529e2a4a 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -5724,7 +5724,9 @@ gfc_conv_subref_array_arg (gfc_se *se, gfc_expr * expr, int g77,
 
   gcc_assert (lse.ss == gfc_ss_terminator);
 
-  tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, true);
+  /* Do not do deallocations when we are looking at a g77-style argument.  */
+
+  tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, !g77);
   gfc_add_expr_to_block (&body, tmp);
 
   /* Generate the copying loops.  */
diff --git a/gcc/testsuite/gfortran.dg/pr115260.f90 b/gcc/testsuite/gfortran.dg/pr115260.f90
new file mode 100644
index 00000000000..ee040f86658
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr115260.f90
@@ -0,0 +1,35 @@
+! { dg-do run }
+! PR 115260 - this got corrupted output.
+! Original test case by Steve Mullerworth
+
+program usegnufields
+  implicit none
+  type :: field_type
+    real,    allocatable :: data(:)
+    integer, allocatable :: idata(:)
+  end type field_type
+  type :: fieldholder
+    type(field_type) :: fieldset(2,4)
+  end type fieldholder
+  type(fieldholder) :: myfields
+
+  allocate(myfields%fieldset(2,1)%data(3))
+  allocate(myfields%fieldset(2,1)%idata(3))
+  myfields%fieldset(2,1)%data =1.0
+  myfields%fieldset(2,1)%idata=2
+
+  call setfields (myfields%fieldset(2,1:4))
+!  print *,'After calling setfields with fieldset(2,1:4)'
+!  print *,myfields%fieldset(2,1)%data
+!  print *,myfields%fieldset(2,1)%idata
+  if (any (myfields%fieldset(2,1)%data  /= 1.0)) stop 1
+  if (any (myfields%fieldset(2,1)%idata /= 2  )) stop 2
+
+contains
+  subroutine setfields (fieldset)
+    type(field_type), intent(inout) :: fieldset(1:4) ! corruption with -O
+!    print *,'In setfields:'
+!    print *,fieldset(1)%data
+!    print *,fieldset(1)%idata
+  end subroutine setfields
+end

Reply via email to