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] Fix PR33166, slight adjustment to the type-system


In this PR we end up with missing casts due to us at the moment
stripping casts to (void *) recursively.  That is, also casts from
(char **) to (void **).  This is wrong and not consistent with
the reasoning that you cannot do anything with a (void *) pointer
and so it's ok to strip casts to it.

The fix is to strip casts to (void *) non-recursively only.  Which
leaves us with fold_stmt_r stripping the cast which is fixed like
I fixed some other occurances of maybe_fold_offset_to_reference.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to mainline.

Richard.

2007-08-24  Richard Guenther  <rguenther@suse.de>

	PR middle-end/33166
	* tree-ssa.c (useless_type_conversion_p): Split into a
	recursive and a non-recursive part.
	(useless_type_conversion_p_1): New function.
	* tree-ssa-ccp.c (fold_stmt_r): Make sure that the result
	from maybe_fold_offset_to_reference is trivially convertible
	to the desired type before doing the simplification.

	* gcc.c-torture/compile/pr33166.c: New testcase.

Index: tree-ssa.c
===================================================================
*** tree-ssa.c	(revision 127700)
--- tree-ssa.c	(working copy)
*************** delete_tree_ssa (void)
*** 885,916 ****
    cfun->gimple_df = NULL;
  }
  
  
! /* Return true if the conversion from INNER_TYPE to OUTER_TYPE is a
!    useless type conversion, otherwise return false.
! 
!    This function implicitly defines the middle-end type system.  With
!    the notion of 'a < b' meaning that useless_type_conversion_p (a, b)
!    holds and 'a > b' meaning that useless_type_conversion_p (b, a) holds,
!    the following invariants shall be fulfilled:
! 
!      1) useless_type_conversion_p is transitive.
! 	If a < b and b < c then a < c.
! 
!      2) useless_type_conversion_p is not symmetric.
! 	From a < b does not follow a > b.
! 
!      3) Types define the available set of operations applicable to values.
! 	A type conversion is useless if the operations for the target type
! 	is a subset of the operations for the source type.  For example
! 	casts to void* are useless, casts from void* are not (void* can't
! 	be dereferenced or offsetted, but copied, hence its set of operations
! 	is a strict subset of that of all other data pointer types).  Casts
! 	to const T* are useless (can't be written to), casts from const T*
! 	to T* are not.  */
! 
! bool
! useless_type_conversion_p (tree outer_type, tree inner_type)
  {
    /* Qualifiers on value types do not matter.  */
    inner_type = TYPE_MAIN_VARIANT (inner_type);
--- 885,894 ----
    cfun->gimple_df = NULL;
  }
  
+ /* Helper function for useless_type_conversion_p.  */
  
! static bool
! useless_type_conversion_p_1 (tree outer_type, tree inner_type)
  {
    /* Qualifiers on value types do not matter.  */
    inner_type = TYPE_MAIN_VARIANT (inner_type);
*************** useless_type_conversion_p (tree outer_ty
*** 964,974 ****
    else if (POINTER_TYPE_P (inner_type)
  	   && POINTER_TYPE_P (outer_type))
      {
-       /* If the outer type is (void *), then the conversion is not
- 	 necessary.  */
-       if (TREE_CODE (TREE_TYPE (outer_type)) == VOID_TYPE)
- 	return true;
- 
        /* Don't lose casts between pointers to volatile and non-volatile
  	 qualified types.  Doing so would result in changing the semantics
  	 of later accesses.  */
--- 942,947 ----
*************** useless_type_conversion_p (tree outer_ty
*** 1002,1023 ****
  	 to types are effectively the same.  We can strip qualifiers
  	 on pointed-to types for further comparison, which is done in
  	 the callee.  */
!       return useless_type_conversion_p (TREE_TYPE (outer_type),
! 				        TREE_TYPE (inner_type));
      }
  
    /* Recurse for complex types.  */
    else if (TREE_CODE (inner_type) == COMPLEX_TYPE
  	   && TREE_CODE (outer_type) == COMPLEX_TYPE)
!     return useless_type_conversion_p (TREE_TYPE (outer_type),
! 				      TREE_TYPE (inner_type));
  
    /* Recurse for vector types with the same number of subparts.  */
    else if (TREE_CODE (inner_type) == VECTOR_TYPE
  	   && TREE_CODE (outer_type) == VECTOR_TYPE
  	   && TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type))
!     return useless_type_conversion_p (TREE_TYPE (outer_type),
! 				      TREE_TYPE (inner_type));
  
    /* For aggregates we may need to fall back to structural equality
       checks.  */
--- 975,996 ----
  	 to types are effectively the same.  We can strip qualifiers
  	 on pointed-to types for further comparison, which is done in
  	 the callee.  */
!       return useless_type_conversion_p_1 (TREE_TYPE (outer_type),
! 				          TREE_TYPE (inner_type));
      }
  
    /* Recurse for complex types.  */
    else if (TREE_CODE (inner_type) == COMPLEX_TYPE
  	   && TREE_CODE (outer_type) == COMPLEX_TYPE)
!     return useless_type_conversion_p_1 (TREE_TYPE (outer_type),
! 				        TREE_TYPE (inner_type));
  
    /* Recurse for vector types with the same number of subparts.  */
    else if (TREE_CODE (inner_type) == VECTOR_TYPE
  	   && TREE_CODE (outer_type) == VECTOR_TYPE
  	   && TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type))
!     return useless_type_conversion_p_1 (TREE_TYPE (outer_type),
! 				        TREE_TYPE (inner_type));
  
    /* For aggregates we may need to fall back to structural equality
       checks.  */
*************** useless_type_conversion_p (tree outer_ty
*** 1037,1042 ****
--- 1010,1052 ----
    return false;
  }
  
+ /* Return true if the conversion from INNER_TYPE to OUTER_TYPE is a
+    useless type conversion, otherwise return false.
+ 
+    This function implicitly defines the middle-end type system.  With
+    the notion of 'a < b' meaning that useless_type_conversion_p (a, b)
+    holds and 'a > b' meaning that useless_type_conversion_p (b, a) holds,
+    the following invariants shall be fulfilled:
+ 
+      1) useless_type_conversion_p is transitive.
+ 	If a < b and b < c then a < c.
+ 
+      2) useless_type_conversion_p is not symmetric.
+ 	From a < b does not follow a > b.
+ 
+      3) Types define the available set of operations applicable to values.
+ 	A type conversion is useless if the operations for the target type
+ 	is a subset of the operations for the source type.  For example
+ 	casts to void* are useless, casts from void* are not (void* can't
+ 	be dereferenced or offsetted, but copied, hence its set of operations
+ 	is a strict subset of that of all other data pointer types).  Casts
+ 	to const T* are useless (can't be written to), casts from const T*
+ 	to T* are not.  */
+ 
+ bool
+ useless_type_conversion_p (tree outer_type, tree inner_type)
+ {
+   /* If the outer type is (void *), then the conversion is not
+      necessary.  We have to make sure to not apply this while
+      recursing though.  */
+   if (POINTER_TYPE_P (inner_type)
+       && POINTER_TYPE_P (outer_type)
+       && TREE_CODE (TREE_TYPE (outer_type)) == VOID_TYPE)
+     return true;
+ 
+   return useless_type_conversion_p_1 (outer_type, inner_type);
+ }
+ 
  /* Return true if a conversion from either type of TYPE1 and TYPE2
     to the other is not required.  Otherwise return false.  */
  
Index: tree-ssa-ccp.c
===================================================================
*** tree-ssa-ccp.c	(revision 127700)
--- tree-ssa-ccp.c	(working copy)
*************** fold_stmt_r (tree *expr_p, int *walk_sub
*** 2060,2066 ****
  		      (TREE_OPERAND (expr, 0),
  		       integer_zero_node,
  		       TREE_TYPE (TREE_TYPE (expr)))))
!         t = build_fold_addr_expr_with_type (t, TREE_TYPE (expr));
        break;
  
        /* ??? Could handle more ARRAY_REFs here, as a variant of INDIRECT_REF.
--- 2060,2071 ----
  		      (TREE_OPERAND (expr, 0),
  		       integer_zero_node,
  		       TREE_TYPE (TREE_TYPE (expr)))))
! 	{
! 	  tree ptr_type = build_pointer_type (TREE_TYPE (t));
! 	  if (!useless_type_conversion_p (TREE_TYPE (expr), ptr_type))
! 	    return NULL_TREE;
!           t = build_fold_addr_expr_with_type (t, ptr_type);
! 	}
        break;
  
        /* ??? Could handle more ARRAY_REFs here, as a variant of INDIRECT_REF.
Index: testsuite/gcc.c-torture/compile/pr33166.c
===================================================================
*** testsuite/gcc.c-torture/compile/pr33166.c	(revision 0)
--- testsuite/gcc.c-torture/compile/pr33166.c	(revision 0)
***************
*** 0 ****
--- 1,10 ----
+ static void ConvertAddr (char *saddr, void **addr)
+ {
+   *addr = (void *) &saddr;
+ }
+ void DefineSelf (char *addr)
+ {
+   ConvertAddr (addr, (void **) &addr);
+   if (addr[0] == 127 && addr[3] == 1)
+     ;
+ }


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