This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Make sizetypes no longer sign-extending


I've been carrying this patch for quite some while now and really
want to go forward with it - the problem is that while all default
languages work fine after this patch Ada shows some testsuite
regressions.  I've had various hacks/workarounds throughout the
Ada frontend for them, but lost track of what fixed what and
they all felt like hacks anyway.

Thus - I know the patch will add Ada testsuite regressions.  But it will
not break Ada bootstrap.  Ada is not in the set of default languages,
nor is it considered release critical.

Are the Ada folks happy with helping to fix the fallout after-the-fact
(I got Eric to fix the bootstrap issues that were first present - thanks
for that)?  I am happy to revisit my hacks/workarounds and post them,
but it will be ultimatively easier to review them if you can see
the FAIL for yourself (there are some workarounds/hacks posted on the
mailinglist for previous attempts IIRC).

Thanks for your consideration.

The patch is currently under re-testing (it needs the 2nd patch
below, which was already approved but back in time broke Ada
bootstrap - I didn't verify if that still occurs).

Richard.

2012-03-06  Richard Guenther  <rguenther@suse.de>

	* 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.

Index: trunk/gcc/fold-const.c
===================================================================
*** trunk.orig/gcc/fold-const.c	2012-03-06 12:41:10.000000000 +0100
--- trunk/gcc/fold-const.c	2012-03-06 14:46:25.000000000 +0100
*************** div_if_zero_remainder (enum tree_code co
*** 191,199 ****
       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),
--- 191,196 ----
*************** int_binop_types_match_p (enum tree_code
*** 935,942 ****
     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;
--- 932,940 ----
     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
*** 1078,1090 ****
        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
--- 1076,1094 ----
        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
*** 1445,1452 ****
  	    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);
--- 1449,1458 ----
  	    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);
*************** extract_muldiv_1 (tree t, tree c, enum t
*** 5924,5934 ****
  	 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)))
  	  && ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR)
  	      || (tcode == MULT_EXPR
  		  && code != TRUNC_MOD_EXPR && code != CEIL_MOD_EXPR
--- 5930,5938 ----
  	 multiple of the other, in which case we replace this with either an
  	 operation or CODE or TCODE.
  
! 	 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
*************** fold_binary_loc (location_t loc,
*** 9953,9959 ****
        if (TREE_CODE (arg0) == ADDR_EXPR)
  	{
  	  tem = try_move_mult_to_index (loc, arg0,
! 					fold_convert_loc (loc, sizetype, arg1));
  	  if (tem)
  	    return fold_convert_loc (loc, type, tem);
  	}
--- 9957,9964 ----
        if (TREE_CODE (arg0) == ADDR_EXPR)
  	{
  	  tem = try_move_mult_to_index (loc, arg0,
! 					fold_convert_loc (loc,
! 							  ssizetype, arg1));
  	  if (tem)
  	    return fold_convert_loc (loc, type, tem);
  	}
Index: trunk/gcc/stor-layout.c
===================================================================
*** trunk.orig/gcc/stor-layout.c	2012-03-06 11:36:46.000000000 +0100
--- trunk/gcc/stor-layout.c	2012-03-06 14:46:25.000000000 +0100
*************** layout_type (tree type)
*** 1970,1975 ****
--- 1970,1983 ----
  					    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,
  							 length));
*************** 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));
--- 2243,2248 ----
*************** 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));
--- 2251,2256 ----
Index: trunk/gcc/tree-ssa-ccp.c
===================================================================
*** trunk.orig/gcc/tree-ssa-ccp.c	2012-03-06 11:36:46.000000000 +0100
--- trunk/gcc/tree-ssa-ccp.c	2012-03-06 14:46:25.000000000 +0100
*************** bit_value_unop_1 (enum tree_code code, t
*** 1101,1114 ****
  	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;
--- 1101,1112 ----
  	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,
*** 1130,1137 ****
  		   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;
--- 1128,1134 ----
  		   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,
*** 1198,1210 ****
  	    }
  	  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);
--- 1195,1200 ----
*************** bit_value_binop_1 (enum tree_code code,
*** 1316,1327 ****
  	  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
--- 1306,1312 ----
  	  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	2012-03-06 14:46:08.000000000 +0100
--- trunk/gcc/tree.c	2012-03-06 14:53:36.000000000 +0100
*************** 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)
*** 6532,6540 ****
  	       && (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)));
  }
  
--- 6526,6532 ----
  	       && (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
*** 8264,8281 ****
    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);
--- 8256,8261 ----
*************** retry:
*** 8294,8303 ****
    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));
--- 8274,8279 ----
*************** retry:
*** 8319,8328 ****
    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));
--- 8295,8300 ----
Index: trunk/gcc/varasm.c
===================================================================
*** trunk.orig/gcc/varasm.c	2012-03-06 14:46:08.000000000 +0100
--- trunk/gcc/varasm.c	2012-03-06 14:48:30.000000000 +0100
*************** output_constructor_regular_field (oc_loc
*** 4756,4764 ****
  
    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);
      }
--- 4756,4768 ----
  
    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));
!       idx = double_int_sext (idx, prec);
        fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1)
  		  * idx.low);
      }
Index: trunk/gcc/omp-low.c
===================================================================
*** trunk.orig/gcc/omp-low.c	2012-03-06 11:36:46.000000000 +0100
--- trunk/gcc/omp-low.c	2012-03-06 14:46:25.000000000 +0100
*************** extract_omp_for_data (gimple for_stmt, s
*** 336,344 ****
        switch (TREE_CODE (t))
  	{
  	case PLUS_EXPR:
- 	case POINTER_PLUS_EXPR:
  	  loop->step = TREE_OPERAND (t, 1);
  	  break;
  	case MINUS_EXPR:
  	  loop->step = TREE_OPERAND (t, 1);
  	  loop->step = fold_build1_loc (loc,
--- 336,346 ----
        switch (TREE_CODE (t))
  	{
  	case 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,
Index: trunk/gcc/testsuite/g++.dg/tree-ssa/pr19807.C
===================================================================
*** trunk.orig/gcc/testsuite/g++.dg/tree-ssa/pr19807.C	2012-03-06 11:36:46.000000000 +0100
--- trunk/gcc/testsuite/g++.dg/tree-ssa/pr19807.C	2012-03-06 14:46:25.000000000 +0100
*************** void bar(int i)
*** 25,30 ****
     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-times "\\\+ 1;" 1 "optimized" } } */
  /* { dg-final { cleanup-tree-dump "optimized" } } */
--- 25,30 ----
     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 "\\\+ (0x0f*|18446744073709551615|4294967295|-1);" "optimized" } } */
  /* { dg-final { scan-tree-dump-times "\\\+ 1;" 1 "optimized" } } */
  /* { dg-final { cleanup-tree-dump "optimized" } } */




2012-03-06  Richard Guenther  <rguenther@suse.de>

	* 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.

Index: trunk/gcc/tree.c
===================================================================
*** trunk.orig/gcc/tree.c	2012-03-06 13:54:25.000000000 +0100
--- trunk/gcc/tree.c	2012-03-06 14:46:08.000000000 +0100
*************** compare_tree_int (const_tree t, unsigned
*** 6829,6834 ****
--- 6829,6848 ----
      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
Index: trunk/gcc/varasm.c
===================================================================
*** trunk.orig/gcc/varasm.c	2012-03-06 13:54:25.000000000 +0100
--- trunk/gcc/varasm.c	2012-03-06 14:46:08.000000000 +0100
*************** assemble_variable (tree decl, int top_le
*** 1987,1993 ****
      return;
  
    if (! dont_output_data
!       && ! host_integerp (DECL_SIZE_UNIT (decl), 1))
      {
        error ("size of variable %q+D is too large", decl);
        return;
--- 1987,1993 ----
      return;
  
    if (! dont_output_data
!       && ! valid_constant_size_p (DECL_SIZE_UNIT (decl)))
      {
        error ("size of variable %q+D is too large", decl);
        return;
Index: trunk/gcc/c-decl.c
===================================================================
*** trunk.orig/gcc/c-decl.c	2012-03-06 13:54:25.000000000 +0100
--- trunk/gcc/c-decl.c	2012-03-06 14:46:08.000000000 +0100
*************** grokdeclarator (const struct c_declarato
*** 5798,5809 ****
  	}
      }
  
!   /* Did array size calculations overflow?  */
! 
    if (TREE_CODE (type) == ARRAY_TYPE
        && COMPLETE_TYPE_P (type)
        && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
!       && TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
      {
        if (name)
  	error_at (loc, "size of array %qE is too large", name);
--- 5798,5809 ----
  	}
      }
  
!   /* 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
!       && ! valid_constant_size_p (TYPE_SIZE_UNIT (type)))
      {
        if (name)
  	error_at (loc, "size of array %qE is too large", name);
Index: trunk/gcc/cp/decl.c
===================================================================
*** trunk.orig/gcc/cp/decl.c	2012-03-06 13:54:25.000000000 +0100
--- trunk/gcc/cp/decl.c	2012-03-06 14:46:08.000000000 +0100
*************** grokdeclarator (const cp_declarator *dec
*** 9635,9646 ****
          error ("non-parameter %qs cannot be a parameter pack", name);
      }
  
!   /* Did array size calculations overflow?  */
! 
    if (TREE_CODE (type) == ARRAY_TYPE
        && COMPLETE_TYPE_P (type)
        && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
!       && TREE_OVERFLOW (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
--- 9635,9646 ----
          error ("non-parameter %qs cannot be a parameter pack", name);
      }
  
!   /* 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
!       && ! 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
Index: trunk/gcc/cfgexpand.c
===================================================================
*** trunk.orig/gcc/cfgexpand.c	2012-03-06 13:54:25.000000000 +0100
--- trunk/gcc/cfgexpand.c	2012-03-06 14:46:08.000000000 +0100
*************** expand_one_var (tree var, bool toplevel,
*** 1238,1245 ****
        if (really_expand)
          expand_one_register_var (origvar);
      }
!   else if (!host_integerp (DECL_SIZE_UNIT (var), 1))
      {
        if (really_expand)
  	{
  	  error ("size of variable %q+D is too large", var);
--- 1238,1246 ----
        if (really_expand)
          expand_one_register_var (origvar);
      }
!   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);
Index: trunk/gcc/tree.h
===================================================================
*** trunk.orig/gcc/tree.h	2012-03-06 13:54:25.000000000 +0100
--- trunk/gcc/tree.h	2012-03-06 14:46:08.000000000 +0100
*************** extern bool tree_expr_nonnegative_warnv_
*** 4439,4444 ****
--- 4439,4445 ----
  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.  */
  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]