This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR33166, slight adjustment to the type-system
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 24 Aug 2007 17:12:57 +0200 (CEST)
- Subject: [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)
+ ;
+ }