OSDN Git Service

2009-08-17 Emmanuel Briot <briot@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa.c
index ddd4cfb..76e4e8b 100644 (file)
@@ -844,15 +844,46 @@ 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)
       && 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;
+
       /* Do not lose casts to restrict qualified pointers.  */
       if ((TYPE_RESTRICT (outer_type)
           != TYPE_RESTRICT (inner_type))
@@ -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.  */
@@ -1068,63 +1102,16 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type)
       return true;
     }
 
-  /* For aggregates we may need to fall back to structural equality
-     checks.  */
+  /* For aggregates we rely on TYPE_CANONICAL exclusively and require
+     explicit conversions for types involving to be structurally
+     compared types.  */
   else if (AGGREGATE_TYPE_P (inner_type)
           && TREE_CODE (inner_type) == TREE_CODE (outer_type))
-    {
-      if (TYPE_STRUCTURAL_EQUALITY_P (outer_type)
-         || TYPE_STRUCTURAL_EQUALITY_P (inner_type))
-       return lang_hooks.types_compatible_p (inner_type, outer_type);
-
-      return false;
-    }
+    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
    to the other is not required.  Otherwise return false.  */