aboutsummaryrefslogtreecommitdiff
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
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
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr41006-1.c17
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr41006-2.c15
-rw-r--r--gcc/tree-ssa.c88
5 files changed, 85 insertions, 48 deletions
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 <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>
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 <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>
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. */