This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[libgfortran,patch] Fix RESHAPE for zero-sized array sections


Hi all,

Attached patch makes RESHAPE behaves correctly on zero-sized array
sections (PR 27895). I don't know why I didn't spot it last time I
looked, as it's really easy: at the start of the routine, when
counting dimensions and extents, you simply use flags to mark if
either source or pad arrays are zero-sized (the flags are named
sempty, pempty). Then, before the main loop, you take the appropriate
action.

This patch fixes an embarassing wrong-code bug, as wrong-code always
are. Regtested on i686-linux (well, on a revision before the bootstrap
breakage :)   OK for mainline, 4.2 and 4.1?

FX

:ADDPATCH libgfortran:

Attachment: reshape_zerosized.ChangeLog
Description: Binary data

Index: libgfortran/m4/reshape.m4
===================================================================
--- libgfortran/m4/reshape.m4	(revision 118156)
+++ libgfortran/m4/reshape.m4	(working copy)
@@ -38,9 +38,9 @@
 
 typedef GFC_ARRAY_DESCRIPTOR(1, index_type) shape_type;
 
-/* The shape parameter is ignored. We can currently deduce the shape from the
-   return array.  */
-dnl Only the kind (ie size) is used to name the function.
+dnl For integer routines, only the kind (ie size) is used to name the
+dnl function.  The same function will be used for integer and logical
+dnl arrays of the same kind.
 
 extern void reshape_`'rtype_ccode (rtype * const restrict, 
 	rtype * const restrict, 
@@ -85,12 +85,13 @@
   const rtype_name *src;
   int n;
   int dim;
+  int sempty, pempty;
 
   if (ret->data == NULL)
     {
       rdim = shape->dim[0].ubound - shape->dim[0].lbound + 1;
       rs = 1;
-      for (n=0; n < rdim; n++)
+      for (n = 0; n < rdim; n++)
 	{
 	  ret->dim[n].lbound = 0;
 	  rex = shape->data[n * shape->dim[0].stride];
@@ -132,13 +133,17 @@
 
   sdim = GFC_DESCRIPTOR_RANK (source);
   ssize = 1;
+  sempty = 0;
   for (n = 0; n < sdim; n++)
     {
       scount[n] = 0;
       sstride[n] = source->dim[n].stride;
       sextent[n] = source->dim[n].ubound + 1 - source->dim[n].lbound;
       if (sextent[n] <= 0)
-        abort ();
+	{
+	  sempty = 1;
+	  sextent[n] = 0;
+	}
 
       if (ssize == sstride[n])
         ssize *= sextent[n];
@@ -150,13 +155,18 @@
     {
       pdim = GFC_DESCRIPTOR_RANK (pad);
       psize = 1;
+      pempty = 0;
       for (n = 0; n < pdim; n++)
         {
           pcount[n] = 0;
           pstride[n] = pad->dim[n].stride;
           pextent[n] = pad->dim[n].ubound + 1 - pad->dim[n].lbound;
           if (pextent[n] <= 0)
-            abort ();
+	    {
+	      pempty = 1;
+	      pextent[n] = 0;
+	    }
+
           if (psize == pstride[n])
             psize *= pextent[n];
           else
@@ -168,6 +178,7 @@
     {
       pdim = 0;
       psize = 1;
+      pempty = 1;
       pptr = NULL;
     }
 
@@ -185,6 +196,24 @@
   rstride0 = rstride[0];
   sstride0 = sstride[0];
 
+  if (sempty && pempty)
+    abort ();
+
+  if (sempty)
+    {
+      /* Switch immediately to the pad array.  */
+      src = pptr;
+      sptr = NULL;
+      sdim = pdim;
+      for (dim = 0; dim < pdim; dim++)
+	{
+	  scount[dim] = pcount[dim];
+	  sextent[dim] = pextent[dim];
+	  sstride[dim] = pstride[dim];
+	  sstride0 = sstride[0] * sizeof (rtype_name);
+	}
+    }
+
   while (rptr)
     {
       /* Select between the source and pad arrays.  */
@@ -194,6 +223,7 @@
       src += sstride0;
       rcount[0]++;
       scount[0]++;
+
       /* Advance to the next destination element.  */
       n = 0;
       while (rcount[n] == rextent[n])
Index: libgfortran/intrinsics/reshape_generic.c
===================================================================
--- libgfortran/intrinsics/reshape_generic.c	(revision 118156)
+++ libgfortran/intrinsics/reshape_generic.c	(working copy)
@@ -37,9 +37,6 @@
 typedef GFC_ARRAY_DESCRIPTOR(1, index_type) shape_type;
 typedef GFC_ARRAY_DESCRIPTOR(GFC_MAX_DIMENSIONS, char) parray;
 
-/* The shape parameter is ignored. We can currently deduce the shape from the
-   return array.  */
-
 static void
 reshape_internal (parray *ret, parray *source, shape_type *shape,
 		  parray *pad, shape_type *order, index_type size)
@@ -73,12 +70,13 @@
   const char *src;
   int n;
   int dim;
+  int sempty, pempty;
 
   if (ret->data == NULL)
     {
       rdim = shape->dim[0].ubound - shape->dim[0].lbound + 1;
       rs = 1;
-      for (n=0; n < rdim; n++)
+      for (n = 0; n < rdim; n++)
 	{
 	  ret->dim[n].lbound = 0;
 	  rex = shape->data[n * shape->dim[0].stride];
@@ -120,13 +118,17 @@
 
   sdim = GFC_DESCRIPTOR_RANK (source);
   ssize = 1;
+  sempty = 0;
   for (n = 0; n < sdim; n++)
     {
       scount[n] = 0;
       sstride[n] = source->dim[n].stride;
       sextent[n] = source->dim[n].ubound + 1 - source->dim[n].lbound;
       if (sextent[n] <= 0)
-        abort ();
+	{
+	  sempty = 1;
+	  sextent[n] = 0;
+	}
 
       if (ssize == sstride[n])
         ssize *= sextent[n];
@@ -138,13 +140,18 @@
     {
       pdim = GFC_DESCRIPTOR_RANK (pad);
       psize = 1;
+      pempty = 0;
       for (n = 0; n < pdim; n++)
         {
           pcount[n] = 0;
           pstride[n] = pad->dim[n].stride;
           pextent[n] = pad->dim[n].ubound + 1 - pad->dim[n].lbound;
           if (pextent[n] <= 0)
-            abort ();
+	    {
+	      pempty = 1;
+              pextent[n] = 0;
+	    }
+
           if (psize == pstride[n])
             psize *= pextent[n];
           else
@@ -156,6 +163,7 @@
     {
       pdim = 0;
       psize = 1;
+      pempty = 1;
       pptr = NULL;
     }
 
@@ -173,6 +181,24 @@
   rstride0 = rstride[0] * size;
   sstride0 = sstride[0] * size;
 
+  if (sempty && pempty)
+    abort ();
+
+  if (sempty)
+    {
+      /* Switch immediately to the pad array.  */
+      src = pptr;
+      sptr = NULL;
+      sdim = pdim;
+      for (dim = 0; dim < pdim; dim++)
+	{
+	  scount[dim] = pcount[dim];
+	  sextent[dim] = pextent[dim];
+	  sstride[dim] = pstride[dim];
+	  sstride0 = sstride[0] * size;
+	}
+    }
+
   while (rptr)
     {
       /* Select between the source and pad arrays.  */
@@ -182,6 +208,7 @@
       src += sstride0;
       rcount[0]++;
       scount[0]++;
+
       /* Advance to the next destination element.  */
       n = 0;
       while (rcount[n] == rextent[n])
@@ -204,7 +231,8 @@
               rcount[n]++;
               rptr += rstride[n] * size;
             }
-        }
+	}
+
       /* Advance to the next source element.  */
       n = 0;
       while (scount[n] == sextent[n])
Index: gcc/testsuite/gfortran.dg/zero_sized_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/zero_sized_1.f90	(revision 118151)
+++ gcc/testsuite/gfortran.dg/zero_sized_1.f90	(working copy)
@@ -193,5 +193,5 @@
   call test_unpack
   call test_spread
   call test_pack
-!  call test_reshape
+  call test_reshape
 end

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]