diff options
author | Richard Guenther <rguenther@suse.de> | 2009-08-10 09:22:47 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2009-08-10 09:22:47 +0000 |
commit | 4f4e722eb62eaddb1313c09dfc0fa5d094d78148 (patch) | |
tree | 0ad55d17f476854e6ffa83832fc420057243cc73 /gcc/tree-ssa.c | |
parent | 727e85447dbd3342ca487b7179dc8a06a853f681 (diff) | |
download | gcc-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.c | 88 |
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. */ |