From 4f4e722eb62eaddb1313c09dfc0fa5d094d78148 Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Mon, 10 Aug 2009 09:22:47 +0000 Subject: [PATCH] re PR middle-end/41006 (verify_stmts failed: error: non-trivial conversion at assignment) 2009-08-10 Richard Guenther 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 --- gcc/ChangeLog | 7 ++ gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/gcc.c-torture/compile/pr41006-1.c | 17 +++++ gcc/testsuite/gcc.c-torture/compile/pr41006-2.c | 15 +++++ gcc/tree-ssa.c | 88 +++++++++++-------------- 5 files changed, 85 insertions(+), 48 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr41006-1.c create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr41006-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 026d176..d03d922 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2009-08-10 Richard Guenther + + 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 PR c++/40866 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d1e2b1d..c4be548 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2009-08-10 Richard Guenther + + 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 PR fortran/40940 diff --git a/gcc/testsuite/gcc.c-torture/compile/pr41006-1.c b/gcc/testsuite/gcc.c-torture/compile/pr41006-1.c new file mode 100644 index 0000000..8aef66d --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr41006-1.c @@ -0,0 +1,17 @@ +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); +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr41006-2.c b/gcc/testsuite/gcc.c-torture/compile/pr41006-2.c new file mode 100644 index 0000000..766778d --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr41006-2.c @@ -0,0 +1,15 @@ +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); +} 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. */ -- 2.7.4