On Fri, 19 Aug 2011, Richard Guenther wrote:

> On Fri, 19 Aug 2011, Eric Botcazou wrote:
> 
> > > Looking at the Ada case I believe this happens because
> > > Ada has negative DECL_FIELD_OFFSET values (but that's
> > > again in sizetype, not ssizetype)?  Other host_integerp
> > > uses in Ada operate on sizes where I hope those are
> > > never negative ;)
> > 
> > Yes, the Ada compiler uses negative offsets for some peculiar constructs.
> > Nothing to do with the language per se, but with mechanisms implemented in 
> > gigi to support some features of the language.
> > 
> > > Eric, any better way of fixing this or would you be fine with this patch?
> > 
> > Hard to say without seeing the complete patch and playing a little with it.
> 
> This is the "complete" patch I am playing with currently, Ada bootstrap
> still fails for me unfortunately.  Bootstrap for all other languages
> succeeds, but there are some regressions, mostly warning-related.
> 
> Any help with pinpointing the Ada problem is welcome.

I have narrowed it down a bit.  Building Ada + libada unpatched,
patching the tree and then running the gnat.dg testsuite reveals

FAIL: gnat.dg/align_max.adb execution test
FAIL: gnat.dg/array11.adb  (test for warnings, line 12)
FAIL: gnat.dg/loop_optimization3.adb (test for excess errors)
WARNING: gnat.dg/loop_optimization3.adb compilation failed to produce 
executable
FAIL: gnat.dg/object_overflow.adb  (test for warnings, line 8)
FAIL: gnat.dg/thin_pointer2.adb execution test
FAIL: gnat.dg/unc_memfree.adb execution test

I just looked at gnat.dg/thin_pointer2.adb for now and we run into

utils2.c:build_simple_component_ref ()

  /* If the field's offset has overflowed, do not attempt to access it
     as doing so may trigger sanity checks deeper in the back-end.
     Note that we don't need to warn since this will be done on trying
     to declare the object.  */
  if (TREE_CODE (DECL_FIELD_OFFSET (field)) == INTEGER_CST
      && TREE_OVERFLOW (DECL_FIELD_OFFSET (field)))
    return NULL_TREE;

for fields with "negative" offset:

(gdb) call debug_tree (field)
 <field_decl 0x7ffff7ef7688 BOUNDS
    type <record_type 0x7ffff7f0f150 string___XUB readonly DI
        size <integer_cst 0x7ffff7ed3ec0 constant visited 64>
        unit size <integer_cst 0x7ffff7ed3ee0 constant visited 8>
        align 32 symtab 0 alias set -1 canonical type 0x7ffff7f0f150
        fields <field_decl 0x7ffff7ef7558 LB0 type <integer_type 
0x7ffff7ee35e8 integer>
            visited nonaddressable SI file <built-in> line 0 col 0
            size <integer_cst 0x7ffff7ee6200 constant visited 32>
            unit size <integer_cst 0x7ffff7ee6220 constant visited 4>
            align 32 offset_align 128
            offset <integer_cst 0x7ffff7ed3f00 constant visited 0>
            bit offset <integer_cst 0x7ffff7ed3f40 constant 0> context 
<record_type 0x7ffff7f0f150 string___XUB> chain <field_decl 0x7ffff7ef75f0 
UB0>> Ada size <integer_cst 0x7ffff7ed3ec0 64>
        pointer_to_this <pointer_type 0x7ffff7f0f1f8> chain <type_decl 
0x7ffff7ef48a0 string___XUB>>
    readonly DI file <built-in> line 0 col 0 size <integer_cst 
0x7ffff7ed3ec0 64> unit size <integer_cst 0x7ffff7ed3ee0 8>
    align 32 offset_align 128
    offset <integer_cst 0x7ffff7ee6e80 type <integer_type 0x7ffff7ee3000 
sizetype> constant public overflow 18446744073709551608> bit offset 
<integer_cst 0x7ffff7ed3f40 0> context <record_type 0x7ffff7f0fa80 
string___XUT> chain <field_decl 0x7ffff7ef7720 ARRAY>>

which is computed by shift_unc_components_for_thin_pointers doing

  DECL_FIELD_OFFSET (bounds_field)
    = size_binop (MINUS_EXPR, size_zero_node, byte_position (array_field));

which (at least) after my change to always make size_binop report
overflow (even for unsigned sizetype, to match what the code was
doing previously for sign_extended_types) results in 0 - 8
overflowing.

The above is probably not always an INTEGER_CST(?), but the following
should "fix" this particular issue.

Index: trunk/gcc/ada/gcc-interface/utils.c
===================================================================
--- trunk.orig/gcc/ada/gcc-interface/utils.c    2011-08-24 
16:06:21.000000000 +0200
+++ trunk/gcc/ada/gcc-interface/utils.c 2011-08-24 16:05:53.000000000 
+0200
@@ -3413,6 +3413,12 @@ shift_unc_components_for_thin_pointers (
 
   DECL_FIELD_OFFSET (bounds_field)
     = size_binop (MINUS_EXPR, size_zero_node, byte_position 
(array_field));
+  if (TREE_CODE (DECL_FIELD_OFFSET (bounds_field)) == INTEGER_CST
+      && TREE_OVERFLOW (DECL_FIELD_OFFSET (bounds_field)))
+    DECL_FIELD_OFFSET (bounds_field)
+      = build_int_cst_wide (sizetype,
+                           TREE_INT_CST_LOW (DECL_FIELD_OFFSET 
(bounds_field)),
+                           TREE_INT_CST_HIGH (DECL_FIELD_OFFSET 
(bounds_field)));
 
   DECL_FIELD_OFFSET (array_field) = size_zero_node;
   DECL_FIELD_BIT_OFFSET (array_field) = bitsize_zero_node;

Updated patch follows.  I hope the above makes me go past
building libada with the patch (maybe even bootstrapping ...).

ACATS fails w/o the above are (x86_64-linux)

                === acats tests ===
FAIL:   c36204d
FAIL:   c41107a
FAIL:   c43204a
FAIL:   c43204c
FAIL:   c43204e
FAIL:   c43204f
FAIL:   c43204g
FAIL:   c43204h
FAIL:   c43204i
FAIL:   c43205i
FAIL:   c52102a
FAIL:   c52102b
FAIL:   c52102c
FAIL:   c52102d
FAIL:   c95087a
FAIL:   cc1311a
FAIL:   cc3106b
FAIL:   cc3224a
FAIL:   cxh1001

Richard.

2011-06-16  Richard Guenther  <rguent...@suse.de>

        * fold-const.c (div_if_zero_remainder): sizetypes no longer
        sign-extend.
        * stor-layout.c (initialize_sizetypes): Likewise.
        * tree-ssa-ccp.c (bit_value_unop_1): Likewise.
        (bit_value_binop_1): Likewise.
        * tree.c (double_int_to_tree): Likewise.
        (double_int_fits_to_tree_p): Likewise.
        (force_fit_type_double): Likewise.
        (host_integerp): Likewise.
        (int_fits_type_p): Likewise.
        * tree-cfg.c (verify_types_in_gimple_reference): Do not compare
        sizes by pointer.

Index: trunk/gcc/fold-const.c
===================================================================
*** trunk.orig/gcc/fold-const.c 2011-08-24 15:34:13.000000000 +0200
--- trunk/gcc/fold-const.c      2011-08-24 15:36:22.000000000 +0200
*************** div_if_zero_remainder (enum tree_code co
*** 194,202 ****
       does the correct thing for POINTER_PLUS_EXPR where we want
       a signed division.  */
    uns = TYPE_UNSIGNED (TREE_TYPE (arg2));
-   if (TREE_CODE (TREE_TYPE (arg2)) == INTEGER_TYPE
-       && TYPE_IS_SIZETYPE (TREE_TYPE (arg2)))
-     uns = false;
  
    quo = double_int_divmod (tree_to_double_int (arg1),
                           tree_to_double_int (arg2),
--- 194,199 ----
*************** int_binop_types_match_p (enum tree_code
*** 938,945 ****
     to produce a new constant.  Return NULL_TREE if we don't know how
     to evaluate CODE at compile-time.  */
  
! tree
! int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2)
  {
    double_int op1, op2, res, tmp;
    tree t;
--- 935,943 ----
     to produce a new constant.  Return NULL_TREE if we don't know how
     to evaluate CODE at compile-time.  */
  
! static tree
! int_const_binop_1 (enum tree_code code, const_tree arg1, const_tree arg2,
!                  int overflowable)
  {
    double_int op1, op2, res, tmp;
    tree t;
*************** int_const_binop (enum tree_code code, co
*** 1081,1093 ****
        return NULL_TREE;
      }
  
!   t = force_fit_type_double (TREE_TYPE (arg1), res, 1,
                             ((!uns || is_sizetype) && overflow)
                             | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
  
    return t;
  }
  
  /* Combine two constants ARG1 and ARG2 under operation CODE to produce a new
     constant.  We assume ARG1 and ARG2 have the same data type, or at least
     are the same kind of constant and the same machine mode.  Return zero if
--- 1079,1097 ----
        return NULL_TREE;
      }
  
!   t = force_fit_type_double (TREE_TYPE (arg1), res, overflowable,
                             ((!uns || is_sizetype) && overflow)
                             | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
  
    return t;
  }
  
+ tree
+ int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2)
+ {
+   return int_const_binop_1 (code, arg1, arg2, 1);
+ }
+ 
  /* Combine two constants ARG1 and ARG2 under operation CODE to produce a new
     constant.  We assume ARG1 and ARG2 have the same data type, or at least
     are the same kind of constant and the same machine mode.  Return zero if
*************** size_binop_loc (location_t loc, enum tre
*** 1448,1455 ****
            return arg1;
        }
  
!       /* Handle general case of two integer constants.  */
!       return int_const_binop (code, arg0, arg1);
      }
  
    return fold_build2_loc (loc, code, type, arg0, arg1);
--- 1452,1461 ----
            return arg1;
        }
  
!       /* Handle general case of two integer constants.  For sizetype
!          constant calculations we always want to know about overflow,
!        even in the unsigned case.  */
!       return int_const_binop_1 (code, arg0, arg1, -1);
      }
  
    return fold_build2_loc (loc, code, type, arg0, arg1);
Index: trunk/gcc/stor-layout.c
===================================================================
*** trunk.orig/gcc/stor-layout.c        2011-08-24 15:34:13.000000000 +0200
--- trunk/gcc/stor-layout.c     2011-08-24 15:36:22.000000000 +0200
*************** initialize_sizetypes (void)
*** 2235,2245 ****
    TYPE_SIZE_UNIT (sizetype) = size_int (GET_MODE_SIZE (TYPE_MODE (sizetype)));
    set_min_and_max_values_for_integral_type (sizetype, precision,
                                            /*is_unsigned=*/true);
-   /* sizetype is unsigned but we need to fix TYPE_MAX_VALUE so that it is
-      sign-extended in a way consistent with force_fit_type.  */
-   TYPE_MAX_VALUE (sizetype)
-     = double_int_to_tree (sizetype,
-                         tree_to_double_int (TYPE_MAX_VALUE (sizetype)));
  
    SET_TYPE_MODE (bitsizetype, smallest_mode_for_size (bprecision, MODE_INT));
    TYPE_ALIGN (bitsizetype) = GET_MODE_ALIGNMENT (TYPE_MODE (bitsizetype));
--- 2235,2240 ----
*************** initialize_sizetypes (void)
*** 2248,2258 ****
      = size_int (GET_MODE_SIZE (TYPE_MODE (bitsizetype)));
    set_min_and_max_values_for_integral_type (bitsizetype, bprecision,
                                            /*is_unsigned=*/true);
-   /* bitsizetype is unsigned but we need to fix TYPE_MAX_VALUE so that it is
-      sign-extended in a way consistent with force_fit_type.  */
-   TYPE_MAX_VALUE (bitsizetype)
-     = double_int_to_tree (bitsizetype,
-                         tree_to_double_int (TYPE_MAX_VALUE (bitsizetype)));
  
    /* Create the signed variants of *sizetype.  */
    ssizetype = make_signed_type (TYPE_PRECISION (sizetype));
--- 2243,2248 ----
Index: trunk/gcc/tree-ssa-ccp.c
===================================================================
*** trunk.orig/gcc/tree-ssa-ccp.c       2011-08-24 15:34:13.000000000 +0200
--- trunk/gcc/tree-ssa-ccp.c    2011-08-24 15:36:22.000000000 +0200
*************** bit_value_unop_1 (enum tree_code code, t
*** 1099,1112 ****
        bool uns;
  
        /* First extend mask and value according to the original type.  */
!       uns = (TREE_CODE (rtype) == INTEGER_TYPE && TYPE_IS_SIZETYPE (rtype)
!              ? 0 : TYPE_UNSIGNED (rtype));
        *mask = double_int_ext (rmask, TYPE_PRECISION (rtype), uns);
        *val = double_int_ext (rval, TYPE_PRECISION (rtype), uns);
  
        /* Then extend mask and value according to the target type.  */
!       uns = (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type)
!              ? 0 : TYPE_UNSIGNED (type));
        *mask = double_int_ext (*mask, TYPE_PRECISION (type), uns);
        *val = double_int_ext (*val, TYPE_PRECISION (type), uns);
        break;
--- 1099,1110 ----
        bool uns;
  
        /* First extend mask and value according to the original type.  */
!       uns = TYPE_UNSIGNED (rtype);
        *mask = double_int_ext (rmask, TYPE_PRECISION (rtype), uns);
        *val = double_int_ext (rval, TYPE_PRECISION (rtype), uns);
  
        /* Then extend mask and value according to the target type.  */
!       uns = TYPE_UNSIGNED (type);
        *mask = double_int_ext (*mask, TYPE_PRECISION (type), uns);
        *val = double_int_ext (*val, TYPE_PRECISION (type), uns);
        break;
*************** bit_value_binop_1 (enum tree_code code,
*** 1128,1135 ****
                   tree r1type, double_int r1val, double_int r1mask,
                   tree r2type, double_int r2val, double_int r2mask)
  {
!   bool uns = (TREE_CODE (type) == INTEGER_TYPE
!             && TYPE_IS_SIZETYPE (type) ? 0 : TYPE_UNSIGNED (type));
    /* Assume we'll get a constant result.  Use an initial varying value,
       we fall back to varying in the end if necessary.  */
    *mask = double_int_minus_one;
--- 1126,1132 ----
                   tree r1type, double_int r1val, double_int r1mask,
                   tree r2type, double_int r2val, double_int r2mask)
  {
!   bool uns = TYPE_UNSIGNED (type);
    /* Assume we'll get a constant result.  Use an initial varying value,
       we fall back to varying in the end if necessary.  */
    *mask = double_int_minus_one;
*************** bit_value_binop_1 (enum tree_code code,
*** 1196,1208 ****
            }
          else if (shift < 0)
            {
-             /* ???  We can have sizetype related inconsistencies in
-                the IL.  */
-             if ((TREE_CODE (r1type) == INTEGER_TYPE
-                  && (TYPE_IS_SIZETYPE (r1type)
-                      ? 0 : TYPE_UNSIGNED (r1type))) != uns)
-               break;
- 
              shift = -shift;
              *mask = double_int_rshift (r1mask, shift,
                                         TYPE_PRECISION (type), !uns);
--- 1193,1198 ----
*************** bit_value_binop_1 (enum tree_code code,
*** 1314,1325 ****
          break;
  
        /* For comparisons the signedness is in the comparison operands.  */
!       uns = (TREE_CODE (r1type) == INTEGER_TYPE
!              && TYPE_IS_SIZETYPE (r1type) ? 0 : TYPE_UNSIGNED (r1type));
!       /* ???  We can have sizetype related inconsistencies in the IL.  */
!       if ((TREE_CODE (r2type) == INTEGER_TYPE
!            && TYPE_IS_SIZETYPE (r2type) ? 0 : TYPE_UNSIGNED (r2type)) != uns)
!         break;
  
        /* If we know the most significant bits we know the values
           value ranges by means of treating varying bits as zero
--- 1304,1310 ----
          break;
  
        /* For comparisons the signedness is in the comparison operands.  */
!       uns = TYPE_UNSIGNED (r1type);
  
        /* If we know the most significant bits we know the values
           value ranges by means of treating varying bits as zero
Index: trunk/gcc/tree.c
===================================================================
*** trunk.orig/gcc/tree.c       2011-08-24 15:34:13.000000000 +0200
--- trunk/gcc/tree.c    2011-08-24 15:36:22.000000000 +0200
*************** tree
*** 1059,1067 ****
  double_int_to_tree (tree type, double_int cst)
  {
    /* Size types *are* sign extended.  */
!   bool sign_extended_type = (!TYPE_UNSIGNED (type)
!                            || (TREE_CODE (type) == INTEGER_TYPE
!                                && TYPE_IS_SIZETYPE (type)));
  
    cst = double_int_ext (cst, TYPE_PRECISION (type), !sign_extended_type);
  
--- 1059,1065 ----
  double_int_to_tree (tree type, double_int cst)
  {
    /* Size types *are* sign extended.  */
!   bool sign_extended_type = !TYPE_UNSIGNED (type);
  
    cst = double_int_ext (cst, TYPE_PRECISION (type), !sign_extended_type);
  
*************** bool
*** 1075,1083 ****
  double_int_fits_to_tree_p (const_tree type, double_int cst)
  {
    /* Size types *are* sign extended.  */
!   bool sign_extended_type = (!TYPE_UNSIGNED (type)
!                            || (TREE_CODE (type) == INTEGER_TYPE
!                                && TYPE_IS_SIZETYPE (type)));
  
    double_int ext
      = double_int_ext (cst, TYPE_PRECISION (type), !sign_extended_type);
--- 1073,1079 ----
  double_int_fits_to_tree_p (const_tree type, double_int cst)
  {
    /* Size types *are* sign extended.  */
!   bool sign_extended_type = !TYPE_UNSIGNED (type);
  
    double_int ext
      = double_int_ext (cst, TYPE_PRECISION (type), !sign_extended_type);
*************** force_fit_type_double (tree type, double
*** 1107,1115 ****
    bool sign_extended_type;
  
    /* Size types *are* sign extended.  */
!   sign_extended_type = (!TYPE_UNSIGNED (type)
!                         || (TREE_CODE (type) == INTEGER_TYPE
!                             && TYPE_IS_SIZETYPE (type)));
  
    /* If we need to set overflow flags, return a new unshared node.  */
    if (overflowed || !double_int_fits_to_tree_p(type, cst))
--- 1103,1109 ----
    bool sign_extended_type;
  
    /* Size types *are* sign extended.  */
!   sign_extended_type = !TYPE_UNSIGNED (type);
  
    /* If we need to set overflow flags, return a new unshared node.  */
    if (overflowed || !double_int_fits_to_tree_p(type, cst))
*************** host_integerp (const_tree t, int pos)
*** 6496,6504 ****
               && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0)
              || (! pos && TREE_INT_CST_HIGH (t) == -1
                  && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0
!                 && (!TYPE_UNSIGNED (TREE_TYPE (t))
!                     || (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
!                         && TYPE_IS_SIZETYPE (TREE_TYPE (t)))))
              || (pos && TREE_INT_CST_HIGH (t) == 0)));
  }
  
--- 6490,6496 ----
               && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0)
              || (! pos && TREE_INT_CST_HIGH (t) == -1
                  && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0
!                 && !TYPE_UNSIGNED (TREE_TYPE (t)))
              || (pos && TREE_INT_CST_HIGH (t) == 0)));
  }
  
*************** int_fits_type_p (const_tree c, const_tre
*** 8190,8207 ****
    dc = tree_to_double_int (c);
    unsc = TYPE_UNSIGNED (TREE_TYPE (c));
  
-   if (TREE_CODE (TREE_TYPE (c)) == INTEGER_TYPE
-       && TYPE_IS_SIZETYPE (TREE_TYPE (c))
-       && unsc)
-     /* So c is an unsigned integer whose type is sizetype and type is not.
-        sizetype'd integers are sign extended even though they are
-        unsigned. If the integer value fits in the lower end word of c,
-        and if the higher end word has all its bits set to 1, that
-        means the higher end bits are set to 1 only for sign extension.
-        So let's convert c into an equivalent zero extended unsigned
-        integer.  */
-     dc = double_int_zext (dc, TYPE_PRECISION (TREE_TYPE (c)));
- 
  retry:
    type_low_bound = TYPE_MIN_VALUE (type);
    type_high_bound = TYPE_MAX_VALUE (type);
--- 8182,8187 ----
*************** retry:
*** 8220,8229 ****
    if (type_low_bound && TREE_CODE (type_low_bound) == INTEGER_CST)
      {
        dd = tree_to_double_int (type_low_bound);
-       if (TREE_CODE (type) == INTEGER_TYPE
-         && TYPE_IS_SIZETYPE (type)
-         && TYPE_UNSIGNED (type))
-       dd = double_int_zext (dd, TYPE_PRECISION (type));
        if (unsc != TYPE_UNSIGNED (TREE_TYPE (type_low_bound)))
        {
          int c_neg = (!unsc && double_int_negative_p (dc));
--- 8200,8205 ----
*************** retry:
*** 8245,8254 ****
    if (type_high_bound && TREE_CODE (type_high_bound) == INTEGER_CST)
      {
        dd = tree_to_double_int (type_high_bound);
-       if (TREE_CODE (type) == INTEGER_TYPE
-         && TYPE_IS_SIZETYPE (type)
-         && TYPE_UNSIGNED (type))
-       dd = double_int_zext (dd, TYPE_PRECISION (type));
        if (unsc != TYPE_UNSIGNED (TREE_TYPE (type_high_bound)))
        {
          int c_neg = (!unsc && double_int_negative_p (dc));
--- 8221,8226 ----
Index: trunk/gcc/ada/gcc-interface/utils.c
===================================================================
*** trunk.orig/gcc/ada/gcc-interface/utils.c    2011-08-24 15:34:13.000000000 
+0200
--- trunk/gcc/ada/gcc-interface/utils.c 2011-08-24 16:05:53.000000000 +0200
*************** rest_of_record_type_compilation (tree re
*** 948,954 ****
            pos = compute_related_constant (curpos, last_pos);
  
          if (!pos && TREE_CODE (curpos) == MULT_EXPR
!             && host_integerp (TREE_OPERAND (curpos, 1), 1))
            {
              tree offset = TREE_OPERAND (curpos, 0);
              align = tree_low_cst (TREE_OPERAND (curpos, 1), 1);
--- 948,955 ----
            pos = compute_related_constant (curpos, last_pos);
  
          if (!pos && TREE_CODE (curpos) == MULT_EXPR
!             && host_integerp (TREE_OPERAND (curpos, 1), 1)
!             && !tree_int_cst_sign_bit (TREE_OPERAND (curpos, 1)))
            {
              tree offset = TREE_OPERAND (curpos, 0);
              align = tree_low_cst (TREE_OPERAND (curpos, 1), 1);
*************** rest_of_record_type_compilation (tree re
*** 960,966 ****
              offset = remove_conversions (offset, true);
              if (TREE_CODE (offset) == BIT_AND_EXPR
                  && host_integerp (TREE_OPERAND (offset, 1), 0)
!                 && TREE_INT_CST_HIGH (TREE_OPERAND (offset, 1)) < 0)
                {
                  unsigned int pow
                    = - tree_low_cst (TREE_OPERAND (offset, 1), 0);
--- 961,967 ----
              offset = remove_conversions (offset, true);
              if (TREE_CODE (offset) == BIT_AND_EXPR
                  && host_integerp (TREE_OPERAND (offset, 1), 0)
!                 && tree_int_cst_sign_bit (TREE_OPERAND (offset, 1)))
                {
                  unsigned int pow
                    = - tree_low_cst (TREE_OPERAND (offset, 1), 0);
*************** rest_of_record_type_compilation (tree re
*** 975,982 ****
                   && TREE_CODE (TREE_OPERAND (curpos, 1)) == INTEGER_CST
                   && TREE_CODE (TREE_OPERAND (curpos, 0)) == MULT_EXPR
                   && host_integerp (TREE_OPERAND
!                                    (TREE_OPERAND (curpos, 0), 1),
!                                    1))
            {
              align
                = tree_low_cst
--- 976,984 ----
                   && TREE_CODE (TREE_OPERAND (curpos, 1)) == INTEGER_CST
                   && TREE_CODE (TREE_OPERAND (curpos, 0)) == MULT_EXPR
                   && host_integerp (TREE_OPERAND
!                                    (TREE_OPERAND (curpos, 0), 1), 1)
!                  && !tree_int_cst_sign_bit (TREE_OPERAND
!                                             (TREE_OPERAND (curpos, 0), 1)))
            {
              align
                = tree_low_cst
*************** shift_unc_components_for_thin_pointers (
*** 3411,3416 ****
--- 3413,3424 ----
  
    DECL_FIELD_OFFSET (bounds_field)
      = size_binop (MINUS_EXPR, size_zero_node, byte_position (array_field));
+   if (TREE_CODE (DECL_FIELD_OFFSET (bounds_field)) == INTEGER_CST
+       && TREE_OVERFLOW (DECL_FIELD_OFFSET (bounds_field)))
+     DECL_FIELD_OFFSET (bounds_field)
+       = build_int_cst_wide (sizetype,
+                           TREE_INT_CST_LOW (DECL_FIELD_OFFSET (bounds_field)),
+                           TREE_INT_CST_HIGH (DECL_FIELD_OFFSET 
(bounds_field)));
  
    DECL_FIELD_OFFSET (array_field) = size_zero_node;
    DECL_FIELD_BIT_OFFSET (array_field) = bitsize_zero_node;
Index: trunk/gcc/varasm.c
===================================================================
*** trunk.orig/gcc/varasm.c     2011-08-24 15:34:13.000000000 +0200
--- trunk/gcc/varasm.c  2011-08-24 15:36:23.000000000 +0200
*************** assemble_variable (tree decl, int top_le
*** 1980,1986 ****
      return;
  
    if (! dont_output_data
!       && ! host_integerp (DECL_SIZE_UNIT (decl), 1))
      {
        error ("size of variable %q+D is too large", decl);
        return;
--- 1980,1989 ----
      return;
  
    if (! dont_output_data
!       && (! host_integerp (DECL_SIZE_UNIT (decl), 1)
!         /* Restrict sizes of variables to half the address-space by
!            making sure the msb of the size is not set.  */
!         || tree_int_cst_sign_bit (DECL_SIZE_UNIT (decl)) != 0))
      {
        error ("size of variable %q+D is too large", decl);
        return;
Index: trunk/gcc/c-family/c-common.c
===================================================================
*** trunk.orig/gcc/c-family/c-common.c  2011-08-24 15:34:13.000000000 +0200
--- trunk/gcc/c-family/c-common.c       2011-08-24 15:36:23.000000000 +0200
*************** pointer_int_sum (location_t loc, enum tr
*** 3790,3819 ****
        intop = convert (int_type, TREE_OPERAND (intop, 0));
      }
  
!   /* Convert the integer argument to a type the same size as sizetype
       so the multiply won't overflow spuriously.  */
    if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
!       || TYPE_UNSIGNED (TREE_TYPE (intop)) != TYPE_UNSIGNED (sizetype))
      intop = convert (c_common_type_for_size (TYPE_PRECISION (sizetype),
!                                            TYPE_UNSIGNED (sizetype)), intop);
  
!   /* Replace the integer argument with a suitable product by the object size.
!      Do this multiplication as signed, then convert to the appropriate type
!      for the pointer operation and disregard an overflow that occured only
!      because of the sign-extension change in the latter conversion.  */
!   {
!     tree t = build_binary_op (loc,
!                             MULT_EXPR, intop,
!                             convert (TREE_TYPE (intop), size_exp), 1);
!     intop = convert (sizetype, t);
!     if (TREE_OVERFLOW_P (intop) && !TREE_OVERFLOW (t))
!       intop = build_int_cst_wide (TREE_TYPE (intop), TREE_INT_CST_LOW (intop),
!                                 TREE_INT_CST_HIGH (intop));
!   }
  
    /* Create the sum or difference.  */
    if (resultcode == MINUS_EXPR)
!     intop = fold_build1_loc (loc, NEGATE_EXPR, sizetype, intop);
  
    ret = fold_build_pointer_plus_loc (loc, ptrop, intop);
  
--- 3790,3811 ----
        intop = convert (int_type, TREE_OPERAND (intop, 0));
      }
  
!   /* Convert the integer argument to a signed type the same size as sizetype
       so the multiply won't overflow spuriously.  */
    if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
!       || TYPE_UNSIGNED (TREE_TYPE (intop)))
      intop = convert (c_common_type_for_size (TYPE_PRECISION (sizetype),
!                                            false), intop);
  
!   /* Replace the integer argument with a suitable product by the
!      object size.  */
!   intop = build_binary_op (loc,
!                          MULT_EXPR, intop,
!                          convert (TREE_TYPE (intop), size_exp), 1);
  
    /* Create the sum or difference.  */
    if (resultcode == MINUS_EXPR)
!     intop = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (intop), intop);
  
    ret = fold_build_pointer_plus_loc (loc, ptrop, intop);
  

Reply via email to