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]

[3.3 PATCH] Backport fortran/12632 fixes


Many thanks to Toon for approving the FORTRAN parts of this patch
for mainline.  After a week without further comment, I decided that
the fold-const.c change was obvious and I've committed the patch to
mainline.


The following version is a backport of this fix to the gcc-3_3-branch.
This patch is nearly identical to the mainline version, with the
exception that the original required the function integer_nonzerop,
which isn't available on the branch.  The solution below is to also
backport that new predicate to 3.3.3's tree.c.

This revised patch has been tested against the gcc-3_3-branch on
i686-pc-linux-gnu with a complete bootstrap, all languages except
treelang, and regression tested with a top-level "make -k check" with
no new failures.

Ok for the 3.3 branch?



2003-12-29  Roger Sayle  <roger@eyesopen.com>

	PR fortran/12632
	* tree.c (integer_nonzerop): New predicate for nonzero integers.
	* tree.h (integer_nonzerop): Add function prototype.
	* fold-const.c (fold) <COND_EXPR>: Don't fold a constant condition,
	if the type of the selected branch doesn't match its' parent.

	* com.c (ffecom_subscript_check_): Take as an extra argument the
	(possibly NULL) decl of the array.  Don't create unnecessary tree
	nodes if the array index is known to be safe at compile-time.
	If the array index is unsafe, force the array decl into memory to
	avoid RTL expansion problems.
	(ffecom_array_ref_): Update calls to ffecom_subscript_check_.
	(ffecom_char_args_x_): Likewise.

	* g77.dg/12632.f: New test case.


Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.367.2.7
diff -c -3 -p -r1.367.2.7 tree.h
*** tree.h	16 Oct 2003 09:33:47 -0000	1.367.2.7
--- tree.h	29 Dec 2003 22:27:37 -0000
*************** extern int integer_all_onesp		PARAMS ((t
*** 2637,2642 ****
--- 2637,2647 ----

  extern int integer_pow2p		PARAMS ((tree));

+ /* integer_nonzerop (tree x) is nonzero if X is an integer constant
+    with a nonzero value.  */
+
+ extern int integer_nonzerop (tree);
+
  /* staticp (tree x) is nonzero if X is a reference to data allocated
     at a fixed address in memory.  */

Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.282.2.3
diff -c -3 -p -r1.282.2.3 tree.c
*** tree.c	21 Aug 2003 01:50:03 -0000	1.282.2.3
--- tree.c	29 Dec 2003 22:27:38 -0000
*************** integer_pow2p (expr)
*** 723,728 ****
--- 723,745 ----
  	  || (low == 0 && (high & (high - 1)) == 0));
  }

+ /* Return 1 if EXPR is an integer constant other than zero or a
+    complex constant other than zero.  */
+
+ int
+ integer_nonzerop (tree expr)
+ {
+   STRIP_NOPS (expr);
+
+   return ((TREE_CODE (expr) == INTEGER_CST
+ 	   && ! TREE_CONSTANT_OVERFLOW (expr)
+ 	   && (TREE_INT_CST_LOW (expr) != 0
+ 	       || TREE_INT_CST_HIGH (expr) != 0))
+ 	  || (TREE_CODE (expr) == COMPLEX_CST
+ 	      && (integer_nonzerop (TREE_REALPART (expr))
+ 		  || integer_nonzerop (TREE_IMAGPART (expr)))));
+ }
+
  /* Return the power of two represented by a tree node known to be a
     power of two.  */

Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.227.2.4
diff -c -3 -p -r1.227.2.4 fold-const.c
*** fold-const.c	3 Jul 2003 13:18:00 -0000	1.227.2.4
--- fold-const.c	29 Dec 2003 22:27:40 -0000
*************** fold (expr)
*** 6785,6793 ****
        /* Pedantic ANSI C says that a conditional expression is never an lvalue,
  	 so all simple results must be passed through pedantic_non_lvalue.  */
        if (TREE_CODE (arg0) == INTEGER_CST)
! 	return pedantic_non_lvalue
! 	  (TREE_OPERAND (t, (integer_zerop (arg0) ? 2 : 1)));
!       else if (operand_equal_p (arg1, TREE_OPERAND (expr, 2), 0))
  	return pedantic_omit_one_operand (type, arg1, arg0);

        /* If the second operand is zero, invert the comparison and swap
--- 6785,6800 ----
        /* Pedantic ANSI C says that a conditional expression is never an lvalue,
  	 so all simple results must be passed through pedantic_non_lvalue.  */
        if (TREE_CODE (arg0) == INTEGER_CST)
! 	{
! 	  tem = TREE_OPERAND (t, (integer_zerop (arg0) ? 2 : 1));
! 	  /* Only optimize constant conditions when the selected branch
! 	     has the same type as the COND_EXPR.  This avoids optimizing
! 	     away "c ? x : throw", where the throw has a void type.  */
! 	  if (TREE_TYPE (tem) == TREE_TYPE (t))
! 	    return pedantic_non_lvalue (tem);
! 	  return t;
! 	}
!       if (operand_equal_p (arg1, TREE_OPERAND (expr, 2), 0))
  	return pedantic_omit_one_operand (type, arg1, arg0);

        /* If the second operand is zero, invert the comparison and swap
Index: f/com.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/f/com.c,v
retrieving revision 1.182.4.5
diff -c -3 -p -r1.182.4.5 com.c
*** f/com.c	9 Jul 2003 19:04:40 -0000	1.182.4.5
--- f/com.c	29 Dec 2003 22:27:43 -0000
*************** static GTY(()) tree shadowed_labels;
*** 639,653 ****

  /* Return the subscript expression, modified to do range-checking.

!    `array' is the array to be checked against.
     `element' is the subscript expression to check.
     `dim' is the dimension number (starting at 0).
     `total_dims' is the total number of dimensions (0 for CHARACTER substring).
  */

  static tree
  ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
! 			 const char *array_name)
  {
    tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
    tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
--- 639,654 ----

  /* Return the subscript expression, modified to do range-checking.

!    `array' is the array type to be checked against.
     `element' is the subscript expression to check.
     `dim' is the dimension number (starting at 0).
     `total_dims' is the total number of dimensions (0 for CHARACTER substring).
+    `item' is the array decl or NULL_TREE.
  */

  static tree
  ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
! 			 const char *array_name, tree item)
  {
    tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
    tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
*************** ffecom_subscript_check_ (tree array, tre
*** 714,719 ****
--- 715,724 ----
          }
      }

+   /* If the array index is safe at compile-time, return element.  */
+   if (integer_nonzerop (cond))
+     return element;
+
    {
      int len;
      char *proc;
*************** ffecom_subscript_check_ (tree array, tre
*** 808,820 ****
    TREE_SIDE_EFFECTS (die) = 1;
    die = convert (void_type_node, die);

!   element = ffecom_3 (COND_EXPR,
! 		      TREE_TYPE (element),
! 		      cond,
! 		      element,
! 		      die);

!   return element;
  }

  /* Return the computed element of an array reference.
--- 813,822 ----
    TREE_SIDE_EFFECTS (die) = 1;
    die = convert (void_type_node, die);

!   if (integer_zerop (cond) && item)
!     ffe_mark_addressable (item);

!   return ffecom_3 (COND_EXPR, TREE_TYPE (element), cond, element, die);
  }

  /* Return the computed element of an array reference.
*************** ffecom_arrayref_ (tree item, ffebld expr
*** 900,906 ****
  	  element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
  	  if (flag_bounds_check)
  	    element = ffecom_subscript_check_ (array, element, i, total_dims,
! 					       array_name);
  	  if (element == error_mark_node)
  	    return element;

--- 902,908 ----
  	  element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
  	  if (flag_bounds_check)
  	    element = ffecom_subscript_check_ (array, element, i, total_dims,
! 					       array_name, item);
  	  if (element == error_mark_node)
  	    return element;

*************** ffecom_arrayref_ (tree item, ffebld expr
*** 946,952 ****
  	  element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
  	  if (flag_bounds_check)
  	    element = ffecom_subscript_check_ (array, element, i, total_dims,
! 					       array_name);
  	  if (element == error_mark_node)
  	    return element;

--- 948,954 ----
  	  element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
  	  if (flag_bounds_check)
  	    element = ffecom_subscript_check_ (array, element, i, total_dims,
! 					       array_name, item);
  	  if (element == error_mark_node)
  	    return element;

*************** ffecom_char_args_x_ (tree *xitem, tree *
*** 2045,2051 ****
  		end_tree = ffecom_expr (end);
  		if (flag_bounds_check)
  		  end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
! 						      char_name);
  		end_tree = convert (ffecom_f2c_ftnlen_type_node,
  				    end_tree);

--- 2047,2053 ----
  		end_tree = ffecom_expr (end);
  		if (flag_bounds_check)
  		  end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
! 						      char_name, NULL_TREE);
  		end_tree = convert (ffecom_f2c_ftnlen_type_node,
  				    end_tree);

*************** ffecom_char_args_x_ (tree *xitem, tree *
*** 2063,2069 ****
  	    start_tree = ffecom_expr (start);
  	    if (flag_bounds_check)
  	      start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
! 						    char_name);
  	    start_tree = convert (ffecom_f2c_ftnlen_type_node,
  				  start_tree);

--- 2065,2071 ----
  	    start_tree = ffecom_expr (start);
  	    if (flag_bounds_check)
  	      start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
! 						    char_name, NULL_TREE);
  	    start_tree = convert (ffecom_f2c_ftnlen_type_node,
  				  start_tree);

*************** ffecom_char_args_x_ (tree *xitem, tree *
*** 2096,2102 ****
  		end_tree = ffecom_expr (end);
  		if (flag_bounds_check)
  		  end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
! 						      char_name);
  		end_tree = convert (ffecom_f2c_ftnlen_type_node,
  				    end_tree);

--- 2098,2104 ----
  		end_tree = ffecom_expr (end);
  		if (flag_bounds_check)
  		  end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
! 						      char_name, NULL_TREE);
  		end_tree = convert (ffecom_f2c_ftnlen_type_node,
  				    end_tree);



C { dg-do compile }
C { dg-options "-fbounds-check" }
       INTEGER I(1)
       I(2) = 0  ! { dg-error "out of defined range" "out of defined range" }
       END


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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