Rev. 269177 uncovered a latent issue in TRANSFER when the MOLD argument
had storage size 0, resulting in an infinite loop.  The attached patch
rejects illegal cases and handles the case where storage size of both
SOURCE and MOLD are 0.  It also verifies proper simplification for
some cases, some of which were not always properly handled before.

Thanks to Dominique for the heads-up which I initially missed.

Regtested on x86_64-pc-linux-gnu; the testcase is based on the report
and slightly extended.

OK for trunk?

Thanks, and sorry for any inconvenience caused,
Harald

2019-02-25  Harald Anlauf  <anl...@gmx.de>

        PR fortran/89492
        * check.c (gfc_calculate_transfer_sizes): Handle cases where
        storage size of elements of MOLD is 0.

2019-02-25  Harald Anlauf  <anl...@gmx.de>

        PR fortran/89492
        * gfortran.dg/pr89492.f90: New test.

Index: gcc/fortran/check.c
===================================================================
--- gcc/fortran/check.c (revision 269177)
+++ gcc/fortran/check.c (working copy)
@@ -5487,6 +5487,26 @@
   if (!gfc_element_size (mold, &result_elt_size))
     return false;
 
+  if (result_elt_size == 0 && *source_size > 0)
+    {
+      gfc_error ("%<MOLD%> argument of %<TRANSFER%> intrinsic at %L "
+                 "shall not have storage size 0 when %<SOURCE%> "
+                "argument has size greater than 0", &mold->where);
+      return false;
+    }
+
+  /* If MOLD is a scalar and SIZE is absent, the result is a scalar.
+   * If MOLD is an array and SIZE is absent, the result is an array and of
+   * rank one. Its size is as small as possible such that its physical
+   * representation is not shorter than that of SOURCE.
+   */
+  if (result_elt_size == 0 && *source_size == 0 && !size)
+    {
+      *result_size = 0;
+      *result_length_p = 0;
+      return true;
+    }
+
   if ((result_elt_size > 0 && (mold->expr_type == EXPR_ARRAY || mold->rank))
       || size)
     {
Index: gcc/testsuite/gfortran.dg/pr89492.f90
===================================================================
--- gcc/testsuite/gfortran.dg/pr89492.f90       (nonexistent)
+++ gcc/testsuite/gfortran.dg/pr89492.f90       (working copy)
@@ -0,0 +1,27 @@
+! { dg-do compile }
+!
+! PR fortran/89492 - Endless compilation of an invalid TRANSFER after r269177
+! Test error recovery for invalid uses of TRANSFER
+! Test proper simplification for MOLD with size 0
+!
+! Derived from original testcase by Dominique d'Humieres
+
+program bug4a
+  implicit none
+  type bug4
+! Intentionally left empty
+  end type bug4
+  integer, parameter :: k = size(transfer('',['']))  ! k = 0
+  integer, parameter :: i = len (transfer('',['']))  ! i = 0
+  integer, parameter :: l = len (transfer('', '' ))  ! l = 0
+  integer, parameter :: m(k) = k
+  integer, parameter :: j(i) = i
+  integer, parameter :: n(l) = l
+  print *, k,i,l,m,j,n
+  print *,      transfer(1,[''])                ! { dg-error "shall not have 
storage size 0" }
+  print *,      transfer(1, '' )                ! { dg-error "shall not have 
storage size 0" }
+  print *, size(transfer(1,['']))               ! { dg-error "shall not have 
storage size 0" }
+  print *, len (transfer(1, '' ))               ! { dg-error "shall not have 
storage size 0" }
+  print *, size(transfer([1],[bug4()]))         ! { dg-error "shall not have 
storage size 0" }
+  print *, transfer(transfer([1],[bug4()]),[1]) ! { dg-error "shall not have 
storage size 0" }
+end program bug4a

Reply via email to