]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
expr.c (get_inner_reference): Do computation of bitoffset from offset in a way we...
authorRichard Guenther <rguenther@suse.de>
Fri, 24 Aug 2007 11:22:44 +0000 (11:22 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 24 Aug 2007 11:22:44 +0000 (11:22 +0000)
2007-08-23  Richard Guenther  <rguenther@suse.de>

* expr.c (get_inner_reference): Do computation of bitoffset
from offset in a way we can detect overflow reliably.

From-SVN: r127767

gcc/ChangeLog
gcc/expr.c

index 437088c7d10cc3e492de4f41ce81ece1187958d5..acafeb67802ad75537d667c1b5a4accca08183c5 100644 (file)
@@ -1,3 +1,8 @@
+2007-08-24  Richard Guenther  <rguenther@suse.de>
+
+       * expr.c (get_inner_reference): Do computation of bitoffset
+       from offset in a way we can detect overflow reliably.
+
 2007-08-22  Richard Guenther  <rguenther@suse.de>
 
        PR middle-end/32563
index 97c8460b856aa972dd14e26c1146c0ada87a215a..4d62318b5e237a891cc6664888daa5c3f640e80c 100644 (file)
@@ -5690,6 +5690,8 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
        *pbitsize = tree_low_cst (size_tree, 1);
     }
 
+  *pmode = mode;
+
   /* Compute cumulative bit-offset for nested component-refs and array-refs,
      and find the ultimate containing object.  */
   while (1)
@@ -5774,18 +5776,25 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
  done:
 
   /* If OFFSET is constant, see if we can return the whole thing as a
-     constant bit position.  Otherwise, split it up.  */
-  if (host_integerp (offset, 0)
-      && 0 != (tem = size_binop (MULT_EXPR,
-                                fold_convert (bitsizetype, offset),
-                                bitsize_unit_node))
-      && 0 != (tem = size_binop (PLUS_EXPR, tem, bit_offset))
-      && host_integerp (tem, 0))
-    *pbitpos = tree_low_cst (tem, 0), *poffset = 0;
-  else
-    *pbitpos = tree_low_cst (bit_offset, 0), *poffset = offset;
+     constant bit position.  Make sure to handle overflow during
+     this conversion.  */
+  if (host_integerp (offset, 0))
+    {
+      double_int tem = double_int_mul (tree_to_double_int (offset),
+                                      uhwi_to_double_int (BITS_PER_UNIT));
+      tem = double_int_add (tem, tree_to_double_int (bit_offset));
+      if (double_int_fits_in_shwi_p (tem))
+       {
+         *pbitpos = double_int_to_shwi (tem);
+         *poffset = NULL_TREE;
+         return exp;
+       }
+    }
+
+  /* Otherwise, split it up.  */
+  *pbitpos = tree_low_cst (bit_offset, 0);
+  *poffset = offset;
 
-  *pmode = mode;
   return exp;
 }