decl.c (xref_basetypes): Refactor.
authorNathan Sidwell <nathan@codesourcery.com>
Thu, 15 Jul 2004 16:15:52 +0000 (16:15 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Thu, 15 Jul 2004 16:15:52 +0000 (16:15 +0000)
* decl.c (xref_basetypes): Refactor.
* tree.c (copy_base_binfos): Replace with ...
(copy_binfo): ... this. Deep copy the given binfo, (not the just
bases of the given base).
* cp-tree.h (copy_base_binfo): Remove.
(copy_binfo): Declare.

From-SVN: r84758

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

index e5c87a61800aaa39364d01f4f3f2ed1305c7717a..c93ce695675e1089935759957aa96c30831835c0 100644 (file)
@@ -1,3 +1,12 @@
+2004-07-15  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * decl.c (xref_basetypes): Refactor.
+       * tree.c (copy_base_binfos): Replace with ...
+       (copy_binfo): ... this. Deep copy the given binfo, (not the just
+       bases of the given base).
+       * cp-tree.h (copy_base_binfo): Remove.
+       (copy_binfo): Declare.
+
 2004-07-15  Mark Mitchell  <mark@codesourcery.com>
 
        * name-lookup.c (set_inherited_value_binding_p): Add class_type 
index 95c633a1f422bd3e50541b62b695ced8939d1d96..1e921d823d29b7b55d6a3ec348d2213f4f87e99e 100644 (file)
@@ -4145,7 +4145,8 @@ extern void init_tree                             (void);
 extern int pod_type_p                          (tree);
 extern int zero_init_p                         (tree);
 extern tree canonical_type_variant              (tree);
-extern tree copy_base_binfos                   (tree, tree, tree);
+extern tree copy_binfo                         (tree, tree, tree,
+                                                tree *, int);
 extern int member_p                            (tree);
 extern cp_lvalue_kind real_lvalue_p             (tree);
 extern int lvalue_or_else                      (tree, const char *);
index 1c547f641f9a83707666a96f1dcb85f28abd1f07..6aac5bae5474cfa7bf5085f05b664668946c0268 100644 (file)
@@ -9024,28 +9024,30 @@ xref_tag_from_type (tree old, tree id, int globalize)
   return xref_tag (tag_kind, id, globalize, false);
 }
 
-/* REF is a type (named NAME), for which we have just seen some
-   baseclasses.  BASE_LIST is a list of those baseclasses; the
-   TREE_PURPOSE is an access_* node, and the TREE_VALUE is the type of
-   the base-class.  Non-NULL TREE_TYPE indicates virtual inheritance.
-   CODE_TYPE_NODE indicates whether REF is a class, struct, or
-   union.  */
+/* Create the binfo hierarchy for REF with (possibly NULL) base list
+   BASE_LIST.  For each element on BASE_LIST the TREE_PURPOSE is an
+   access_* node, and the TREE_VALUE is the type of the base-class.
+   Non-NULL TREE_TYPE indicates virtual inheritance.  */
 
 void
 xref_basetypes (tree ref, tree base_list)
 {
-  /* In the declaration `A : X, Y, ... Z' we mark all the types
-     (A, X, Y, ..., Z) so we can check for duplicates.  */
   tree *basep;
-  unsigned max_vbases = 0;
+  tree binfo;
+  unsigned max_vbases = 0; /* Maxium direct & indirect virtual bases. */
+  unsigned max_bases = 0;  /* Maxium direct bases.  */
   int i;
-  enum tag_types tag_code;
+  tree default_access;
+  tree igo_prev; /* Track Inheritance Graph Order.  */
 
   if (ref == error_mark_node)
     return;
 
-  tag_code = TREE_CODE (ref) == UNION_TYPE ? union_type
-    : (CLASSTYPE_DECLARED_CLASS (ref) ? class_type : record_type);
+  /* The base of a derived class is private by default, all others are
+     public.  */
+  default_access = (TREE_CODE (ref) == RECORD_TYPE
+                   && CLASSTYPE_DECLARED_CLASS (ref)
+                   ? access_private_node : access_public_node);
 
   /* First, make sure that any templates in base-classes are
      instantiated.  This ensures that if we call ourselves recursively
@@ -9061,169 +9063,138 @@ xref_basetypes (tree ref, tree base_list)
        /* An incomplete type.  Remove it from the list.  */
        *basep = TREE_CHAIN (*basep);
       else
-       basep = &TREE_CHAIN (*basep);
+       {
+         max_bases++;
+         if (TREE_TYPE (*basep))
+           max_vbases++;
+         if (CLASS_TYPE_P (basetype))
+           max_vbases += VEC_length (tree, CLASSTYPE_VBASECLASSES (basetype));
+         basep = &TREE_CHAIN (*basep);
+       }
     }
 
   SET_CLASSTYPE_MARKED (ref);
-  i = list_length (base_list);
+
   /* The binfo slot should be empty, unless this is an (ill-formed)
      redefinition.  */
   my_friendly_assert (!TYPE_BINFO (ref) || TYPE_SIZE (ref), 20040706);
   my_friendly_assert (TYPE_MAIN_VARIANT (ref) == ref, 20040712);
-  TYPE_BINFO (ref) = make_tree_binfo (BINFO_LANG_SLOTS);
-  BINFO_OFFSET (TYPE_BINFO (ref)) = size_zero_node;
-  BINFO_TYPE (TYPE_BINFO (ref)) = ref;
   
-  if (i)
+  binfo = make_tree_binfo (BINFO_LANG_SLOTS);
+  TYPE_BINFO (ref) = binfo;
+  BINFO_OFFSET (binfo) = size_zero_node;
+  BINFO_TYPE (binfo) = ref;
+  
+  if (max_bases)
+    {
+      BINFO_BASE_BINFOS (binfo) = make_tree_vec (max_bases);
+      BINFO_BASE_ACCESSES (binfo) = make_tree_vec (max_bases);
+      /* An aggregate cannot have baseclasses.  */
+      CLASSTYPE_NON_AGGREGATE (ref) = 1;
+      
+      if (TREE_CODE (ref) == UNION_TYPE)
+       error ("derived union `%T' invalid", ref);
+    }
+      
+  if (max_bases > 1)
     {
-      tree binfo = TYPE_BINFO (ref);
-      tree binfos = make_tree_vec (i);
-      tree accesses = make_tree_vec (i);
+      TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
+      /* If there is more than one non-empty they cannot be at the
+        same address.  */
+      TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
       
-      BINFO_BASE_BINFOS (binfo) = binfos;
-      BINFO_BASE_ACCESSES (binfo) = accesses;
+      if (TYPE_FOR_JAVA (ref))
+       error ("Java class '%T' cannot have multiple bases", ref);
+    }
   
-      for (i = 0; base_list; base_list = TREE_CHAIN (base_list))
-       {
-         tree access = TREE_PURPOSE (base_list);
-         int via_virtual = TREE_TYPE (base_list) != NULL_TREE;
-         tree basetype = TREE_VALUE (base_list);
-         tree base_binfo;
-         
-         if (via_virtual)
-           max_vbases++;
-         if (access == access_default_node)
-           /* The base of a derived struct is public by default.  */
-           access = (tag_code == class_type
-                     ? access_private_node : access_public_node);
-         
-         if (basetype && TREE_CODE (basetype) == TYPE_DECL)
-           basetype = TREE_TYPE (basetype);
-         if (!basetype
-             || (TREE_CODE (basetype) != RECORD_TYPE
-                 && TREE_CODE (basetype) != TYPENAME_TYPE
-                 && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
-                 && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM))
-           {
-             error ("base type `%T' fails to be a struct or class type",
-                    basetype);
-             continue;
-           }
-         
-         if (CLASSTYPE_MARKED (basetype))
-           {
-             if (basetype == ref)
-               error ("recursive type `%T' undefined", basetype);
-             else
-               error ("duplicate base type `%T' invalid", basetype);
-             continue;
-           }
-         
-         if (TYPE_FOR_JAVA (basetype)
-             && (current_lang_depth () == 0))
-           TYPE_FOR_JAVA (ref) = 1;
-         
-         if (CLASS_TYPE_P (basetype) && !dependent_type_p (basetype))
-           {
-             base_binfo = TYPE_BINFO (basetype);
+  if (max_vbases)
+    {
+      CLASSTYPE_VBASECLASSES (ref) = VEC_alloc (tree, max_vbases);
+      TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
+      /* Converting to a virtual base class requires looking up the
+        offset of the virtual base.  */
+      TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
+      
+      if (TYPE_FOR_JAVA (ref))
+       error ("Java class '%T' cannot have virtual bases", ref);
+    }
 
-             my_friendly_assert (base_binfo, 20040706);
-           }
-         else
-           {
-             base_binfo = make_tree_binfo (BINFO_LANG_SLOTS);
-             
-             BINFO_TYPE (base_binfo) = basetype;
-             BINFO_DEPENDENT_BASE_P (base_binfo) = 1;
-           }
-         
-         TREE_VEC_ELT (binfos, i) = base_binfo;
-         TREE_VEC_ELT (accesses, i) = access;
-         /* This flag will be in the binfo of the base type, we must
-            clear it after copying the base binfos.  */
-         BINFO_VIRTUAL_P (base_binfo) = via_virtual;
-         
-         SET_CLASSTYPE_MARKED (basetype);
-         
-         /* We are free to modify these bits because they are meaningless
-            at top level, and BASETYPE is a top-level type.  */
-         if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
-           {
-             TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
-             /* Converting to a virtual base class requires looking
-                up the offset of the virtual base.  */
-             TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
-           }
+  i = 0;
+  for (igo_prev = binfo; base_list; base_list = TREE_CHAIN (base_list))
+    {
+      tree access = TREE_PURPOSE (base_list);
+      int via_virtual = TREE_TYPE (base_list) != NULL_TREE;
+      tree basetype = TREE_VALUE (base_list);
+      tree base_binfo = NULL_TREE;
+      
+      if (access == access_default_node)
+       access = default_access;
          
-         if (CLASS_TYPE_P (basetype))
-           {
-             TYPE_HAS_NEW_OPERATOR (ref)
-               |= TYPE_HAS_NEW_OPERATOR (basetype);
-             TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
-               |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
-             TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
-             /* If the base-class uses multiple inheritance, so do we.  */
-             TYPE_USES_MULTIPLE_INHERITANCE (ref)
-               |= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
-             /* Likewise, if converting to a base of the base may require
-                code, then we may need to generate code to convert to a
-                base as well.  */
-             TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
-               |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);
-             TYPE_HAS_CONVERSION (ref) |= TYPE_HAS_CONVERSION (basetype);
-             max_vbases += VEC_length
-               (tree, CLASSTYPE_VBASECLASSES (basetype));
-           }
-         i++;
+      if (TREE_CODE (basetype) == TYPE_DECL)
+       basetype = TREE_TYPE (basetype);
+      if (TREE_CODE (basetype) != RECORD_TYPE
+         && TREE_CODE (basetype) != TYPENAME_TYPE
+         && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
+         && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM)
+       {
+         error ("base type `%T' fails to be a struct or class type",
+                basetype);
+         continue;
        }
-      if (i)
+      
+      if (CLASSTYPE_MARKED (basetype))
        {
-         TREE_VEC_LENGTH (accesses) = TREE_VEC_LENGTH (binfos) = i;
-         /* An aggregate cannot have baseclasses.  */
-         CLASSTYPE_NON_AGGREGATE (ref) = 1;
+         if (basetype == ref)
+           error ("recursive type `%T' undefined", basetype);
+         else
+           error ("duplicate base type `%T' invalid", basetype);
+         continue;
        }
-      else
-       BINFO_BASE_ACCESSES (binfo) = BINFO_BASE_BINFOS (binfo) = NULL_TREE;
-      if (max_vbases)
-       CLASSTYPE_VBASECLASSES (ref) = VEC_alloc (tree, max_vbases);
+      SET_CLASSTYPE_MARKED (basetype);
       
-      if (i > 1)
+      if (TYPE_FOR_JAVA (basetype) && (current_lang_depth () == 0))
+       TYPE_FOR_JAVA (ref) = 1;
+
+      if (CLASS_TYPE_P (basetype) && !dependent_type_p (basetype))
        {
-         TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
-         /* If there is more than one non-empty they cannot be at the same
-            address.  */
-         TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
+         base_binfo = TYPE_BINFO (basetype);
+         /* The orignal basetype could have been a typedef'd type.  */
+         basetype = BINFO_TYPE (base_binfo);
+         
+         /* Inherit flags from the base.  */
+         TYPE_HAS_NEW_OPERATOR (ref)
+           |= TYPE_HAS_NEW_OPERATOR (basetype);
+         TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
+           |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
+         TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
+         TYPE_USES_MULTIPLE_INHERITANCE (ref)
+           |= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
+         TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
+           |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);
+         TYPE_HAS_CONVERSION (ref) |= TYPE_HAS_CONVERSION (basetype);
        }
-    }
-  
-  /* Copy the base binfos, collect the virtual bases and set the
-     inheritance order chain.  */
-  copy_base_binfos (TYPE_BINFO (ref), ref, NULL_TREE);
+      
+      base_binfo = copy_binfo (base_binfo, basetype, ref,
+                              &igo_prev, via_virtual);
+      if (!BINFO_INHERITANCE_CHAIN (base_binfo))
+       BINFO_INHERITANCE_CHAIN (base_binfo) = binfo;
 
-  if (TREE_CODE (ref) == UNION_TYPE)
-    {
-      if (i)
-       error ("derived union `%T' invalid", ref);
+      TREE_VEC_ELT (BINFO_BASE_ACCESSES (binfo), i) = access;
+      BINFO_BASE_BINFO (binfo, i) = base_binfo;
+      i++;
     }
 
-  if (TYPE_FOR_JAVA (ref))
+  if (max_bases)
     {
-      if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
-       error ("Java class '%T' cannot have multiple bases", ref);
-      if (CLASSTYPE_VBASECLASSES (ref))
-       error ("Java class '%T' cannot have virtual bases", ref);
+      /* If any bases were invalid, we will have allocated too many
+        slots.  */
+      TREE_VEC_LENGTH (BINFO_BASE_ACCESSES (binfo)) = i;
+      TREE_VEC_LENGTH (BINFO_BASE_BINFOS (binfo)) = i;
     }
-
+  
   /* Unmark all the types.  */
-  while (i--)
-    {
-      tree binfo = BINFO_BASE_BINFO (TYPE_BINFO (ref), i);
-      tree basetype = BINFO_TYPE (binfo);
-      
-      CLEAR_CLASSTYPE_MARKED (basetype);
-      if (!BINFO_DEPENDENT_BASE_P (binfo))
-       BINFO_VIRTUAL_P (TYPE_BINFO (basetype)) = 0;
-    }
+  for (i = 0; i != BINFO_N_BASE_BINFOS (binfo); i++)
+    CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (BINFO_BASE_BINFO (binfo, i)));
   CLEAR_CLASSTYPE_MARKED (ref);
 }
 
index 6cb784ad3bacc341aeb1db1b1abb91dfcb133a8a..4321b8a1a725494370bcaeb1e4b05585f507bc97 100644 (file)
@@ -567,85 +567,92 @@ canonical_type_variant (tree t)
   return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t));
 }
 \f
-/* Makes new binfos for the indirect bases under BINFO. T is the most
-   derived TYPE. PREV is the previous binfo, whose TREE_CHAIN we make
-   point to this binfo. We return the last BINFO created.
-
-   The CLASSTYPE_VBASECLASSES vector of T is constructed in the correct
-   order.
+/* Makes a copy of BINFO and TYPE, which is to be inherited into a
+   graph dominated by T.  If BINFO is NULL, TYPE is a dependent base,
+   and we do a shallow copy.  If BINFO is non-NULL, we do a deep copy.
+   VIRT indicates whether TYPE is inherited virtually or not.
+   IGO_PREV points at the previous binfo of the inheritance graph
+   order chain.  The newly copied binfo's TREE_CHAIN forms this
+   ordering.
+
+   The CLASSTYPE_VBASECLASSES vector of T is constructed in the
+   correct order. That is in the order the bases themselves should be
+   constructed in.
 
    The BINFO_INHERITANCE of a virtual base class points to the binfo
-   og the most derived type.
-
-   The binfo's TREE_CHAIN is set to inheritance graph order, but bases
-   for non-class types are not included (i.e. those which are
-   dependent bases in non-instantiated templates).  */
+   of the most derived type. ??? We could probably change this so that
+   BINFO_INHERITANCE becomes synonymous with BINFO_PRIMARY, and hence
+   remove a field.  They currently can only differ for primary virtual
+   virtual bases.  */
 
 tree
-copy_base_binfos (tree binfo, tree t, tree prev)
+copy_binfo (tree binfo, tree type, tree t, tree *igo_prev, int virt)
 {
-  tree binfos = BINFO_BASE_BINFOS (binfo);
-  int n, ix;
+  tree new_binfo;
 
-  if (prev)
-    TREE_CHAIN (prev) = binfo;
-  prev = binfo;
+  if (virt)
+    {
+      /* See if we've already made this virtual base.  */
+      new_binfo = binfo_for_vbase (type, t);
+      if (new_binfo)
+       return new_binfo;
+    }
   
-  if (binfos == NULL_TREE)
-    return prev;
+  new_binfo = make_tree_binfo (BINFO_LANG_SLOTS);
+  BINFO_TYPE (new_binfo) = type;
 
-  n = TREE_VEC_LENGTH (binfos);
+  /* Chain it into the inheritance graph.  */
+  TREE_CHAIN (*igo_prev) = new_binfo;
+  *igo_prev = new_binfo;
   
-  /* Now copy the structure beneath BINFO.  */
-  for (ix = 0; ix != n; ix++)
+  if (binfo)
     {
-      tree base_binfo = TREE_VEC_ELT (binfos, ix);
-      tree new_binfo = NULL_TREE;
-
-      if (BINFO_DEPENDENT_BASE_P (base_binfo))
+      int ix, n = BINFO_N_BASE_BINFOS (binfo);
+      
+      my_friendly_assert (!BINFO_DEPENDENT_BASE_P (binfo), 20040712);
+      my_friendly_assert (type == BINFO_TYPE (binfo), 20040714);
+  
+      BINFO_OFFSET (new_binfo) = BINFO_OFFSET (binfo);
+      BINFO_VIRTUALS (new_binfo) = BINFO_VIRTUALS (binfo);
+      
+      /* Create a new base binfo vector.  */
+      if (n)
        {
-         my_friendly_assert (binfo == TYPE_BINFO (t), 20030204);
-         
-         new_binfo = base_binfo;
-         TREE_CHAIN (prev) = new_binfo;
-         prev = new_binfo;
-         BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;
-         BINFO_DEPENDENT_BASE_P (new_binfo) = 1;
+         BINFO_BASE_BINFOS (new_binfo) = make_tree_vec (n);
+          /* We do not need to copy the accesses, as they are read only.  */
+         BINFO_BASE_ACCESSES (new_binfo) = BINFO_BASE_ACCESSES (binfo);
        }
-      else if (BINFO_VIRTUAL_P (base_binfo))
-       new_binfo = binfo_for_vbase (BINFO_TYPE (base_binfo), t);
       
-      if (!new_binfo)
+      /* Recursively copy base binfos of BINFO.  */
+      for (ix = 0; ix != n; ix++)
        {
-         new_binfo = make_tree_binfo (BINFO_LANG_SLOTS);
-
-         BINFO_TYPE (new_binfo) = BINFO_TYPE (base_binfo);
-         BINFO_OFFSET (new_binfo) = BINFO_OFFSET (base_binfo);
-         BINFO_VIRTUALS (new_binfo) = BINFO_VIRTUALS (base_binfo);
-
-         if (BINFO_BASE_BINFOS (base_binfo))
-           /* Duplicate the binfo's base vector, so we can recurse.  */
-           BINFO_BASE_BINFOS (new_binfo)
-             = copy_node (BINFO_BASE_BINFOS (base_binfo));
-         /* We do not need to copy the accesses, as they are read only.  */
-         BINFO_BASE_ACCESSES (new_binfo) = BINFO_BASE_ACCESSES (base_binfo);
+         tree base_binfo = BINFO_BASE_BINFO (binfo, ix);
+         tree new_base_binfo;
+         
+         my_friendly_assert (!BINFO_DEPENDENT_BASE_P (base_binfo), 20040713);
+         new_base_binfo = copy_binfo (base_binfo, BINFO_TYPE (base_binfo),
+                                      t, igo_prev,
+                                      BINFO_VIRTUAL_P (base_binfo));
          
-         prev = copy_base_binfos (new_binfo, t, prev);
-         if (BINFO_VIRTUAL_P (base_binfo))
-           {
-             VEC_quick_push (tree, CLASSTYPE_VBASECLASSES (t), new_binfo);
-             BINFO_VIRTUAL_P (new_binfo) = 1;
-             BINFO_INHERITANCE_CHAIN (new_binfo) = TYPE_BINFO (t);
-           }
-         else
-           BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;
+         if (!BINFO_INHERITANCE_CHAIN (new_base_binfo))
+           BINFO_INHERITANCE_CHAIN (new_base_binfo) = new_binfo;
+         BINFO_BASE_BINFO (new_binfo, ix) = new_base_binfo;
        }
-      TREE_VEC_ELT (binfos, ix) = new_binfo;
     }
-
-  return prev;
+  else
+    BINFO_DEPENDENT_BASE_P (new_binfo) = 1;
+  
+  if (virt)
+    {
+      /* Push it onto the list after any virtual bases it contains
+        will have been pushed.  */
+      VEC_quick_push (tree, CLASSTYPE_VBASECLASSES (t), new_binfo);
+      BINFO_VIRTUAL_P (new_binfo) = 1;
+      BINFO_INHERITANCE_CHAIN (new_binfo) = TYPE_BINFO (t);
+    }
+  
+  return new_binfo;
 }
-
 \f
 /* Hashing of lists so that we don't make duplicates.
    The entry point is `list_hash_canon'.  */