]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
cp-tree.h (build_shared_int_cst): New function.
authorMark Mitchell <mark@codesourcery.com>
Mon, 17 Jan 2000 22:54:23 +0000 (22:54 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 17 Jan 2000 22:54:23 +0000 (22:54 +0000)
* cp-tree.h (build_shared_int_cst): New function.
* call.c (build_over_call): Use DECL_VIRTUAL_CONTEXT, for clarity.
* class.c (modify_vtable_entry): Likewise.
(add_virtual_function): Split out code to generated shared
INTEGER_CSTs to build_share_int_cst.
(modify_all_vtables): Handle all the overridden functions here.
Add overridden functions from non-primary virtual bases to the
primary vtable.
(finish_struct_1): Adjust call to modify_all_vtables.  Add
overridden functions from non-primary bases to the vtable.
* tree.c (build_shared_int_cst): New function.

From-SVN: r31476

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/tree.c

index 04ee628f964c8fb49b4b963ce480b1e7ba82c315..8fe890e329222a06300c428309f2cbce9efc7b44 100644 (file)
@@ -1,5 +1,17 @@
 2000-01-17  Mark Mitchell  <mark@codesourcery.com>
 
+       * cp-tree.h (build_shared_int_cst): New function.
+       * call.c (build_over_call): Use DECL_VIRTUAL_CONTEXT, for clarity.
+       * class.c (modify_vtable_entry): Likewise.
+       (add_virtual_function): Split out code to generated shared
+       INTEGER_CSTs to build_share_int_cst.
+       (modify_all_vtables): Handle all the overridden functions here.
+       Add overridden functions from non-primary virtual bases to the
+       primary vtable.
+       (finish_struct_1): Adjust call to modify_all_vtables.  Add
+       overridden functions from non-primary bases to the vtable.
+       * tree.c (build_shared_int_cst): New function.
+       
        * cp-tree.h (scratchalloc): Remove.
        (build_scratch_list): Likewise.
        * call.c (convert_class_to_reference): Replace build_scratch_list
index 7114d022b961e707643a3b7bc9b3f48b51d80c76..f526abfa4fec5daa7e876d810345aaadc3daf1f1 100644 (file)
@@ -4126,7 +4126,7 @@ build_over_call (cand, args, flags)
     {
       tree t, *p = &TREE_VALUE (converted_args);
       tree binfo = get_binfo
-       (DECL_CONTEXT (fn), TREE_TYPE (TREE_TYPE (*p)), 0);
+       (DECL_VIRTUAL_CONTEXT (fn), TREE_TYPE (TREE_TYPE (*p)), 0);
       *p = convert_pointer_to_real (binfo, *p);
       if (TREE_SIDE_EFFECTS (*p))
        *p = save_expr (*p);
index 6d221eb5fca7c5da18236d4fd6438695821407dd..5539176a1dcd70f1e004b671af390a73981f5259 100644 (file)
@@ -103,7 +103,7 @@ static tree dfs_get_class_offset PROTO((tree, void *));
 static tree get_class_offset PROTO((tree, tree, tree, tree));
 static void modify_one_vtable PROTO((tree, tree, tree));
 static tree dfs_modify_vtables PROTO((tree, void *));
-static void modify_all_vtables PROTO((tree, tree));
+static tree modify_all_vtables PROTO((tree, int *, tree));
 static void determine_primary_base PROTO((tree, int *));
 static void finish_struct_methods PROTO((tree));
 static void maybe_warn_about_overly_private_class PROTO ((tree));
@@ -1107,7 +1107,7 @@ modify_vtable_entry (old_entry_in_list, new_offset, fndecl)
   if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
     {
       DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
-      DECL_CONTEXT (fndecl) = DECL_CONTEXT (base_fndecl);
+      DECL_VIRTUAL_CONTEXT (fndecl) = DECL_VIRTUAL_CONTEXT (base_fndecl);
     }
 }
 
@@ -1166,8 +1166,6 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p,
      tree fndecl;
      tree t; /* Structure type.  */
 {
-  my_friendly_assert (DECL_CONTEXT (fndecl) == t, 20000116);
-
   /* If this function doesn't override anything from a base class, we
      can just assign it a new DECL_VINDEX now.  Otherwise, if it does
      override something, we keep it around and assign its DECL_VINDEX
@@ -1185,25 +1183,10 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p,
 
       start_vtable (t, has_virtual);
 
-      /* Build a new INT_CST for this DECL_VINDEX.  */
-      {
-       static tree index_table[256];
-       tree idx;
-       /* We skip a slot for the offset/tdesc entry.  */
-       int i = (*has_virtual)++;
-
-       if (i >= 256 || index_table[i] == 0)
-         {
-           idx = build_int_2 (i, 0);
-           if (i < 256)
-             index_table[i] = idx;
-         }
-       else
-         idx = index_table[i];
+      /* Now assign virtual dispatch information.  */
+      DECL_VINDEX (fndecl) = build_shared_int_cst ((*has_virtual)++);
+      DECL_VIRTUAL_CONTEXT (fndecl) = t;
 
-       /* Now assign virtual dispatch information.  */
-       DECL_VINDEX (fndecl) = idx;
-      }
       /* Save the state we've computed on the NEW_VIRTUALS list.  */
       *new_virtuals_p = tree_cons (integer_zero_node,
                                   fndecl,
@@ -2752,17 +2735,81 @@ dfs_modify_vtables (binfo, data)
   return NULL_TREE;
 }
 
-static void
-modify_all_vtables (t, fndecl)
+/* Update all of the primary and secondary vtables for T.  Create new
+   vtables as required, and initialize their RTTI information.  Each
+   of the functions in OVERRIDDEN_VIRTUALS overrides a virtual
+   function from a base class; find and modify the appropriate entries
+   to point to the overriding functions.  Returns a list, in
+   declaration order, of the functions that are overridden in this
+   class, but do not appear in the primary base class vtable, and
+   which should therefore be appended to the end of the vtable for T.  */
+
+static tree
+modify_all_vtables (t, has_virtual_p, overridden_virtuals)
      tree t;
-     tree fndecl;
+     int *has_virtual_p;
+     tree overridden_virtuals;
 {
-  tree list;
+  tree fns;
+  tree binfo;
 
-  list = build_tree_list (t, fndecl);
-  dfs_walk (TYPE_BINFO (t), dfs_modify_vtables, 
-           dfs_unmarked_real_bases_queue_p, list);
-  dfs_walk (TYPE_BINFO (t), dfs_unmark, dfs_marked_real_bases_queue_p, t);
+  binfo = TYPE_BINFO (t);
+
+  /* Even if there are no overridden virtuals, we want to go through
+     the hierarchy updating RTTI information.  */
+  if (!overridden_virtuals && TYPE_CONTAINS_VPTR_P (t) && flag_rtti)
+    overridden_virtuals = build_tree_list (NULL_TREE, NULL_TREE);
+
+  /* Iterate through each of the overriding functions, updating the
+     base vtables.  */
+  for (fns = overridden_virtuals; fns; fns = TREE_CHAIN (fns))
+    {
+      tree list;
+      list = build_tree_list (t, TREE_VALUE (fns));
+      dfs_walk (binfo, dfs_modify_vtables, 
+               dfs_unmarked_real_bases_queue_p, list);
+      dfs_walk (binfo, dfs_unmark, dfs_marked_real_bases_queue_p, t);
+    }
+
+  /* If we should include overriding functions for secondary vtables
+     in our primary vtable, add them now.  */
+  if (all_overridden_vfuns_in_vtables_p ())
+    {
+      tree *fnsp = &overridden_virtuals;
+
+      while (*fnsp)
+       {
+         tree fn = TREE_VALUE (*fnsp);
+
+         if (BINFO_VIRTUALS (binfo)
+             && !value_member (fn, BINFO_VIRTUALS (binfo)))
+           {
+             /* We know we need a vtable for this class now.  */
+             start_vtable (t, has_virtual_p);
+             /* Set the vtable index.  */
+             DECL_VINDEX (fn) 
+               = build_shared_int_cst ((*has_virtual_p)++);
+             /* We don't need to convert to a base class when calling
+                this function.  */
+             DECL_VIRTUAL_CONTEXT (fn) = t;
+             /* We don't need to adjust the `this' pointer when
+                calling this function.  */
+             TREE_PURPOSE (*fnsp) = integer_zero_node;
+
+             /* This is an overridden function not already in our
+                vtable.  Keep it.  */
+             fnsp = &TREE_CHAIN (*fnsp);
+           }
+         else
+           /* We've already got an entry for this function.  Skip
+              it.  */
+           *fnsp = TREE_CHAIN (*fnsp);
+       }
+    }
+  else
+    overridden_virtuals = NULL_TREE;
+
+  return overridden_virtuals;
 }
 
 /* Fixup all the delta entries in this one vtable that need updating.  */
@@ -4818,22 +4865,15 @@ finish_struct_1 (t)
       TYPE_VFIELD (t) = vfield;
     }
 
-  if (flag_rtti && TYPE_CONTAINS_VPTR_P (t) && !overridden_virtuals)
-    modify_all_vtables (t, NULL_TREE);
+  overridden_virtuals 
+    = modify_all_vtables (t, &has_virtual, nreverse (overridden_virtuals));
 
-  for (overridden_virtuals = nreverse (overridden_virtuals);
-       overridden_virtuals;
-       overridden_virtuals = TREE_CHAIN (overridden_virtuals))
-    modify_all_vtables (t, TREE_VALUE (overridden_virtuals));
-  
   if (TYPE_USES_VIRTUAL_BASECLASSES (t))
     {
       tree vbases;
       /* Now fixup any virtual function entries from virtual bases
         that have different deltas.  This has to come after we do the
-        pending hard virtuals, as we might have a function that comes
-        from multiple virtual base instances that is only overridden
-        by a hard virtual above.  */
+        overridden virtuals.  */
       vbases = CLASSTYPE_VBASECLASSES (t);
       while (vbases)
        {
@@ -4851,6 +4891,7 @@ finish_struct_1 (t)
 
   /* If necessary, create the vtable for this class.  */
   if (new_virtuals
+      || overridden_virtuals
       || (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ()))
     {
       new_virtuals = nreverse (new_virtuals);
@@ -4859,7 +4900,8 @@ finish_struct_1 (t)
        {
          if (! CLASSTYPE_COM_INTERFACE (t))
            {
-             /* The second slot is for the tdesc pointer when thunks are used.  */
+             /* The second slot is for the tdesc pointer when thunks
+                are used.  */
              if (flag_vtable_thunks)
                new_virtuals = tree_cons (NULL_TREE, NULL_TREE, new_virtuals);
 
@@ -4918,6 +4960,10 @@ finish_struct_1 (t)
         followed by entries for new functions unique to this class.  */
       TYPE_BINFO_VIRTUALS (t) 
        = chainon (TYPE_BINFO_VIRTUALS (t), new_virtuals);
+      /* Finally, add entries for functions that override virtuals
+        from non-primary bases.  */
+      TYPE_BINFO_VIRTUALS (t) 
+       = chainon (TYPE_BINFO_VIRTUALS (t), overridden_virtuals);
     }
 
   /* Now lay out the virtual function table.  */
index 366181da256ed47945d7c683060123541e60a62a..e0e29481830d5f7cb6544d565cb9917536f21357 100644 (file)
@@ -4199,6 +4199,7 @@ extern tree cp_build_qualified_type_real        PROTO((tree, int, int));
 extern void remap_save_expr                     PROTO((tree *, splay_tree, tree, int *));
 #define cp_build_qualified_type(TYPE, QUALS) \
   cp_build_qualified_type_real ((TYPE), (QUALS), /*complain=*/1)
+extern tree build_shared_int_cst                PROTO((int));
 
 /* in typeck.c */
 extern int string_conv_p                       PROTO((tree, tree, int));
index 3c342d5f87727f214f98d9c15db223817ccbe33b..3bf874a8351878c5c1850118102525fa26da056b 100644 (file)
@@ -1,5 +1,5 @@
 /* Language-dependent node constructors for parse phase of GNU compiler.
-   Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 92-98, 1999, 2000 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GNU CC.
@@ -1710,6 +1710,26 @@ build_min VPROTO((enum tree_code code, tree tt, ...))
   return t;
 }
 
+/* Returns an INTEGER_CST (of type `int') corresponding to I.
+   Multiple calls with the same value of I may or may not yield the
+   same node; therefore, callers should never modify the node
+   returned.  */
+
+tree
+build_shared_int_cst (i)
+     int i;
+{
+  static tree cache[256];
+
+  if (i >= 256)
+    return build_int_2 (i, 0);
+  
+  if (!cache[i])
+    cache[i] = build_int_2 (i, 0);
+  
+  return cache[i];
+}
+
 tree
 get_type_decl (t)
      tree t;