aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa.c
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2009-08-10 09:22:47 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2009-08-10 09:22:47 +0000
commit4f4e722eb62eaddb1313c09dfc0fa5d094d78148 (patch)
tree0ad55d17f476854e6ffa83832fc420057243cc73 /gcc/tree-ssa.c
parent727e85447dbd3342ca487b7179dc8a06a853f681 (diff)
downloadgcc-4f4e722eb62eaddb1313c09dfc0fa5d094d78148.zip
gcc-4f4e722eb62eaddb1313c09dfc0fa5d094d78148.tar.gz
gcc-4f4e722eb62eaddb1313c09dfc0fa5d094d78148.tar.bz2
re PR middle-end/41006 (verify_stmts failed: error: non-trivial conversion at assignment)
2009-08-10 Richard Guenther <rguenther@suse.de> PR middle-end/41006 * tree-ssa.c (useless_type_conversion_p_1): Fold into ... (useless_type_conversion_p): ... here. Require pointer targets to be compatible. * gcc.c-torture/compile/pr41006-1.c: New testcase. * gcc.c-torture/compile/pr41006-2.c: Likewise. From-SVN: r150621
Diffstat (limited to 'gcc/tree-ssa.c')
-rw-r--r--gcc/tree-ssa.c88
1 files changed, 40 insertions, 48 deletions
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index ddd4cfb..97e15ae 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -844,10 +844,31 @@ delete_tree_ssa (void)
redirect_edge_var_map_destroy ();
}
-/* Helper function for useless_type_conversion_p. */
+/* Return true if the conversion from INNER_TYPE to OUTER_TYPE is a
+ useless type conversion, otherwise return false.
-static bool
-useless_type_conversion_p_1 (tree outer_type, tree inner_type)
+ 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)
{
/* Do the following before stripping toplevel qualifiers. */
if (POINTER_TYPE_P (inner_type)
@@ -909,6 +930,16 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type)
else if (POINTER_TYPE_P (inner_type)
&& POINTER_TYPE_P (outer_type))
{
+ /* If the outer type is (void *) or a pointer to an incomplete
+ record type, then the conversion is not necessary. */
+ if (VOID_TYPE_P (TREE_TYPE (outer_type))
+ || (AGGREGATE_TYPE_P (TREE_TYPE (outer_type))
+ && TREE_CODE (TREE_TYPE (outer_type)) != ARRAY_TYPE
+ && (TREE_CODE (TREE_TYPE (outer_type))
+ == TREE_CODE (TREE_TYPE (inner_type)))
+ && !COMPLETE_TYPE_P (TREE_TYPE (outer_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. For function types the volatile qualifier
@@ -938,9 +969,12 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type)
/* Otherwise pointers/references are equivalent if their pointed
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));
+ the callee. Note we have to use true compatibility here
+ because addresses are subject to propagation into dereferences
+ and thus might get the original type exposed which is equivalent
+ to a reverse conversion. */
+ return types_compatible_p (TREE_TYPE (outer_type),
+ TREE_TYPE (inner_type));
}
/* Recurse for complex types. */
@@ -1083,48 +1117,6 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type)
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 *) or a pointer to an incomplete record type,
- 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)
- && (VOID_TYPE_P (TREE_TYPE (outer_type))
- || (AGGREGATE_TYPE_P (TREE_TYPE (outer_type))
- && TREE_CODE (TREE_TYPE (outer_type)) != ARRAY_TYPE
- && (TREE_CODE (TREE_TYPE (outer_type))
- == TREE_CODE (TREE_TYPE (inner_type)))
- && !COMPLETE_TYPE_P (TREE_TYPE (outer_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. */