re PR middle-end/41006 (verify_stmts failed: error: non-trivial conversion at assignment)
authorRichard Guenther <rguenther@suse.de>
Mon, 10 Aug 2009 09:22:47 +0000 (09:22 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 10 Aug 2009 09:22:47 +0000 (09:22 +0000)
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

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr41006-1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/compile/pr41006-2.c [new file with mode: 0644]
gcc/tree-ssa.c

index 026d176..d03d922 100644 (file)
@@ -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
index d1e2b1d..c4be548 100644 (file)
@@ -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 (file)
index 0000000..8aef66d
--- /dev/null
@@ -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 (file)
index 0000000..766778d
--- /dev/null
@@ -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);
+}
index ddd4cfb..97e15ae 100644 (file)
@@ -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.  */