From patchwork Thu Aug 25 08:50:55 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Biener X-Patchwork-Id: 111523 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 1ADE0B6F69 for ; Thu, 25 Aug 2011 18:51:22 +1000 (EST) Received: (qmail 14503 invoked by alias); 25 Aug 2011 08:51:18 -0000 Received: (qmail 14470 invoked by uid 22791); 25 Aug 2011 08:51:14 -0000 X-SWARE-Spam-Status: No, hits=-2.5 required=5.0 tests=AWL, BAYES_00, LONGWORDS, RP_MATCHES_RCVD, TW_TX X-Spam-Check-By: sourceware.org Received: from cantor2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 25 Aug 2011 08:50:58 +0000 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.221.2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx2.suse.de (Postfix) with ESMTP id 73C668E857; Thu, 25 Aug 2011 10:50:55 +0200 (CEST) Date: Thu, 25 Aug 2011 10:50:55 +0200 (CEST) From: Richard Guenther To: Eric Botcazou Cc: gcc-patches@gcc.gnu.org Subject: Re: [PATCH][RFC] Fix sizetype "sign" checks In-Reply-To: Message-ID: References: <201108190100.09992.ebotcazou@adacore.com> User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) MIME-Version: 1.0 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org On Wed, 24 Aug 2011, Richard Guenther wrote: > 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. Another patch that makes the gnat.dg and acats testsuites clean on x86_64-linux apart from diagnostic regressions is fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1) * idx.low); but I still fail to build Ada without bootstrapping as the RTS is still miscompiled which results in gnatmake segfaulting like Starting program: /home/abuild/rguenther/obj/gcc/gnatmake -c -b -I../rts -I. -I/space/rguenther/src/svn/trunk2/gcc/ada --GNATBIND=../../gnatbind --GCC=../../xgcc\ -B../../\ -g\ -O2\ \ -gnatpg\ -gnata gnatchop gnatcmd gnatkr gnatls gnatprep gnatxref gnatfind gnatname gnatclean -bargs -I../rts -I. -I/space/rguenther/src/svn/trunk2/gcc/ada -static -x Program received signal SIGSEGV, Segmentation fault. system.secondary_stack.ss_mark () at ../rts/s-secsta.adb:465 465 return (Sstk => Sstk, Sptr => To_Stack_Ptr (Sstk).Top); (gdb) p Sstk $1 = (system.address) 0x0 Are there any other places where GIGI would expect sign-extended sizetype values? Any hint where to look for the above failure? system.soft_links.get_sec_stack_addr_nt doesn't seem to get called at all. Where is the machinery to eventually set it up located? Grepping for stack or secondary doesn't reveal too much useful information. Updated patch below. Thanks, Richard. 2011-06-16 Richard Guenther * 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-25 09:51:16.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; *************** output_constructor_regular_field (oc_loc *** 4740,4747 **** if (local->index != NULL_TREE) { ! 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)); fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1) * idx.low); --- 4743,4757 ---- if (local->index != NULL_TREE) { ! /* ??? Ada has negative DECL_FIELD_OFFSETs but we are using an ! unsigned sizetype so make sure to sign-extend the indices before ! subtracting them. */ ! unsigned prec = TYPE_PRECISION (sizetype); ! double_int idx ! = double_int_sub (double_int_sext (tree_to_double_int (local->index), ! prec), ! double_int_sext (tree_to_double_int ! (local->min_index), prec)); gcc_assert (double_int_fits_in_shwi_p (idx)); fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1) * idx.low); 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); Index: varasm.c =================================================================== --- varasm.c (revision 178035) +++ varasm.c (working copy) @@ -4740,8 +4743,15 @@ output_constructor_regular_field (oc_loc if (local->index != NULL_TREE) { - double_int idx = double_int_sub (tree_to_double_int (local->index), - tree_to_double_int (local->min_index)); + /* ??? Ada has negative DECL_FIELD_OFFSETs but we are using an + unsigned sizetype so make sure to sign-extend the indices before + subtracting them. */ + unsigned prec = TYPE_PRECISION (sizetype); + double_int idx + = double_int_sub (double_int_sext (tree_to_double_int (local->index), + prec), + double_int_sext (tree_to_double_int + (local->min_index), prec)); gcc_assert (double_int_fits_in_shwi_p (idx));