OSDN Git Service

2007-07-04 Douglas Gregor <doug.gregor@gmail.com>
authordgregor <dgregor@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 4 Jul 2007 06:32:30 +0000 (06:32 +0000)
committerdgregor <dgregor@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 4 Jul 2007 06:32:30 +0000 (06:32 +0000)
* tree.c (maybe_canonicalize_argtypes): New.
(build_function_type): Set canonical type.
(build_method_type_directly): Ditto.
(reconstruct_complex_type): Rebuild the METHOD_TYPE node
properly.

2007-07-04  Douglas Gregor  <doug.gregor@gmail.com>

* decl.c (build_ptrmemfunc_type): Always use structural equality
tests when comparing pointer-to-member-function types, because the
handling of TYPE_GET_PTRMEMFUNC_TYPE currently defeats canonical
types.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@126303 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/tree.c

index dc785cb..abeacc3 100644 (file)
@@ -1,3 +1,11 @@
+2007-07-04  Douglas Gregor  <doug.gregor@gmail.com>
+
+       * tree.c (maybe_canonicalize_argtypes): New.
+       (build_function_type): Set canonical type.
+       (build_method_type_directly): Ditto.
+       (reconstruct_complex_type): Rebuild the METHOD_TYPE node
+       properly.
+
 2007-07-03  Andrew Pinski  <andrew_pinski@playstation.sony.com>
 
        * tree-ssa-loop-ivopts.c (strip_offset_1): Treat POINTER_PLUS_EXPR
index 17b76c0..1621175 100644 (file)
@@ -1,3 +1,10 @@
+2007-07-04  Douglas Gregor  <doug.gregor@gmail.com>
+
+       * decl.c (build_ptrmemfunc_type): Always use structural equality
+       tests when comparing pointer-to-member-function types, because the
+       handling of TYPE_GET_PTRMEMFUNC_TYPE currently defeats canonical
+       types.
+       
 2007-07-03  Mark Mitchell  <mark@codesourcery.com>
 
        * init.c (build_new): Tweak comment.
index 1fae5f8..630cec1 100644 (file)
@@ -6602,10 +6602,10 @@ build_ptrmemfunc_type (tree type)
      later.  */
   TYPE_SET_PTRMEMFUNC_TYPE (type, t);
 
-  if (TYPE_STRUCTURAL_EQUALITY_P (type))
-    SET_TYPE_STRUCTURAL_EQUALITY (t);
-  else if (TYPE_CANONICAL (type) != type)
-    TYPE_CANONICAL (t) = build_ptrmemfunc_type (TYPE_CANONICAL (type));
+  /* Managing canonical types for the RECORD_TYPE behind a
+     pointer-to-member function is a nightmare, so use structural
+     equality for now.  */
+  SET_TYPE_STRUCTURAL_EQUALITY (t);
 
   return t;
 }
index 72a2593..8feaf47 100644 (file)
@@ -5647,6 +5647,82 @@ get_inner_array_type (tree array)
   return type;
 }
 
+/* Computes the canonical argument types from the argument type list
+   ARGTYPES. 
+
+   ANY_STRUCTURAL_P points to a boolean that states whether any of the
+   other types that work with ARGTYPES (e.g., the return type of the
+   function) are structural. *ANY_STRUCTURAL_P will be set TRUE if any
+   of those types or any of the argument types in ARGTYPES are
+   structural.
+
+   ANY_NONCANONICAL_P points to a boolean that states whether any of
+   the other types that work with ARGTYPES (e.g., the return type of
+   the function) are non-canonical type nodes. *ANY_NONCANONICAL_P
+   will be set TRUE if any of those types or any of the argument types
+   in ARGTYPES are non-canonical.
+
+   Returns a canonical argument list, which may be ARGTYPES when the
+   canonical argument list is unneeded (i.e., *ANY_STRUCTURAL_P is
+   true) or would not differ from ARGTYPES.  */
+
+static tree 
+maybe_canonicalize_argtypes(tree argtypes, 
+                           bool *any_structural_p,
+                           bool *any_noncanonical_p)
+{
+  tree arg;
+  bool any_noncanonical_argtypes_p = false;
+  
+  for (arg = argtypes; arg && !(*any_structural_p); arg = TREE_CHAIN (arg))
+    {
+      if (!TREE_VALUE (arg) || TREE_VALUE (arg) == error_mark_node)
+       /* Fail gracefully by stating that the type is structural.  */
+       *any_structural_p = true;
+      else if (TYPE_STRUCTURAL_EQUALITY_P (TREE_VALUE (arg)))
+       *any_structural_p = true;
+      else if (TYPE_CANONICAL (TREE_VALUE (arg)) != TREE_VALUE (arg)
+              || TREE_PURPOSE (arg))
+       /* If the argument has a default argument, we consider it
+          non-canonical even though the type itself is canonical.
+          That way, different variants of function and method types
+          with default arguments will all point to the variant with
+          no defaults as their canonical type.  */
+        any_noncanonical_argtypes_p = true;
+    }
+
+  if (*any_structural_p)
+    return argtypes;
+
+  if (any_noncanonical_argtypes_p)
+    {
+      /* Build the canonical list of argument types.  */
+      tree canon_argtypes = NULL_TREE;
+      bool is_void = false;
+
+      for (arg = argtypes; arg; arg = TREE_CHAIN (arg))
+        {
+          if (arg == void_list_node)
+            is_void = true;
+          else
+            canon_argtypes = tree_cons (NULL_TREE,
+                                        TYPE_CANONICAL (TREE_VALUE (arg)),
+                                        canon_argtypes);
+        }
+
+      canon_argtypes = nreverse (canon_argtypes);
+      if (is_void)
+        canon_argtypes = chainon (canon_argtypes, void_list_node);
+
+      /* There is a non-canonical type.  */
+      *any_noncanonical_p = true;
+      return canon_argtypes;
+    }
+
+  /* The canonical argument types are the same as ARGTYPES.  */
+  return argtypes;
+}
+
 /* Construct, lay out and return
    the type of functions returning type VALUE_TYPE
    given arguments of types ARG_TYPES.
@@ -5659,6 +5735,8 @@ build_function_type (tree value_type, tree arg_types)
 {
   tree t;
   hashval_t hashcode = 0;
+  bool any_structural_p, any_noncanonical_p;
+  tree canon_argtypes;
 
   if (TREE_CODE (value_type) == FUNCTION_TYPE)
     {
@@ -5671,14 +5749,23 @@ build_function_type (tree value_type, tree arg_types)
   TREE_TYPE (t) = value_type;
   TYPE_ARG_TYPES (t) = arg_types;
 
-  /* We don't have canonicalization of function types, yet. */
-  SET_TYPE_STRUCTURAL_EQUALITY (t);
-
   /* If we already have such a type, use the old one.  */
   hashcode = iterative_hash_object (TYPE_HASH (value_type), hashcode);
   hashcode = type_hash_list (arg_types, hashcode);
   t = type_hash_canon (hashcode, t);
 
+  /* Set up the canonical type. */
+  any_structural_p   = TYPE_STRUCTURAL_EQUALITY_P (value_type);
+  any_noncanonical_p = TYPE_CANONICAL (value_type) != value_type;
+  canon_argtypes = maybe_canonicalize_argtypes (arg_types, 
+                                               &any_structural_p,
+                                               &any_noncanonical_p);
+  if (any_structural_p)
+    SET_TYPE_STRUCTURAL_EQUALITY (t);
+  else if (any_noncanonical_p)
+    TYPE_CANONICAL (t) = build_function_type (TYPE_CANONICAL (value_type),
+                                             canon_argtypes);
+      
   if (!COMPLETE_TYPE_P (t))
     layout_type (t);
   return t;
@@ -5728,6 +5815,8 @@ build_method_type_directly (tree basetype,
   tree t;
   tree ptype;
   int hashcode = 0;
+  bool any_structural_p, any_noncanonical_p;
+  tree canon_argtypes;
 
   /* Make a node of the sort we want.  */
   t = make_node (METHOD_TYPE);
@@ -5741,15 +5830,29 @@ build_method_type_directly (tree basetype,
   argtypes = tree_cons (NULL_TREE, ptype, argtypes);
   TYPE_ARG_TYPES (t) = argtypes;
 
-  /* We don't have canonicalization of method types yet. */
-  SET_TYPE_STRUCTURAL_EQUALITY (t);
-
   /* If we already have such a type, use the old one.  */
   hashcode = iterative_hash_object (TYPE_HASH (basetype), hashcode);
   hashcode = iterative_hash_object (TYPE_HASH (rettype), hashcode);
   hashcode = type_hash_list (argtypes, hashcode);
   t = type_hash_canon (hashcode, t);
 
+  /* Set up the canonical type. */
+  any_structural_p
+    = (TYPE_STRUCTURAL_EQUALITY_P (basetype)
+       || TYPE_STRUCTURAL_EQUALITY_P (rettype));
+  any_noncanonical_p
+    = (TYPE_CANONICAL (basetype) != basetype
+       || TYPE_CANONICAL (rettype) != rettype);
+  canon_argtypes = maybe_canonicalize_argtypes (TREE_CHAIN (argtypes),
+                                               &any_structural_p,
+                                               &any_noncanonical_p);
+  if (any_structural_p)
+    SET_TYPE_STRUCTURAL_EQUALITY (t);
+  else if (any_noncanonical_p)
+    TYPE_CANONICAL (t) 
+      = build_method_type_directly (TYPE_CANONICAL (basetype),
+                                   TYPE_CANONICAL (rettype),
+                                   canon_argtypes);
   if (!COMPLETE_TYPE_P (t))
     layout_type (t);
 
@@ -7329,15 +7432,14 @@ reconstruct_complex_type (tree type, tree bottom)
     }
   else if (TREE_CODE (type) == METHOD_TYPE)
     {
-      tree argtypes;
       inner = reconstruct_complex_type (TREE_TYPE (type), bottom);
       /* The build_method_type_directly() routine prepends 'this' to argument list,
          so we must compensate by getting rid of it.  */
-      argtypes = TYPE_ARG_TYPES (type);
-      outer = build_method_type_directly (TYPE_METHOD_BASETYPE (type),
-                                         inner,
-                                         TYPE_ARG_TYPES (type));
-      TYPE_ARG_TYPES (outer) = argtypes;
+      outer 
+       = build_method_type_directly 
+           (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))),
+            inner,
+            TREE_CHAIN (TYPE_ARG_TYPES (type)));
     }
   else
     return bottom;