From: Richard Guenther Date: Wed, 2 May 2012 11:22:31 +0000 (+0000) Subject: tree.c (valid_constant_size_p): New function. X-Git-Tag: releases/gcc-4.8.0~5754 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=56099f00a526f137d24bbf2ac6def05003ebe5c5;p=thirdparty%2Fgcc.git tree.c (valid_constant_size_p): New function. 2012-05-02 Richard Guenther * tree.c (valid_constant_size_p): New function. * tree.h (valid_constant_size_p): Declare. * cfgexpand.c (expand_one_var): Adjust check for too large variables by using valid_constant_size_p. * varasm.c (assemble_variable): Likewise. c/ * c-decl.c (grokdeclarator): Properly check for sizes that cover more than half of the address-space. cp/ * decl.c (grokdeclarator): Properly check for sizes that cover more than half of the address-space. 2012-05-02 Richard Guenther * fold-const.c (div_if_zero_remainder): sizetypes no longer sign-extend. (int_const_binop_1): New worker for int_const_binop with overflowable parameter. Pass it through to force_fit_type_double. (int_const_binop): Wrap around int_const_binop_1 with overflowable equal to one. (size_binop_loc): Call int_const_binop_1 with overflowable equal to minus one, forcing overflow detection for even unsigned types. (extract_muldiv_1): Remove bogus TYPE_IS_SIZETYPE special-casing. (fold_binary_loc): Call try_move_mult_to_index with signed offset. * stor-layout.c (initialize_sizetypes): sizetypes no longer sign-extend. (layout_type): For zero-sized arrays ignore overflow on the size calculations. * 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. * varasm.c (output_constructor_regular_field): Sign-extend the field-offset to cater for negative offsets produced by the Ada frontend. * omp-low.c (extract_omp_for_data): Convert the loop step to signed for pointer adjustments. * g++.dg/tree-ssa/pr19807.C: Adjust. From-SVN: r187042 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f9b8a6e84f26..485395915600 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,43 @@ +2012-05-02 Richard Guenther + + * fold-const.c (div_if_zero_remainder): sizetypes no longer + sign-extend. + (int_const_binop_1): New worker for int_const_binop with + overflowable parameter. Pass it through + to force_fit_type_double. + (int_const_binop): Wrap around int_const_binop_1 with overflowable + equal to one. + (size_binop_loc): Call int_const_binop_1 with overflowable equal + to minus one, forcing overflow detection for even unsigned types. + (extract_muldiv_1): Remove bogus TYPE_IS_SIZETYPE special-casing. + (fold_binary_loc): Call try_move_mult_to_index with signed offset. + * stor-layout.c (initialize_sizetypes): sizetypes no longer + sign-extend. + (layout_type): For zero-sized arrays ignore overflow on the + size calculations. + * 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. + * varasm.c (output_constructor_regular_field): Sign-extend the + field-offset to cater for negative offsets produced by the Ada frontend. + * omp-low.c (extract_omp_for_data): Convert the loop step to + signed for pointer adjustments. + +2012-05-02 Richard Guenther + + * tree.c (valid_constant_size_p): New function. + * tree.h (valid_constant_size_p): Declare. + * cfgexpand.c (expand_one_var): Adjust check for too large + variables by using valid_constant_size_p. + * varasm.c (assemble_variable): Likewise. + + * c-decl.c (grokdeclarator): Properly check for sizes that + cover more than half of the address-space. + 2012-05-02 Jakub Jelinek PR tree-optimization/53163 diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 158b3ad0f195..3153cf4e1836 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -5811,12 +5811,12 @@ grokdeclarator (const struct c_declarator *declarator, } } - /* Did array size calculations overflow? */ - + /* Did array size calculations overflow or does the array cover more + than half of the address-space? */ if (TREE_CODE (type) == ARRAY_TYPE && COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST - && TREE_OVERFLOW (TYPE_SIZE_UNIT (type))) + && ! valid_constant_size_p (TYPE_SIZE_UNIT (type))) { if (name) error_at (loc, "size of array %qE is too large", name); diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 9de3e51c673f..4c27e762df57 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -1241,8 +1241,9 @@ expand_one_var (tree var, bool toplevel, bool really_expand) if (really_expand) expand_one_register_var (origvar); } - else if (!host_integerp (DECL_SIZE_UNIT (var), 1)) + else if (! valid_constant_size_p (DECL_SIZE_UNIT (var))) { + /* Reject variables which cover more than half of the address-space. */ if (really_expand) { error ("size of variable %q+D is too large", var); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e52149f023d4..6b0e57cedb53 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2012-05-02 Richard Guenther + + * decl.c (grokdeclarator): Properly check for sizes that + cover more than half of the address-space. + 2012-04-30 Marc Glisse PR c++/51033 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 40818a3f3ff5..108b51531d4a 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -9672,12 +9672,12 @@ grokdeclarator (const cp_declarator *declarator, error ("non-parameter %qs cannot be a parameter pack", name); } - /* Did array size calculations overflow? */ - + /* Did array size calculations overflow or does the array cover more + than half of the address-space? */ if (TREE_CODE (type) == ARRAY_TYPE && COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST - && TREE_OVERFLOW (TYPE_SIZE_UNIT (type))) + && ! valid_constant_size_p (TYPE_SIZE_UNIT (type))) { error ("size of array %qs is too large", name); /* If we proceed with the array type as it is, we'll eventually diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 41081ff919c3..fe12942d9811 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -191,9 +191,6 @@ div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2) 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), @@ -935,8 +932,9 @@ int_binop_types_match_p (enum tree_code code, const_tree type1, const_tree type2 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) +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; @@ -1078,13 +1076,19 @@ int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2) return NULL_TREE; } - t = force_fit_type_double (TREE_TYPE (arg1), res, 1, + 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 @@ -1423,8 +1427,10 @@ size_binop_loc (location_t loc, enum tree_code code, tree arg0, tree arg1) return arg1; } - /* Handle general case of two integer constants. */ - return int_const_binop (code, arg0, 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); @@ -5908,11 +5914,9 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type, multiple of the other, in which case we replace this with either an operation or CODE or TCODE. - If we have an unsigned type that is not a sizetype, we cannot do - this since it will change the result if the original computation - overflowed. */ - if ((TYPE_OVERFLOW_UNDEFINED (ctype) - || (TREE_CODE (ctype) == INTEGER_TYPE && TYPE_IS_SIZETYPE (ctype))) + If we have an unsigned type, we cannot do this since it will change + the result if the original computation overflowed. */ + if (TYPE_OVERFLOW_UNDEFINED (ctype) && ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR) || (tcode == MULT_EXPR && code != TRUNC_MOD_EXPR && code != CEIL_MOD_EXPR @@ -9971,7 +9975,8 @@ fold_binary_loc (location_t loc, if (TREE_CODE (arg0) == ADDR_EXPR) { tem = try_move_mult_to_index (loc, arg0, - fold_convert_loc (loc, sizetype, arg1)); + fold_convert_loc (loc, + ssizetype, arg1)); if (tem) return fold_convert_loc (loc, type, tem); } diff --git a/gcc/omp-low.c b/gcc/omp-low.c index ec1a5522d7f8..f6b62438dcec 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -336,9 +336,11 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd, switch (TREE_CODE (t)) { case PLUS_EXPR: - case POINTER_PLUS_EXPR: loop->step = TREE_OPERAND (t, 1); break; + case POINTER_PLUS_EXPR: + loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1)); + break; case MINUS_EXPR: loop->step = TREE_OPERAND (t, 1); loop->step = fold_build1_loc (loc, diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index e72e7f390910..12a6c13a6b8d 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -2182,11 +2182,37 @@ layout_type (tree type) that (possible) negative values are handled appropriately when determining overflow. */ else - length - = fold_convert (sizetype, - size_binop (PLUS_EXPR, - build_int_cst (TREE_TYPE (lb), 1), - size_binop (MINUS_EXPR, ub, lb))); + { + /* ??? When it is obvious that the range is signed + represent it using ssizetype. */ + if (TREE_CODE (lb) == INTEGER_CST + && TREE_CODE (ub) == INTEGER_CST + && TYPE_UNSIGNED (TREE_TYPE (lb)) + && tree_int_cst_lt (ub, lb)) + { + lb = double_int_to_tree + (ssizetype, + double_int_sext (tree_to_double_int (lb), + TYPE_PRECISION (TREE_TYPE (lb)))); + ub = double_int_to_tree + (ssizetype, + double_int_sext (tree_to_double_int (ub), + TYPE_PRECISION (TREE_TYPE (ub)))); + } + length + = fold_convert (sizetype, + size_binop (PLUS_EXPR, + build_int_cst (TREE_TYPE (lb), 1), + size_binop (MINUS_EXPR, ub, lb))); + } + + /* If we arrived at a length of zero ignore any overflow + that occured as part of the calculation. There exists + an association of the plus one where that overflow would + not happen. */ + if (integer_zerop (length) + && TREE_OVERFLOW (length)) + length = size_zero_node; TYPE_SIZE (type) = size_binop (MULT_EXPR, element_size, fold_convert (bitsizetype, @@ -2453,11 +2479,6 @@ initialize_sizetypes (void) 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)); @@ -2466,11 +2487,6 @@ initialize_sizetypes (void) = 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)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b2055433beb1..956501520461 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2012-05-02 Richard Guenther + + * g++.dg/tree-ssa/pr19807.C: Adjust. + 2012-05-02 Jakub Jelinek PR tree-optimization/53163 diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr19807.C b/gcc/testsuite/g++.dg/tree-ssa/pr19807.C index bba79a9d150d..0eeeb18abda5 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/pr19807.C +++ b/gcc/testsuite/g++.dg/tree-ssa/pr19807.C @@ -25,6 +25,6 @@ void bar(int i) Simply test for the existence of +1 and -1 once, which also ensures the above. If the addition/subtraction would be applied to the pointer we would instead see +-4 (or 8, depending on sizeof(int)). */ -/* { dg-final { scan-tree-dump-times "\\\+ -1;" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump "\\\+ (0x0f*|18446744073709551615|4294967295|-1);" "optimized" } } */ /* { dg-final { scan-tree-dump-times "\\\+ 1;" 1 "optimized" } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 4e86b8db0c32..1257b8bf7ba2 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -1101,14 +1101,12 @@ bit_value_unop_1 (enum tree_code code, tree type, 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)); + 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 = (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type) - ? 0 : TYPE_UNSIGNED (type)); + uns = TYPE_UNSIGNED (type); *mask = double_int_ext (*mask, TYPE_PRECISION (type), uns); *val = double_int_ext (*val, TYPE_PRECISION (type), uns); break; @@ -1130,8 +1128,7 @@ bit_value_binop_1 (enum tree_code code, tree type, 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)); + 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; @@ -1198,13 +1195,6 @@ bit_value_binop_1 (enum tree_code code, tree type, } 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); @@ -1316,12 +1306,7 @@ bit_value_binop_1 (enum tree_code code, tree type, 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; + 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 diff --git a/gcc/tree.c b/gcc/tree.c index 4623d3765e42..1ee3f1db51e4 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1062,10 +1062,7 @@ build_int_cst_type (tree type, HOST_WIDE_INT low) tree 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))); + bool sign_extended_type = !TYPE_UNSIGNED (type); cst = double_int_ext (cst, TYPE_PRECISION (type), !sign_extended_type); @@ -1079,9 +1076,7 @@ bool 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))); + bool sign_extended_type = !TYPE_UNSIGNED (type); double_int ext = double_int_ext (cst, TYPE_PRECISION (type), !sign_extended_type); @@ -1111,9 +1106,7 @@ force_fit_type_double (tree type, double_int cst, int overflowable, bool sign_extended_type; /* Size types *are* sign extended. */ - sign_extended_type = (!TYPE_UNSIGNED (type) - || (TREE_CODE (type) == INTEGER_TYPE - && TYPE_IS_SIZETYPE (type))); + 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)) @@ -6553,9 +6546,7 @@ host_integerp (const_tree t, int pos) && (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))))) + && !TYPE_UNSIGNED (TREE_TYPE (t))) || (pos && TREE_INT_CST_HIGH (t) == 0))); } @@ -6850,6 +6841,20 @@ compare_tree_int (const_tree t, unsigned HOST_WIDE_INT u) return 1; } +/* Return true if SIZE represents a constant size that is in bounds of + what the middle-end and the backend accepts (covering not more than + half of the address-space). */ + +bool +valid_constant_size_p (const_tree size) +{ + if (! host_integerp (size, 1) + || TREE_OVERFLOW (size) + || tree_int_cst_sign_bit (size) != 0) + return false; + return true; +} + /* Return true if CODE represents an associative tree code. Otherwise return false. */ bool @@ -8276,18 +8281,6 @@ int_fits_type_p (const_tree c, const_tree type) 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); @@ -8306,10 +8299,6 @@ retry: 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)); @@ -8331,10 +8320,6 @@ retry: 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)); diff --git a/gcc/tree.h b/gcc/tree.h index e719be2ed407..3d7fcabe142f 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4451,6 +4451,7 @@ extern bool tree_expr_nonnegative_warnv_p (tree, bool *); extern bool may_negate_without_overflow_p (const_tree); extern tree strip_array_types (tree); extern tree excess_precision_type (tree); +extern bool valid_constant_size_p (const_tree); /* Construct various nodes representing fract or accum data types. */ diff --git a/gcc/varasm.c b/gcc/varasm.c index 03ac49b4677d..ce9e32803649 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -1992,7 +1992,7 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, return; if (! dont_output_data - && ! host_integerp (DECL_SIZE_UNIT (decl), 1)) + && ! valid_constant_size_p (DECL_SIZE_UNIT (decl))) { error ("size of variable %q+D is too large", decl); return; @@ -4773,9 +4773,13 @@ output_constructor_regular_field (oc_local_state *local) if (local->index != NULL_TREE) { + /* Perform the index calculation in modulo arithmetic but + sign-extend the result because Ada has negative DECL_FIELD_OFFSETs + but we are using an unsigned sizetype. */ + unsigned prec = TYPE_PRECISION (sizetype); double_int idx = double_int_sub (tree_to_double_int (local->index), tree_to_double_int (local->min_index)); - gcc_assert (double_int_fits_in_shwi_p (idx)); + idx = double_int_sext (idx, prec); fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1) * idx.low); }