+2006-05-11 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/27529
+ * fold-const.c (fold_unary): Handle intermediate conversion
+ to a pointer type like intermediate conversion to an integer
+ type in folding of (T1)(T2)var to var.
+ Match the code to the comment in the final conversion for
+ (T1)(T2)var to (T1)var regarding to type precision. Rather
+ than disallow T1 being of pointer type, assert that both T1
+ and var are of pointer type or not. Make sure not to fall
+ over the frontends lazyness wrt array to pointer decay though.
+
2006-05-10 Richard Earnshaw <rearnsha@arm.com>
* arm.c (arm_struct_value_rtx): Delete.
type via an object of identical or wider precision, neither
conversion is needed. */
if (TYPE_MAIN_VARIANT (inside_type) == TYPE_MAIN_VARIANT (type)
- && ((inter_int && final_int) || (inter_float && final_float))
+ && (((inter_int || inter_ptr) && final_int)
+ || (inter_float && final_float))
&& inter_prec >= final_prec)
return fold_build1 (code, type, TREE_OPERAND (op0, 0));
- the initial type is a pointer type and the precisions of the
intermediate and final types differ, or
- the final type is a pointer type and the precisions of the
- initial and intermediate types differ. */
+ initial and intermediate types differ.
+ - the final type is a pointer type and the initial type not
+ - the initial type is a pointer to an array and the final type
+ not. */
if (! inside_float && ! inter_float && ! final_float
&& ! inside_vec && ! inter_vec && ! final_vec
- && (inter_prec > inside_prec || inter_prec > final_prec)
+ && (inter_prec >= inside_prec || inter_prec >= final_prec)
&& ! (inside_int && inter_int
&& inter_unsignedp != inside_unsignedp
&& inter_prec < final_prec)
&& ! (final_ptr && inside_prec != inter_prec)
&& ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type))
&& TYPE_MODE (type) == TYPE_MODE (inter_type))
- && ! final_ptr)
+ && final_ptr == inside_ptr
+ && ! (inside_ptr
+ && TREE_CODE (TREE_TYPE (inside_type)) == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE))
return fold_build1 (code, type, TREE_OPERAND (op0, 0));
}
--- /dev/null
+/* { dg-do "compile" } */
+/* { dg-options "-fdump-tree-original" } */
+
+typedef int ssize_t __attribute__((mode(pointer)));
+ssize_t foo (ssize_t x)
+{
+ return (ssize_t)(char *)x;
+}
+
+char *bar (char *x)
+{
+ return (char *)(ssize_t)x;
+}
+
+/* { dg-final { scan-tree-dump-times "return x;" 2 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */