Hi,

this is the failure of a couple of tests in the gnat.dg testsuite on 32-bit 
platforms (but on some hosts only):

FAIL: gnat.dg/loop_optimization3.adb (test for excess errors)
FAIL: gnat.dg/opt30.adb (test for excess errors)
FAIL: gnat.dg/opt49.adb (test for excess errors)

caused by a segfault in native_encode_initializer when it is encoding the 
CONSTRUCTOR for an array whose lower bound is negative (it's OK in Ada).
The computation of the current position is done in HOST_WIDE_INT and this does 
not work for arrays whose original range has a negative lower bound and a 
positive upper bound; the computation must be done in sizetype instead so that 
it may wrap around, like in get_inner_reference or get_ref_base_and_extent.

Tested on x86-64/Linux, OK for the mainline and 10 branch?


2021-03-18  Eric Botcazou  <ebotca...@adacore.com>

        PR middle-end/99641
        * fold-const.c (native_encode_initializer) <CONSTRUCTOR>: For an
        array type, do the computation of the current position in sizetype.

-- 
Eric Botcazou
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index e0bdb4b6ba6..55652819d71 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -8051,21 +8051,20 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
       int o = off == -1 ? 0 : off;
       if (TREE_CODE (type) == ARRAY_TYPE)
 	{
-	  HOST_WIDE_INT min_index;
+	  tree min_index;
 	  unsigned HOST_WIDE_INT cnt;
 	  HOST_WIDE_INT curpos = 0, fieldsize, valueinit = -1;
 	  constructor_elt *ce;
 
-	  if (TYPE_DOMAIN (type) == NULL_TREE
-	      || !tree_fits_shwi_p (TYPE_MIN_VALUE (TYPE_DOMAIN (type))))
+	  if (!TYPE_DOMAIN (type))
 	    return 0;
+	  min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
 
 	  fieldsize = int_size_in_bytes (TREE_TYPE (type));
 	  if (fieldsize <= 0)
 	    return 0;
 
-	  min_index = tree_to_shwi (TYPE_MIN_VALUE (TYPE_DOMAIN (type)));
-	  if (ptr != NULL)
+	  if (ptr)
 	    memset (ptr, '\0', MIN (total_bytes - off, len));
 
 	  for (cnt = 0; ; cnt++)
@@ -8084,21 +8083,35 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
 		break;
 	      else
 		pos = total_bytes;
+
 	      if (index && TREE_CODE (index) == RANGE_EXPR)
 		{
-		  if (!tree_fits_shwi_p (TREE_OPERAND (index, 0))
-		      || !tree_fits_shwi_p (TREE_OPERAND (index, 1)))
+		  tree pos_diff
+		    = fold_convert (sizetype,
+				    fold_build2 (MINUS_EXPR, TREE_TYPE (index),
+						 TREE_OPERAND (index, 0),
+						 min_index));
+		  if (!tree_fits_shwi_p (pos_diff))
+		    return 0;
+		  pos = tree_to_shwi (pos_diff) * fieldsize;
+		  tree count_diff
+		    = fold_convert (sizetype,
+				    fold_build2 (MINUS_EXPR, TREE_TYPE (index),
+						 TREE_OPERAND (index, 1),
+						 TREE_OPERAND (index, 0)));
+		  if (!tree_fits_shwi_p (count_diff))
 		    return 0;
-		  pos = (tree_to_shwi (TREE_OPERAND (index, 0)) - min_index)
-			* fieldsize;
-		  count = (tree_to_shwi (TREE_OPERAND (index, 1))
-			   - tree_to_shwi (TREE_OPERAND (index, 0)));
+		  count = tree_to_shwi (count_diff);
 		}
 	      else if (index)
 		{
-		  if (!tree_fits_shwi_p (index))
+		  tree pos_diff
+		    = fold_convert (sizetype,
+				    fold_build2 (MINUS_EXPR, TREE_TYPE (index),
+						 index, min_index));
+		  if (!tree_fits_shwi_p (pos_diff))
 		    return 0;
-		  pos = (tree_to_shwi (index) - min_index) * fieldsize;
+		  pos = tree_to_shwi (pos_diff) * fieldsize;
 		}
 
 	      if (mask && !CONSTRUCTOR_NO_CLEARING (init) && curpos != pos)

Reply via email to