Commit 4f4e722e by Richard Guenther Committed by Richard Biener

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
parent 727e8544
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.
2009-08-10 Dodji Seketeli <dodji@redhat.com> 2009-08-10 Dodji Seketeli <dodji@redhat.com>
PR c++/40866 PR c++/40866
......
2009-08-10 Richard Guenther <rguenther@suse.de>
PR middle-end/41006
* gcc.c-torture/compile/pr41006-1.c: New testcase.
* gcc.c-torture/compile/pr41006-2.c: Likewise.
2009-08-10 Janus Weil <janus@gcc.gnu.org> 2009-08-10 Janus Weil <janus@gcc.gnu.org>
PR fortran/40940 PR fortran/40940
......
typedef int (*FARPROC)();
typedef int (*LPFN_ACCEPTEX)(void*);
static LPFN_ACCEPTEX acceptex_fn;
int xWSAIoctl(void*);
static void get_fn(FARPROC* fn)
{
FARPROC func;
if (!xWSAIoctl( &func))
*fn = func;
}
void get_fn_pointers()
{
get_fn((FARPROC*)&acceptex_fn);
}
typedef int *FARPROC;
static int * __restrict__ acceptex_fn;
int xWSAIoctl(void*);
static void get_fn(FARPROC* fn)
{
FARPROC func;
if (!xWSAIoctl( &func))
*fn = func;
}
void get_fn_pointers()
{
get_fn((FARPROC*)&acceptex_fn);
}
...@@ -844,10 +844,31 @@ delete_tree_ssa (void) ...@@ -844,10 +844,31 @@ delete_tree_ssa (void)
redirect_edge_var_map_destroy (); 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 This function implicitly defines the middle-end type system. With
useless_type_conversion_p_1 (tree outer_type, tree inner_type) 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. */ /* Do the following before stripping toplevel qualifiers. */
if (POINTER_TYPE_P (inner_type) if (POINTER_TYPE_P (inner_type)
...@@ -909,6 +930,16 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type) ...@@ -909,6 +930,16 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type)
else if (POINTER_TYPE_P (inner_type) else if (POINTER_TYPE_P (inner_type)
&& POINTER_TYPE_P (outer_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 /* Don't lose casts between pointers to volatile and non-volatile
qualified types. Doing so would result in changing the semantics qualified types. Doing so would result in changing the semantics
of later accesses. For function types the volatile qualifier of later accesses. For function types the volatile qualifier
...@@ -938,8 +969,11 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type) ...@@ -938,8 +969,11 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type)
/* Otherwise pointers/references are equivalent if their pointed /* Otherwise pointers/references are equivalent if their pointed
to types are effectively the same. We can strip qualifiers to types are effectively the same. We can strip qualifiers
on pointed-to types for further comparison, which is done in on pointed-to types for further comparison, which is done in
the callee. */ the callee. Note we have to use true compatibility here
return useless_type_conversion_p_1 (TREE_TYPE (outer_type), 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)); TREE_TYPE (inner_type));
} }
...@@ -1083,48 +1117,6 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type) ...@@ -1083,48 +1117,6 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type)
return false; 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 /* Return true if a conversion from either type of TYPE1 and TYPE2
to the other is not required. Otherwise return false. */ to the other is not required. Otherwise return false. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment