]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/cp/search.c
class.c (build_vbase_path): Simplify.
[gcc.git] / gcc / cp / search.c
index dc81a3383020c5377bf8f5954bdfa3138a98d82d..abd6867a0f4cc4b423f443e7c0daf6256f85bb6c 100644 (file)
@@ -1,6 +1,6 @@
 /* Breadth-first and depth-first routines for
    searching multiple-inheritance lattice for GNU C++.
-   Copyright (C) 1987, 89, 92-97, 1998, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1987, 89, 92-97, 1998, 1999, 2000 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GNU CC.
@@ -75,10 +75,8 @@ pop_stack_level (stack)
 #define search_level stack_level
 static struct search_level *search_stack;
 
-static tree get_abstract_virtuals_1 PROTO((tree, int, tree));
 static tree next_baselink PROTO((tree));
 static tree get_vbase_1 PROTO((tree, tree, unsigned int *));
-static tree convert_pointer_to_vbase PROTO((tree, tree));
 static tree lookup_field_1 PROTO((tree, tree));
 static tree convert_pointer_to_single_level PROTO((tree, tree));
 static int lookup_fnfields_here PROTO((tree, tree));
@@ -90,20 +88,22 @@ static tree dfs_no_overlap_yet PROTO((tree, void *));
 static int get_base_distance_recursive
        PROTO((tree, int, int, int, int *, tree *, tree,
               int, int *, int, int));
+static int dynamic_cast_base_recurse PROTO((tree, tree, int, tree *));
 static void expand_upcast_fixups 
        PROTO((tree, tree, tree, tree, tree, tree, tree *));
 static void fixup_virtual_upcast_offsets
        PROTO((tree, tree, int, int, tree, tree, tree, tree,
               tree *));
-static tree unmarkedp PROTO((tree, void *));
 static tree marked_vtable_pathp PROTO((tree, void *));
 static tree unmarked_vtable_pathp PROTO((tree, void *));
 static tree marked_new_vtablep PROTO((tree, void *));
 static tree unmarked_new_vtablep PROTO((tree, void *));
 static tree marked_pushdecls_p PROTO((tree, void *));
 static tree unmarked_pushdecls_p PROTO((tree, void *));
+#if 0
 static tree dfs_debug_unmarkedp PROTO((tree, void *));
 static tree dfs_debug_mark PROTO((tree, void *));
+#endif
 static tree dfs_find_vbases PROTO((tree, void *));
 static tree dfs_clear_vbase_slots PROTO((tree, void *));
 static tree dfs_init_vbase_pointers PROTO((tree, void *));
@@ -131,8 +131,6 @@ static tree dfs_walk_real PROTO ((tree,
                                  tree (*) (tree, void *),
                                  tree (*) (tree, void *),
                                  void *));
-static tree dfs_bfv_queue_p PROTO ((tree, void *));
-static tree dfs_bfv_helper PROTO ((tree, void *));
 static tree get_virtuals_named_this_r PROTO ((tree, void *));
 static tree context_for_name_lookup PROTO ((tree));
 static tree canonical_binfo PROTO ((tree));
@@ -150,6 +148,9 @@ static int protected_accessible_p PROTO ((tree, tree, tree, tree));
 static int friend_accessible_p PROTO ((tree, tree, tree, tree));
 static void setup_class_bindings PROTO ((tree, int));
 static int template_self_reference_p PROTO ((tree, tree));
+static void fixup_all_virtual_upcast_offsets PROTO ((tree, tree));
+static tree dfs_mark_primary_bases PROTO((tree, void *));
+static tree get_shared_vbase_if_not_primary PROTO((tree, tree));
 
 /* Allocate a level of searching.  */
 
@@ -247,7 +248,7 @@ get_vbase (parent, binfo)
    EXPR is a non-null POINTER_TYPE to RECORD_TYPE.  We also know that
    the type of what expr points to has a virtual base of type TYPE.  */
 
-static tree
+tree
 convert_pointer_to_vbase (type, expr)
      tree type;
      tree expr;
@@ -483,8 +484,7 @@ get_base_distance (parent, binfo, protect, path_ptr)
      tree, deal with it.  This happens when we are called from
      expand_upcast_fixups.  */
   if (rval == -1 && TREE_CODE (parent) == TREE_VEC
-      && parent == binfo_member (BINFO_TYPE (parent),
-                                CLASSTYPE_VBASECLASSES (type)))
+      && parent == BINFO_FOR_VBASE (BINFO_TYPE (parent), type))
     {
       my_friendly_assert (BINFO_INHERITANCE_CHAIN (parent) == binfo, 980827);
       new_binfo = parent;
@@ -496,6 +496,77 @@ get_base_distance (parent, binfo, protect, path_ptr)
   return rval;
 }
 
+/* Worker function for get_dynamic_cast_base_type.  */
+
+static int
+dynamic_cast_base_recurse (subtype, binfo, via_virtual, offset_ptr)
+     tree subtype;
+     tree binfo;
+     int via_virtual;
+     tree *offset_ptr;
+{
+  tree binfos;
+  int i, n_baselinks;
+  int worst = -3;
+  
+  if (BINFO_TYPE (binfo) == subtype)
+    {
+      if (via_virtual)
+        return -2;
+      else
+        {
+          *offset_ptr = BINFO_OFFSET (binfo);
+          return 0;
+        }
+    }
+  
+  binfos = BINFO_BASETYPES (binfo);
+  n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+  for (i = 0; i < n_baselinks; i++)
+    {
+      tree base_binfo = TREE_VEC_ELT (binfos, i);
+      int rval;
+      
+      if (!TREE_VIA_PUBLIC (base_binfo))
+        continue;
+      rval = dynamic_cast_base_recurse
+             (subtype, base_binfo,
+              via_virtual || TREE_VIA_VIRTUAL (base_binfo), offset_ptr);
+      if (worst == -3)
+        worst = rval;
+      else if (rval >= 0)
+        worst = worst >= 0 ? -1 : worst;
+      else if (rval > -3)
+        worst = worst < rval ? worst : rval;
+    }
+  return worst;
+}
+
+/* The dynamic cast runtime needs a hint about how the static SUBTYPE type started
+   from is related to the required TARGET type, in order to optimize the
+   inheritance graph search. This information is independant of the
+   current context, and ignores private paths, hence get_base_distance is
+   inappropriate. Return a TREE specifying the base offset, BOFF.
+   BOFF >= 0, there is only one public non-virtual SUBTYPE base at offset BOFF,
+      and there are no public virtual SUBTYPE bases.
+   BOFF == -1, SUBTYPE occurs as multiple public non-virtual bases.
+   BOFF == -2, SUBTYPE occurs as multiple public virtual or non-virtual bases.
+   BOFF == -3, SUBTYPE is not a public base.  */
+
+tree
+get_dynamic_cast_base_type (subtype, target)
+     tree subtype;
+     tree target;
+{
+  tree offset = NULL_TREE;
+  int boff = dynamic_cast_base_recurse (subtype, TYPE_BINFO (target),
+                                        0, &offset);
+  
+  if (!boff)
+    return offset;
+  return build_int_2 (boff, -1);
+}
+
 /* Search for a member with name NAME in a multiple inheritance lattice
    specified by TYPE.  If it does not exist, return NULL_TREE.
    If the member is ambiguously referenced, return `error_mark_node'.
@@ -540,7 +611,16 @@ lookup_field_1 (type, name)
          else if (DECL_NAME (fields[i]) < name)
            lo = i + 1;
          else
-           return fields[i];
+           {
+             /* We might have a nested class and a field with the
+                same name; we sorted them appropriately via
+                field_decl_cmp, so just look for the last field with
+                this name.  */
+             while (i + 1 < hi
+                    && DECL_NAME (fields[i+1]) == name)
+               ++i;
+             return fields[i];
+           }
        }
       return NULL_TREE;
     }
@@ -584,8 +664,8 @@ lookup_field_1 (type, name)
   if (name == vptr_identifier)
     {
       /* Give the user what s/he thinks s/he wants.  */
-      if (TYPE_VIRTUAL_P (type))
-       return CLASSTYPE_VFIELD (type);
+      if (TYPE_POLYMORPHIC_P (type))
+       return TYPE_VFIELD (type);
     }
   return NULL_TREE;
 }
@@ -704,7 +784,7 @@ shared_marked_p (binfo, data)
      void *data;
 {
   binfo = canonical_binfo (binfo);
-  return markedp (binfo, data) ? binfo : NULL_TREE;
+  return markedp (binfo, data);
 }
 
 /* If BINFO is not marked, return a canonical version of BINFO.
@@ -716,7 +796,7 @@ shared_unmarked_p (binfo, data)
      void *data;
 {
   binfo = canonical_binfo (binfo);
-  return unmarkedp (binfo, data) ? binfo : NULL_TREE;
+  return unmarkedp (binfo, data);
 }
 
 /* Called from access_in_type via dfs_walk.  Calculate the access to
@@ -1214,8 +1294,7 @@ lookup_field_queue_p (binfo, data)
     return NULL_TREE;
 
   if (TREE_VIA_VIRTUAL (binfo))
-    return binfo_member (BINFO_TYPE (binfo),
-                        CLASSTYPE_VBASECLASSES (lfi->type));
+    return BINFO_FOR_VBASE (BINFO_TYPE (binfo), lfi->type);
   else
     return binfo;
 }
@@ -1335,14 +1414,12 @@ lookup_field_r (binfo, data)
              /* This is the first time we noticed an ambiguity.  Add
                 what we previously thought was a reasonable candidate
                 to the list.  */
-             lfi->ambiguous = scratch_tree_cons (NULL_TREE, lfi->rval,
-                                                 NULL_TREE);
+             lfi->ambiguous = tree_cons (NULL_TREE, lfi->rval, NULL_TREE);
              TREE_TYPE (lfi->ambiguous) = error_mark_node;
            }
 
          /* Add the new value.  */
-         lfi->ambiguous = scratch_tree_cons (NULL_TREE, nval, 
-                                             lfi->ambiguous);
+         lfi->ambiguous = tree_cons (NULL_TREE, nval, lfi->ambiguous);
          TREE_TYPE (lfi->ambiguous) = error_mark_node;
          lfi->errstr = "request for member `%D' is ambiguous";
        }
@@ -1486,7 +1563,7 @@ lookup_member (xbasetype, name, protect, want_type)
 
   if (rval && is_overloaded_fn (rval)) 
     {
-      rval = scratch_tree_cons (basetype_path, rval, NULL_TREE);
+      rval = tree_cons (basetype_path, rval, NULL_TREE);
       SET_BASELINK_P (rval);
     }
 
@@ -1776,10 +1853,9 @@ get_virtuals_named_this_r (binfo, data)
   idx = lookup_fnfields_here (BINFO_TYPE (binfo), gvnti->name);
   if (idx >= 0)
     gvnti->fields
-      = scratch_tree_cons (binfo, 
-                          TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type),
-                                        idx),
-                          gvnti->fields);
+      = tree_cons (binfo, 
+                  TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx),
+                  gvnti->fields);
 
   return NULL_TREE;
 }
@@ -2035,81 +2111,256 @@ get_matching_virtual (binfo, fndecl, dtorp)
     }
 }
 
-/* Return the list of virtual functions which are abstract in type
-   TYPE that come from non virtual base classes.  See
-   expand_direct_vtbls_init for the style of search we do.  */
+/* A queue function for dfs_walk that skips any nonprimary virtual
+   bases and any already marked bases.  */
+
+tree
+dfs_skip_nonprimary_vbases_unmarkedp (binfo, data)
+     tree binfo;
+     void *data ATTRIBUTE_UNUSED;
+{
+  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo))
+    /* This is a non-primary virtual base.  SKip it.  */
+    return NULL_TREE;
+
+  return unmarkedp (binfo, NULL);
+}
+
+/* A queue function for dfs_walk that skips any nonprimary virtual
+   bases and any unmarked bases.  */
+
+tree
+dfs_skip_nonprimary_vbases_markedp (binfo, data)
+     tree binfo;
+     void *data ATTRIBUTE_UNUSED;
+{
+  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo))
+    /* This is a non-primary virtual base.  SKip it.  */
+    return NULL_TREE;
+
+  return markedp (binfo, NULL);
+}
+
+/* Called via dfs_walk from mark_primary_bases.  */
 
 static tree
-get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
+dfs_mark_primary_bases (binfo, data)
      tree binfo;
-     int do_self;
-     tree abstract_virtuals;
+     void *data;
 {
-  tree binfos = BINFO_BASETYPES (binfo);
-  int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+  int i;
+  tree base_binfo;
 
-  for (i = 0; i < n_baselinks; i++)
-    {
-      tree base_binfo = TREE_VEC_ELT (binfos, i);
-      int is_not_base_vtable
-       = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
-      if (! TREE_VIA_VIRTUAL (base_binfo))
-       abstract_virtuals
-         = get_abstract_virtuals_1 (base_binfo, is_not_base_vtable,
-                                    abstract_virtuals);
-    }
-  /* Should we use something besides CLASSTYPE_VFIELDS? */
-  if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
+  if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
+    return NULL_TREE;
+
+  i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
+  base_binfo = BINFO_BASETYPE (binfo, i);
+
+  if (!TREE_VIA_VIRTUAL (base_binfo))
+    /* Non-virtual base classes are easy.  */
+    BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
+  else
     {
-      tree virtuals = BINFO_VIRTUALS (binfo);
+      tree shared_binfo;
 
-      skip_rtti_stuff (&virtuals, BINFO_TYPE (binfo));
+      shared_binfo 
+       = BINFO_FOR_VBASE (BINFO_TYPE (base_binfo), (tree) data);
 
-      while (virtuals)
+      /* If this virtual base is not already primary somewhere else in
+        the hiearchy, then we'll be using this copy.  */
+      if (!BINFO_VBASE_PRIMARY_P (shared_binfo)
+         && !BINFO_VBASE_MARKED (shared_binfo))
        {
-         tree base_fndecl = TREE_VALUE (virtuals);
-         if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
-           abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, 
-                                          abstract_virtuals);
-         virtuals = TREE_CHAIN (virtuals);
+         BINFO_VBASE_PRIMARY_P (shared_binfo) = 1;
+         BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
        }
     }
-  return abstract_virtuals;
+
+  return NULL_TREE;
+}
+
+/* Set BINFO_PRIMARY_MARKED_P for all binfos in the hierarchy
+   dominated by BINFO that are primary bases.  */
+
+void
+mark_primary_bases (type)
+     tree type;
+{
+  tree vbase;
+
+  /* Mark the TYPE_BINFO hierarchy.  */
+  dfs_walk (TYPE_BINFO (type), dfs_mark_primary_bases, 
+           dfs_skip_nonprimary_vbases_unmarkedp, type);
+
+  /* Now go through the virtual base classes.  Any that are not
+     already primary will need to be allocated in TYPE, and so we need
+     to mark their primary bases.  */
+  for (vbase = CLASSTYPE_VBASECLASSES (type); 
+       vbase; 
+       vbase = TREE_CHAIN (vbase))
+    {
+      if (BINFO_VBASE_PRIMARY_P (vbase))
+       /* This virtual base was already included in the hierarchy, so
+          there's nothing to do here.  */
+       continue;
+
+      /* Temporarily pretend that VBASE is primary so that its bases
+        will be walked; this is the real copy of VBASE.  */
+      BINFO_PRIMARY_MARKED_P (vbase) = 1;
+
+      /* Now, walk its bases.  */
+      dfs_walk (vbase, dfs_mark_primary_bases,
+               dfs_skip_nonprimary_vbases_unmarkedp, type);
+
+      /* VBASE wasn't really primary.  */
+      BINFO_PRIMARY_MARKED_P (vbase) = 0;
+      /* And we don't want to allow it to *become* primary if it is a
+        base of some subsequent base class.  */
+      SET_BINFO_VBASE_MARKED (vbase);
+    }
+
+  /* Clear the VBASE_MARKED bits we set above.  */
+  for (vbase = CLASSTYPE_VBASECLASSES (type); 
+       vbase; 
+       vbase = TREE_CHAIN (vbase))
+    CLEAR_BINFO_VBASE_MARKED (vbase);
+}
+
+/* If BINFO is a non-primary virtual baseclass (in the hierarchy
+   dominated by TYPE), and no primary copy appears anywhere in the
+   hierarchy, return the shared copy.  If a primary copy appears
+   elsewhere, return NULL_TREE.  Otherwise, return BINFO itself; it is
+   either a non-virtual base or a primary virtual base.  */
+
+static tree
+get_shared_vbase_if_not_primary (binfo, type)
+     tree binfo;
+     tree type;
+{
+  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo))
+    {
+      /* This is a non-primary virtual base.  If there is no primary
+        version, get the shared version.  */
+      binfo = BINFO_FOR_VBASE (BINFO_TYPE (binfo), type);
+      if (BINFO_VBASE_PRIMARY_P (binfo))
+       return NULL_TREE;
+    }
+
+  return binfo;
 }
 
-/* Return the list of virtual functions which are abstract in type TYPE.
-   This information is cached, and so must be built on a
-   non-temporary obstack.  */
+/* A queue function to use with dfs_walk that prevents travel into any
+   nonprimary virtual base, or its baseclasses.  DATA should be the
+   type of the complete object, or a TREE_LIST whose TREE_PURPOSE is
+   the type of the complete object.  By using this function as a queue
+   function, you will walk over exactly those BINFOs that actually
+   exist in the complete object, including those for virtual base
+   classes.  If you SET_BINFO_MARKED for each binfo you process, you
+   are further guaranteed that you will walk into each virtual base
+   class exactly once.  */
 
 tree
-get_abstract_virtuals (type)
-     tree type;
+dfs_unmarked_real_bases_queue_p (binfo, data)
+     tree binfo;
+     void *data;
 {
-  tree vbases;
-  tree abstract_virtuals = NULL;
+  tree type = (tree) data;
 
-  /* First get all from non-virtual bases.  */
-  abstract_virtuals
-    = get_abstract_virtuals_1 (TYPE_BINFO (type), 1, abstract_virtuals);
-                                              
-  for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; vbases = TREE_CHAIN (vbases))
+  if (TREE_CODE (type) == TREE_LIST)
+    type = TREE_PURPOSE (type);
+  binfo = get_shared_vbase_if_not_primary (binfo, type); 
+  return binfo ? unmarkedp (binfo, NULL) : NULL_TREE;
+}
+
+/* Like dfs_unmarked_real_bases_queue_p but walks only into things
+   that are marked, rather than unmarked.  */
+
+tree
+dfs_marked_real_bases_queue_p (binfo, data)
+     tree binfo;
+     void *data;
+{
+  tree type = (tree) data;
+
+  if (TREE_CODE (type) == TREE_LIST)
+    type = TREE_PURPOSE (type);
+  binfo = get_shared_vbase_if_not_primary (binfo, type);
+  return binfo ? markedp (binfo, NULL) : NULL_TREE;
+}
+
+/* Called via dfs_walk from dfs_get_pure_virtuals.  */
+
+static tree
+dfs_get_pure_virtuals (binfo, data)
+     tree binfo;
+     void *data;
+{
+  tree type = (tree) data;
+
+  /* We're not interested in primary base classes; the derived class
+     of which they are a primary base will contain the information we
+     need.  */
+  if (!BINFO_PRIMARY_MARKED_P (binfo))
     {
-      tree virtuals = BINFO_VIRTUALS (vbases);
+      tree virtuals;
+      
+      for (virtuals = skip_rtti_stuff (binfo, 
+                                      BINFO_TYPE (binfo), 
+                                      NULL);
+          virtuals;
+          virtuals = TREE_CHAIN (virtuals))
+       if (DECL_PURE_VIRTUAL_P (TREE_VALUE (virtuals)))
+         CLASSTYPE_PURE_VIRTUALS (type) 
+           = tree_cons (NULL_TREE, TREE_VALUE (virtuals),
+                        CLASSTYPE_PURE_VIRTUALS (type));
+    }
+  
+  SET_BINFO_MARKED (binfo);
 
-      skip_rtti_stuff (&virtuals, BINFO_TYPE (vbases));
+  return NULL_TREE;
+}
 
-      while (virtuals)
+/* Set CLASSTYPE_PURE_VIRTUALS for TYPE.  */
+
+void
+get_pure_virtuals (type)
+     tree type;
+{
+  tree vbases;
+
+  /* Clear the CLASSTYPE_PURE_VIRTUALS list; whatever is already there
+     is going to be overridden.  */
+  CLASSTYPE_PURE_VIRTUALS (type) = NULL_TREE;
+  /* Now, run through all the bases which are not primary bases, and
+     collect the pure virtual functions.  We look at the vtable in
+     each class to determine what pure virtual functions are present.
+     (A primary base is not interesting because the derived class of
+     which it is a primary base will contain vtable entries for the
+     pure virtuals in the base class.  */
+  dfs_walk (TYPE_BINFO (type), dfs_get_pure_virtuals, 
+           dfs_unmarked_real_bases_queue_p, type);
+  dfs_walk (TYPE_BINFO (type), dfs_unmark, 
+           dfs_marked_real_bases_queue_p, type);
+
+  /* Put the pure virtuals in dfs order.  */
+  CLASSTYPE_PURE_VIRTUALS (type) = nreverse (CLASSTYPE_PURE_VIRTUALS (type));
+
+  for (vbases = CLASSTYPE_VBASECLASSES (type); 
+       vbases; 
+       vbases = TREE_CHAIN (vbases))
+    {
+      tree virtuals;
+
+      for (virtuals = skip_rtti_stuff (vbases, BINFO_TYPE (vbases), NULL);
+          virtuals;
+          virtuals = TREE_CHAIN (virtuals))
        {
          tree base_fndecl = TREE_VALUE (virtuals);
          if (DECL_NEEDS_FINAL_OVERRIDER_P (base_fndecl))
            cp_error ("`%#D' needs a final overrider", base_fndecl);
-         else if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
-           abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, 
-                                          abstract_virtuals);
-         virtuals = TREE_CHAIN (virtuals);
        }
     }
-  return nreverse (abstract_virtuals);
 }
 
 static tree
@@ -2165,14 +2416,15 @@ convert_pointer_to_single_level (to_type, expr)
   return NULL_TREE;
 }
 
-tree markedp (binfo, data) 
+tree 
+markedp (binfo, data) 
      tree binfo;
      void *data ATTRIBUTE_UNUSED;
 { 
   return BINFO_MARKED (binfo) ? binfo : NULL_TREE; 
 }
 
-static tree
+tree
 unmarkedp (binfo, data) 
      tree binfo;
      void *data ATTRIBUTE_UNUSED;
@@ -2233,7 +2485,6 @@ unmarked_pushdecls_p (binfo, data)
 #if 0
 static int dfs_search_slot_nonempty_p (binfo) tree binfo;
 { return CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) != 0; }
-#endif
 
 static tree 
 dfs_debug_unmarkedp (binfo, data) 
@@ -2243,6 +2494,7 @@ dfs_debug_unmarkedp (binfo, data)
   return (!CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo)) 
          ? binfo : NULL_TREE);
 }
+#endif
 
 /* The worker functions for `dfs_walk'.  These do not need to
    test anything (vis a vis marking) if they are paired with
@@ -2263,6 +2515,17 @@ dfs_unmark (binfo, data)
   return NULL_TREE;
 }
 
+/* Clear both BINFO_MARKED and BINFO_VBASE_MARKED.  */
+
+tree
+dfs_vbase_unmark (binfo, data)
+     tree binfo;
+     void *data ATTRIBUTE_UNUSED;
+{
+  CLEAR_BINFO_VBASE_MARKED (binfo);
+  return dfs_unmark (binfo, data);
+}
+
 #if 0
 static void
 dfs_mark_vtable_path (binfo) tree binfo;
@@ -2283,8 +2546,10 @@ dfs_unmark_new_vtable (binfo) tree binfo;
 static void
 dfs_clear_search_slot (binfo) tree binfo;
 { CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) = 0; }
-#endif
 
+/* Keep this code around in case we later want to control debug info
+   based on whether a type is "used".  Currently, we only suppress debug
+   info if we can emit it with the vtable.  jason 1999-11-11) */
 static tree
 dfs_debug_mark (binfo, data)
      tree binfo;
@@ -2292,47 +2557,18 @@ dfs_debug_mark (binfo, data)
 {
   tree t = BINFO_TYPE (binfo);
 
-  /* Use heuristic that if there are virtual functions,
-     ignore until we see a non-inline virtual function.  */
-  tree methods = CLASSTYPE_METHOD_VEC (t);
-
   CLASSTYPE_DEBUG_REQUESTED (t) = 1;
 
-  if (methods == 0)
-    return NULL_TREE;
-
   /* If interface info is known, either we've already emitted the debug
      info or we don't need to.  */
   if (CLASSTYPE_INTERFACE_KNOWN (t))
     return NULL_TREE;
 
-  /* If debug info is requested from this context for this type, supply it.
-     If debug info is requested from another context for this type,
-     see if some third context can supply it.  */
-  if (current_function_decl == NULL_TREE
-      || DECL_CLASS_CONTEXT (current_function_decl) != t)
-    {
-      if (TREE_VEC_ELT (methods, 1))
-       methods = TREE_VEC_ELT (methods, 1);
-      else if (TREE_VEC_ELT (methods, 0))
-       methods = TREE_VEC_ELT (methods, 0);
-      else
-       methods = TREE_VEC_ELT (methods, 2);
-      methods = OVL_CURRENT (methods);
-      while (methods)
-       {
-         if (DECL_VINDEX (methods)
-             && DECL_THIS_INLINE (methods) == 0
-             && DECL_ABSTRACT_VIRTUAL_P (methods) == 0)
-           {
-             /* Somebody, somewhere is going to have to define this
-                virtual function.  When they do, they will provide
-                the debugging info.  */
-             return NULL_TREE;
-           }
-         methods = TREE_CHAIN (methods);
-       }
-    }
+  /* If the class has virtual functions, we'll emit the debug info
+     with the vtable.  */
+  if (TYPE_POLYMORPHIC_P (t))
+    return NULL_TREE;
+
   /* We cannot rely on some alien method to solve our problems,
      so we must write out the debug info ourselves.  */
   TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 0;
@@ -2340,6 +2576,7 @@ dfs_debug_mark (binfo, data)
 
   return NULL_TREE;
 }
+#endif
 \f
 struct vbase_info 
 {
@@ -2388,18 +2625,11 @@ dfs_init_vbase_pointers (binfo, data)
 {
   struct vbase_info *vi = (struct vbase_info *) data;
   tree type = BINFO_TYPE (binfo);
-  tree fields = TYPE_FIELDS (type);
+  tree fields;
   tree this_vbase_ptr;
 
   CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
 
-#if 0
-  /* See finish_struct_1 for when we can enable this.  */
-  /* If we have a vtable pointer first, skip it.  */
-  if (VFIELD_NAME_P (DECL_NAME (fields)))
-    fields = TREE_CHAIN (fields);
-#endif
-
   if (BINFO_INHERITANCE_CHAIN (binfo))
     {
       this_vbase_ptr = TREE_CHAIN (BINFO_INHERITANCE_CHAIN (binfo));
@@ -2413,6 +2643,14 @@ dfs_init_vbase_pointers (binfo, data)
   else
     this_vbase_ptr = TREE_CHAIN (binfo);
 
+  /* We're going to iterate through all the pointers to virtual
+     base-classes.  They come at the beginning of the class.  */
+  fields = TYPE_FIELDS (type);
+  if (fields == TYPE_VFIELD (type))
+    /* If the first field is the vtbl pointer (as happens in the new
+       ABI), skip it.  */
+    fields = TREE_CHAIN (fields);
+
   if (fields == NULL_TREE
       || DECL_NAME (fields) == NULL_TREE
       || ! VBASE_NAME_P (DECL_NAME (fields)))
@@ -2513,7 +2751,7 @@ virtual_context (fndecl, t, vbase)
              /* Not sure if checking path == vbase is necessary here, but just in
                 case it is.  */
              if (TREE_VIA_VIRTUAL (path) || path == vbase)
-               return binfo_member (BINFO_TYPE (path), CLASSTYPE_VBASECLASSES (t));
+               return BINFO_FOR_VBASE (BINFO_TYPE (path), t);
              path = BINFO_INHERITANCE_CHAIN (path);
            }
        }
@@ -2556,7 +2794,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
                      vbase_offsets)
      tree binfo, addr, orig_addr, vbase, vbase_addr, t, *vbase_offsets;
 {
-  tree virtuals = BINFO_VIRTUALS (binfo);
+  tree virtuals;
   tree vc;
   tree delta;
   unsigned HOST_WIDE_INT n;
@@ -2571,7 +2809,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
       *vbase_offsets = delta;
     }
 
-  n = skip_rtti_stuff (&virtuals, BINFO_TYPE (binfo));
+  virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), &n);
 
   while (virtuals)
     {
@@ -2602,7 +2840,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
              DECL_ARTIFICIAL (nvtbl) = 1;
              nvtbl = pushdecl (nvtbl);
              init = NULL_TREE;
-             cp_finish_decl (nvtbl, init, NULL_TREE, 0,
+             cp_finish_decl (nvtbl, init, NULL_TREE,
                              LOOKUP_ONLYCONVERTING);
 
              /* We don't set DECL_VIRTUAL_P and DECL_CONTEXT on nvtbl
@@ -2613,13 +2851,12 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
 
              init = build (MODIFY_EXPR, TREE_TYPE (nvtbl),
                            nvtbl, vtbl);
-             TREE_SIDE_EFFECTS (init) = 1;
-             expand_expr_stmt (init);
+             finish_expr_stmt (init);
              /* Update the vtable pointers as necessary.  */
              ref = build_vfield_ref
                (build_indirect_ref (addr, NULL_PTR),
-                DECL_CONTEXT (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))));
-             expand_expr_stmt
+                DECL_CONTEXT (TYPE_VFIELD (BINFO_TYPE (binfo))));
+             finish_expr_stmt
                (build_modify_expr (ref, NOP_EXPR, nvtbl));
            }
          assemble_external (vtbl);
@@ -2662,7 +2899,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
            cp_build_qualified_type (TREE_TYPE (new_delta),
                                     CP_TYPE_QUALS (TREE_TYPE (new_delta))
                                     & ~TYPE_QUAL_CONST);
-         expand_expr_stmt (build_modify_expr (new_delta, NOP_EXPR,
+         finish_expr_stmt (build_modify_expr (new_delta, NOP_EXPR,
                                               old_delta));
        }
       ++n;
@@ -2708,23 +2945,67 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
     }
 }
 
-/* Build a COMPOUND_EXPR which when expanded will generate the code
-   needed to initialize all the virtual function table slots of all
-   the virtual baseclasses.  MAIN_BINFO is the binfo which determines
-   the virtual baseclasses to use; TYPE is the type of the object to
-   which the initialization applies.  TRUE_EXP is the true object we
-   are initializing, and DECL_PTR is the pointer to the sub-object we
-   are initializing.
+/* Fixup all the virtual upcast offsets for TYPE.  DECL_PTR is the
+   address of the sub-object being initialized.  */
 
-   When USE_COMPUTED_OFFSETS is non-zero, we can assume that the
-   object was laid out by a top-level constructor and the computed
-   offsets are valid to store vtables.  When zero, we must store new
-   vtables through virtual baseclass pointers.  */
+static void
+fixup_all_virtual_upcast_offsets (type, decl_ptr)
+     tree type;
+     tree decl_ptr;
+{
+  tree if_stmt;
+  tree in_charge_node;
+  tree vbases;
+
+  /* Only tweak the vtables if we're in charge.  */
+  in_charge_node = current_in_charge_parm;
+  if (!in_charge_node)
+    /* There's no need for any fixups in this case.  */
+    return;
+  in_charge_node = build_binary_op (EQ_EXPR, 
+                                   in_charge_node, integer_zero_node);
+  if_stmt = begin_if_stmt ();
+  finish_if_stmt_cond (in_charge_node, if_stmt);
+  
+  /* Iterate through the virtual bases, fixing up the upcast offset
+     for each one.  */
+  for (vbases = CLASSTYPE_VBASECLASSES (type);
+       vbases;
+       vbases = TREE_CHAIN (vbases))
+    {
+      if (flag_vtable_thunks)
+       /* We don't have dynamic thunks yet!  So for now, just fail
+          silently.  */
+       ;
+      else
+       {
+         tree vbase_offsets;
+         tree addr;
+
+         vbase_offsets = NULL_TREE;
+         addr = convert_pointer_to_vbase (TREE_TYPE (vbases), decl_ptr);
+         fixup_virtual_upcast_offsets (vbases,
+                                       TYPE_BINFO (BINFO_TYPE (vbases)),
+                                       1, 0, addr, decl_ptr,
+                                       type, vbases, &vbase_offsets);
+       }
+    }
+
+  /* Close out the if-statement.  */
+  finish_then_clause (if_stmt);
+  finish_if_stmt ();
+}
+
+/* Generate the code needed to initialize all the virtual function
+   table slots of all the virtual baseclasses.  BINFO is the binfo
+   which determines the virtual baseclasses to use.  TRUE_EXP is the
+   true object we are initializing, and DECL_PTR is the pointer to the
+   sub-object we are initializing.  */
 
 void
-expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
+expand_indirect_vtbls_init (binfo, decl_ptr)
      tree binfo;
-     tree true_exp, decl_ptr;
+     tree decl_ptr;
 {
   tree type = BINFO_TYPE (binfo);
 
@@ -2741,66 +3022,13 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
 
   if (TYPE_USES_VIRTUAL_BASECLASSES (type))
     {
-      rtx fixup_insns = NULL_RTX;
       tree vbases = CLASSTYPE_VBASECLASSES (type);
       struct vbase_info vi;
-      vi.decl_ptr = (true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0) 
-                    : decl_ptr);
+      vi.decl_ptr = decl_ptr;
       vi.vbase_types = vbases;
 
       dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep, &vi);
-
-      /* Initialized with vtables of type TYPE.  */
-      for (; vbases; vbases = TREE_CHAIN (vbases))
-       {
-         tree addr;
-
-         addr = convert_pointer_to_vbase (TREE_TYPE (vbases), vi.decl_ptr);
-
-         /* Do all vtables from this virtual base.  */
-         /* This assumes that virtual bases can never serve as parent
-            binfos.  (in the CLASSTYPE_VFIELD_PARENT sense)  */
-         expand_direct_vtbls_init (vbases, TYPE_BINFO (BINFO_TYPE (vbases)),
-                                   1, 0, addr);
-
-         /* Now we adjust the offsets for virtual functions that
-            cross virtual boundaries on an implicit upcast on vf call
-            so that the layout of the most complete type is used,
-            instead of assuming the layout of the virtual bases from
-            our current type.  */
-
-         if (flag_vtable_thunks)
-           {
-             /* We don't have dynamic thunks yet!
-                So for now, just fail silently.  */
-           }
-         else
-           {
-             tree vbase_offsets = NULL_TREE;
-             push_to_sequence (fixup_insns);
-             fixup_virtual_upcast_offsets (vbases,
-                                           TYPE_BINFO (BINFO_TYPE (vbases)),
-                                           1, 0, addr, vi.decl_ptr,
-                                           type, vbases, &vbase_offsets);
-             fixup_insns = get_insns ();
-             end_sequence ();
-           }
-       }
-
-      if (fixup_insns)
-       {
-         tree in_charge_node = lookup_name (in_charge_identifier, 0);
-         if (! in_charge_node)
-           {
-             warning ("recoverable internal compiler error, nobody's in charge!");
-             in_charge_node = integer_zero_node;
-           }
-         in_charge_node = build_binary_op (EQ_EXPR, in_charge_node, integer_zero_node);
-         expand_start_cond (in_charge_node, 0);
-         emit_insns (fixup_insns);
-         expand_end_cond ();
-       }
-
+      fixup_all_virtual_upcast_offsets (type, vi.decl_ptr);
       dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0);
     }
 }
@@ -2814,49 +3042,83 @@ dfs_get_vbase_types (binfo, data)
      tree binfo;
      void *data;
 {
-  tree *vbase_types = (tree *) data;
+  tree type = (tree) data;
 
   if (TREE_VIA_VIRTUAL (binfo) && ! BINFO_VBASE_MARKED (binfo))
     {
-      tree new_vbase = make_binfo (integer_zero_node, binfo,
+      tree new_vbase = make_binfo (integer_zero_node, 
+                                  BINFO_TYPE (binfo),
                                   BINFO_VTABLE (binfo),
                                   BINFO_VIRTUALS (binfo));
-      TREE_CHAIN (new_vbase) = *vbase_types;
+      unshare_base_binfos (new_vbase);
       TREE_VIA_VIRTUAL (new_vbase) = 1;
-      *vbase_types = new_vbase;
+      BINFO_INHERITANCE_CHAIN (new_vbase) = TYPE_BINFO (type);
+      TREE_CHAIN (new_vbase) = CLASSTYPE_VBASECLASSES (type);
+      CLASSTYPE_VBASECLASSES (type) = new_vbase;
       SET_BINFO_VBASE_MARKED (binfo);
     }
   SET_BINFO_MARKED (binfo);
   return NULL_TREE;
 }
 
-/* Return a list of binfos for the virtual base classes for TYPE, in
-   depth-first search order.  The list is freshly allocated, so
-   no modification is made to  the current binfo hierarchy.  */
+/* Set CLASSTYPE_VBASECLASSES for TYPE.  */
 
-tree
+void
 get_vbase_types (type)
      tree type;
 {
-  tree vbase_types;
-  tree vbases;
-  tree binfo;
-
-  binfo = TYPE_BINFO (type);
-  vbase_types = NULL_TREE;
-  dfs_walk (binfo, dfs_get_vbase_types, unmarkedp, &vbase_types);
-  dfs_walk (binfo, dfs_unmark, markedp, 0);
+  CLASSTYPE_VBASECLASSES (type) = NULL_TREE;
+  dfs_walk (TYPE_BINFO (type), dfs_get_vbase_types, unmarkedp, type);
   /* Rely upon the reverse dfs ordering from dfs_get_vbase_types, and now
      reverse it so that we get normal dfs ordering.  */
-  vbase_types = nreverse (vbase_types);
+  CLASSTYPE_VBASECLASSES (type) = nreverse (CLASSTYPE_VBASECLASSES (type));
+  dfs_walk (TYPE_BINFO (type), dfs_vbase_unmark, markedp, 0);
+}
+\f
+/* Debug info for C++ classes can get very large; try to avoid
+   emitting it everywhere.
 
-  /* unmark marked vbases */
-  for (vbases = vbase_types; vbases; vbases = TREE_CHAIN (vbases))
-    CLEAR_BINFO_VBASE_MARKED (vbases);
+   Note that this optimization wins even when the target supports
+   BINCL (if only slightly), and reduces the amount of work for the
+   linker.  */
 
-  return vbase_types;
+void
+maybe_suppress_debug_info (t)
+     tree t;
+{
+  /* We can't do the usual TYPE_DECL_SUPPRESS_DEBUG thing with DWARF, which
+     does not support name references between translation units.  It supports
+     symbolic references between translation units, but only within a single
+     executable or shared library.
+
+     For DWARF 2, we handle TYPE_DECL_SUPPRESS_DEBUG by pretending
+     that the type was never defined, so we only get the members we
+     actually define.  */
+  if (write_symbols == DWARF_DEBUG || write_symbols == NO_DEBUG)
+    return;
+
+  /* We might have set this earlier in cp_finish_decl.  */
+  TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 0;
+
+  /* If we already know how we're handling this class, handle debug info
+     the same way.  */
+  if (CLASSTYPE_INTERFACE_ONLY (t))
+    TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
+  else if (CLASSTYPE_INTERFACE_KNOWN (t))
+    /* Don't set it.  */;
+  /* If the class has virtual functions, write out the debug info
+     along with the vtable.  */
+  else if (TYPE_POLYMORPHIC_P (t))
+    TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
+
+  /* Otherwise, just emit the debug info normally.  */
 }
-\f
+
+#if 0
+/* Keep this code around in case we later want to control debug info
+   based on whether a type is "used".  Currently, we only suppress debug
+   info if we can emit it with the vtable.  jason 1999-11-11) */
+
 /* If we want debug info for a type TYPE, make sure all its base types
    are also marked as being potentially interesting.  This avoids
    the problem of not writing any debug info for intermediate basetypes
@@ -2875,13 +3137,8 @@ note_debug_info_needed (type)
     /* We can't go looking for the base types and fields just yet.  */
     return;
 
-  /* We can't do the TYPE_DECL_SUPPRESS_DEBUG thing with DWARF, which
-     does not support name references between translation units.  Well, we
-     could, but that would mean putting global labels in the debug output
-     before each exported type and each of its functions and static data
-     members.  */
-  if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG
-      || write_symbols == NO_DEBUG)
+  /* See the comment in maybe_suppress_debug_info.  */
+  if (write_symbols == DWARF_DEBUG || write_symbols == NO_DEBUG)
     return;
 
   dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp, 0);
@@ -2894,6 +3151,7 @@ note_debug_info_needed (type)
        note_debug_info_needed (ttype);
     }
 }
+#endif
 \f
 /* Subroutines of push_class_decls ().  */
 
@@ -3058,24 +3316,13 @@ void
 push_class_decls (type)
      tree type;
 {
-  struct obstack *ambient_obstack = current_obstack;
   search_stack = push_search_level (search_stack, &search_obstack);
 
-  /* Build up all the relevant bindings and such on the cache
-     obstack.  That way no memory is wasted when we throw away the
-     cache later.  */
-  push_cache_obstack ();
-
   /* Enter type declarations and mark.  */
   dfs_walk (TYPE_BINFO (type), dfs_push_type_decls, unmarked_pushdecls_p, 0);
 
   /* Enter non-type declarations and unmark.  */
   dfs_walk (TYPE_BINFO (type), dfs_push_decls, marked_pushdecls_p, 0);
-
-  /* Undo the call to push_cache_obstack above.  */
-  pop_obstacks ();
-
-  current_obstack = ambient_obstack;
 }
 
 /* Here's a subroutine we need because C lacks lambdas.  */
@@ -3152,8 +3399,6 @@ reinit_search_statistics ()
 #endif /* GATHER_STATISTICS */
 }
 
-#define scratch_tree_cons expr_tree_cons
-
 static tree
 add_conversions (binfo, data)
      tree binfo;
@@ -3180,7 +3425,7 @@ add_conversions (binfo, data)
       /* Make sure we don't already have this conversion.  */
       if (! IDENTIFIER_MARKED (name))
        {
-         *conversions = scratch_tree_cons (binfo, tmp, *conversions);
+         *conversions = tree_cons (binfo, tmp, *conversions);
          IDENTIFIER_MARKED (name) = 1;
        }
     }
@@ -3270,55 +3515,32 @@ types_overlap_p (empty_type, next_type)
   return oi.found_overlap;
 }
 
-struct bfv_info {
-  tree vbases;
-  tree var;
-};
-
-static tree
-dfs_bfv_queue_p (binfo, data)
-     tree binfo;
-     void *data;
-{
-  struct bfv_info *bfvi = (struct bfv_info *) data;
-
-  /* Use the real virtual base class objects, not the placeholders in
-     the usual hierarchy.  */
-  if (TREE_VIA_VIRTUAL (binfo))
-    return binfo_member (BINFO_TYPE (binfo), bfvi->vbases);
-  
-  return binfo;
-}
-
-/* Passed to dfs_walk_real by binfo_for_vtable; determine if bvtable
-   comes from BINFO.  */
+/* Given a vtable VAR, determine which binfo it comes from.
 
-static tree
-dfs_bfv_helper (binfo, data)
-     tree binfo;
-     void *data;
-{
-  struct bfv_info *bfvi = (struct bfv_info *) data;
-
-  if (BINFO_VTABLE (binfo) == bfvi->var)
-    return binfo;
-  return NULL_TREE;
-}
-
-/* Given a vtable VAR, determine which binfo it comes from.  */
+   FIXME What about secondary vtables?  */
 
 tree
 binfo_for_vtable (var)
      tree var;
 {
-  tree type;
-  struct bfv_info bfvi;
+  tree binfo = TYPE_BINFO (DECL_CONTEXT (var));
+  tree binfos;
+  int i;
 
-  type = DECL_CONTEXT (var);
-  bfvi.vbases = CLASSTYPE_VBASECLASSES (type);
-  bfvi.var = var;
-  return dfs_walk_real (TYPE_BINFO (type),
-                       0, dfs_bfv_helper, dfs_bfv_queue_p, &bfvi);
+  while (1)
+    {
+      binfos = BINFO_BASETYPES (binfo);
+      if (binfos == NULL_TREE)
+       break;
+
+      i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
+      if (i == -1)
+       break;
+
+      binfo = TREE_VEC_ELT (binfos, i);
+    }
+
+  return binfo;
 }
 
 /* Returns 1 iff BINFO is from a direct or indirect virtual base.  */
This page took 0.053368 seconds and 5 git commands to generate.