class.c (vcall_offset_data_s): Add last_init and fns.
authorMark Mitchell <mark@codesourcery.com>
Mon, 12 Jun 2000 20:46:28 +0000 (20:46 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 12 Jun 2000 20:46:28 +0000 (20:46 +0000)
* class.c (vcall_offset_data_s): Add last_init and fns.
(overrides): Rename to same_signature_p.
(dfs_find_final_overrider): Adjust accordingly.
(mark_overriders): Likewise.
(warn_hidden): Likewise.
(build_vtbl_initializer): Reorganize machinery for building things
at negative offsets.
(build_vcall_and_vbase_vtbl_entries): Likewise.
(build_vbase_offset_vtbl_entries): Likewise.
(dfs_build_vcall_offset_vtbl_entries): Correct order of vcall
offset entries.  Do not create two entries for functions with the
same signature.
(build_vcall_offset_vtbl_entries): Initialize vod->fns.
(build_rtti_vtbl_entries): Reorganize machinery for building things
at negative offsets.

From-SVN: r34503

gcc/cp/ChangeLog
gcc/cp/class.c

index 17000bd..5920a04 100644 (file)
@@ -1,5 +1,21 @@
 2000-06-12  Mark Mitchell  <mark@codesourcery.com>
 
+       * class.c (vcall_offset_data_s): Add last_init and fns.
+       (overrides): Rename to same_signature_p.
+       (dfs_find_final_overrider): Adjust accordingly.
+       (mark_overriders): Likewise.
+       (warn_hidden): Likewise.
+       (build_vtbl_initializer): Reorganize machinery for building things
+       at negative offsets.
+       (build_vcall_and_vbase_vtbl_entries): Likewise.
+       (build_vbase_offset_vtbl_entries): Likewise.
+       (dfs_build_vcall_offset_vtbl_entries): Correct order of vcall
+       offset entries.  Do not create two entries for functions with the
+       same signature.
+       (build_vcall_offset_vtbl_entries): Initialize vod->fns.
+       (build_rtti_vtbl_entries): Reorganize machinery for building things
+       at negative offsets.
+
        * optimize.c (expand_call_inline): Don't recurse into the code
        used to initialize the parameters more than once.
 
index c34deb0..4d9d399 100644 (file)
@@ -66,11 +66,17 @@ typedef struct vcall_offset_data_s
 {
   /* The binfo for the most-derived type.  */
   tree derived;
+  /* The negative-index vtable initializers built up so far.  These
+     are in order from least negative index to most negative index.  */
+  tree inits;
+  /* The last (i.e., most negative entry in INITS.  */
+  tree* last_init;
   /* The binfo for the virtual base for which we're building
      initializers.  */
   tree vbase;
-  /* The vcall offset initializers built up so far.  */
-  tree inits;
+  /* The functions in vbase for which we have already provided vcall
+     offsets.  */
+  varray_type fns;
   /* The vtable index of the next vcall or vbase offset.  */
   tree index;
   /* Nonzero if we are building the initializer for the primary
@@ -107,7 +113,7 @@ static void delete_duplicate_fields PARAMS ((tree));
 static void finish_struct_bits PARAMS ((tree));
 static int alter_access PARAMS ((tree, tree, tree));
 static void handle_using_decl PARAMS ((tree, tree));
-static int overrides PARAMS ((tree, tree));
+static int same_signature_p PARAMS ((tree, tree));
 static int strictly_overrides PARAMS ((tree, tree));
 static void mark_overriders PARAMS ((tree, tree));
 static void check_for_override PARAMS ((tree, tree));
@@ -174,7 +180,7 @@ static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
 static void layout_empty_base PARAMS ((tree, tree, varray_type));
 static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
 static void set_vindex PARAMS ((tree, tree, int *));
-static tree build_rtti_vtbl_entries PARAMS ((tree, tree));
+static void build_rtti_vtbl_entries PARAMS ((tree, tree, vcall_offset_data *));
 static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree, 
                                                        vcall_offset_data *));
 static tree dfs_mark_primary_bases PARAMS ((tree, void *));
@@ -2383,11 +2389,11 @@ layout_vtable_decl (binfo, n)
     }
 }
 
-/* True if we should override the given BASE_FNDECL with the given
-   FNDECL.  */
+/* True iff FNDECL and BASE_FNDECL (both non-static member functions)
+   have the same signature.  */
 
 static int
-overrides (fndecl, base_fndecl)
+same_signature_p (fndecl, base_fndecl)
      tree fndecl, base_fndecl;
 {
   /* One destructor overrides another if they are the same kind of
@@ -2455,7 +2461,8 @@ dfs_find_final_overrider (binfo, data)
          for (method = TYPE_METHODS (BINFO_TYPE (TREE_VALUE (path)));
               method;
               method = TREE_CHAIN (method))
-           if (DECL_VIRTUAL_P (method) && overrides (method, ffod->fn))
+           if (DECL_VIRTUAL_P (method) 
+               && same_signature_p (method, ffod->fn))
              break;
 
          if (method)
@@ -2826,10 +2833,8 @@ mark_overriders (fndecl, base_fndecls)
      tree fndecl, base_fndecls;
 {
   for (; base_fndecls; base_fndecls = TREE_CHAIN (base_fndecls))
-    {
-      if (overrides (fndecl, TREE_VALUE (base_fndecls)))
-       TREE_PURPOSE (base_fndecls) = fndecl;
-    }
+    if (same_signature_p (fndecl, TREE_VALUE (base_fndecls)))
+      TREE_PURPOSE (base_fndecls) = fndecl;
 }
 
 /* If this declaration supersedes the declaration of
@@ -2955,15 +2960,13 @@ warn_hidden (t)
       /* Now give a warning for all base functions without overriders,
         as they are hidden.  */
       for (; base_fndecls; base_fndecls = TREE_CHAIN (base_fndecls))
-       {
-         if (! overrides (TREE_PURPOSE (base_fndecls),
-                          TREE_VALUE (base_fndecls)))
-           {
-             /* Here we know it is a hider, and no overrider exists.  */
-             cp_warning_at ("`%D' was hidden", TREE_VALUE (base_fndecls));
-             cp_warning_at ("  by `%D'", TREE_PURPOSE (base_fndecls));
-           }
-       }
+       if (!same_signature_p (TREE_PURPOSE (base_fndecls),
+                              TREE_VALUE (base_fndecls)))
+         {
+           /* Here we know it is a hider, and no overrider exists.  */
+           cp_warning_at ("`%D' was hidden", TREE_VALUE (base_fndecls));
+           cp_warning_at ("  by `%D'", TREE_PURPOSE (base_fndecls));
+         }
     }
 }
 
@@ -6938,33 +6941,32 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
      int *non_fn_entries_p;
 {
   tree v;
-  tree inits;
-  tree vfun_inits;
+   tree vfun_inits;
   tree vbase;
   vcall_offset_data vod;
 
   /* Initialize those parts of VOD that matter.  */
   vod.derived = t;
   vod.inits = NULL_TREE;
+  vod.last_init = &vod.inits;
   vod.primary_p = (binfo == TYPE_BINFO (t));
   /* The first vbase or vcall offset is at index -3 in the vtable.  */
   vod.index = build_int_2 (-3, -1);
 
+  /* Add entries to the vtable for RTTI.  */
+  build_rtti_vtbl_entries (binfo, rtti_binfo, &vod);
+
   /* Add the vcall and vbase offset entries.  */
   build_vcall_and_vbase_vtbl_entries (binfo, &vod);
-  inits = vod.inits;
-  /* Clear BINFO_VTABLE_PAATH_MARKED; it's set by
+   /* Clear BINFO_VTABLE_PAATH_MARKED; it's set by
      build_vbase_offset_vtbl_entries.  */
   for (vbase = CLASSTYPE_VBASECLASSES (t); 
        vbase; 
        vbase = TREE_CHAIN (vbase))
     CLEAR_BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase));
 
-  /* Add entries to the vtable for RTTI.  */
-  inits = chainon (inits, build_rtti_vtbl_entries (binfo, rtti_binfo));
-
   if (non_fn_entries_p)
-    *non_fn_entries_p = list_length (inits);
+    *non_fn_entries_p = list_length (vod.inits);
 
   /* Go through all the ordinary virtual functions, building up
      initializers.  */
@@ -7005,9 +7007,11 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
      order; straighten them out now.  */
   vfun_inits = nreverse (vfun_inits);
   
-  /* The complete initializer is the INITS, followed by the
-     VFUN_INITS.  */
-  return chainon (inits, vfun_inits);
+  /* The negative offset initializers are also in reverse order.  */
+  vod.inits = nreverse (vod.inits);
+
+  /* Chain the two together.  */
+  return chainon (vod.inits, vfun_inits);
 }
 
 /* Sets vod->inits to be the initializers for the vbase and vcall
@@ -7019,14 +7023,9 @@ build_vcall_and_vbase_vtbl_entries (binfo, vod)
      vcall_offset_data *vod;
 {
   tree b;
-  tree inits;
 
   /* If this is a derived class, we must first create entries
-     corresponding to the base class.  These entries must go closer to
-     the vptr, so we save them up and add them to the end of the list
-     later.  */
-  inits = vod->inits;
-  vod->inits = NULL_TREE;
+     corresponding to the primary base class.  */
   b = BINFO_PRIMARY_BINFO (binfo);
   if (b)
     build_vcall_and_vbase_vtbl_entries (b, vod);
@@ -7035,8 +7034,6 @@ build_vcall_and_vbase_vtbl_entries (binfo, vod)
   build_vbase_offset_vtbl_entries (binfo, vod);
   /* Add the vcall entries for this base.  */
   build_vcall_offset_vtbl_entries (binfo, vod);
-
-  vod->inits = chainon (vod->inits, inits);
 }
 
 /* Returns the initializers for the vbase offset entries in the vtable
@@ -7116,11 +7113,12 @@ build_vbase_offset_vtbl_entries (binfo, vod)
         we are walking in inheritance graph order so these end up in
         the right order.  */
       delta = size_diffop (BINFO_OFFSET (b), BINFO_OFFSET (binfo));
-      vod->inits = tree_cons (NULL_TREE, 
-                             fold (build1 (NOP_EXPR, 
-                                           vtable_entry_type,
-                                           delta)),
-                             vod->inits);
+      *vod->last_init 
+       = build_tree_list (NULL_TREE,
+                          fold (build1 (NOP_EXPR, 
+                                        vtable_entry_type,
+                                        delta)));
+      vod->last_init = &TREE_CHAIN (*vod->last_init);
     }
 }
 
@@ -7162,22 +7160,48 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
       }
 
   /* Make entries for the rest of the virtuals.  */
-  while (base_virtuals)
+  for (; base_virtuals;
+       derived_virtuals = TREE_CHAIN (derived_virtuals),
+        base_virtuals = TREE_CHAIN (base_virtuals))
     {
       /* Figure out what function we're looking at.  */
       tree fn = TREE_VALUE (derived_virtuals);
-      tree base = DECL_CONTEXT (fn);
+      tree base;
+      tree base_binfo;
+      size_t i;
+
+      /* If there is already an entry for a function with the same
+        signature as FN, then we do not need a second vcall offset.
+        Check the list of functions already present in the derived
+        class vtable.  */
+      for (i = 0; i < VARRAY_ACTIVE_SIZE (vod->fns); ++i) 
+       {
+         tree derived_entry;
+
+         derived_entry = VARRAY_TREE (vod->fns, i);
+         if (same_signature_p (TREE_VALUE (derived_entry), fn))
+           {
+             BV_VCALL_INDEX (derived_virtuals) 
+               = BV_VCALL_INDEX (derived_entry);
+             break;
+           }
+       }
+      if (i != VARRAY_ACTIVE_SIZE (vod->fns))
+       continue;
+
       /* The FN comes from BASE.  So, we must caculate the adjustment
         from the virtual base that derived from BINFO to BASE.  */
-      tree base_binfo = get_binfo (base, vod->derived, /*protect=*/0);
+      base = DECL_CONTEXT (fn);
+      base_binfo = get_binfo (base, vod->derived, /*protect=*/0);
 
       /* Compute the vcall offset.  */
-      binfo_inits
-       = tree_cons (NULL_TREE,
-                    fold (build1 (NOP_EXPR, vtable_entry_type,
-                                  size_diffop (BINFO_OFFSET (base_binfo),
-                                               BINFO_OFFSET (vod->vbase)))),
-                    binfo_inits);
+      *vod->last_init 
+       = (build_tree_list 
+          (NULL_TREE,
+           fold (build1 (NOP_EXPR, vtable_entry_type,
+                         size_diffop (BINFO_OFFSET (base_binfo),
+                                      BINFO_OFFSET (vod->vbase))))));
+      vod->last_init = &TREE_CHAIN (*vod->last_init);
 
       /* If there is already a vcall index, then we are processing a
         construction vtable.  The index should be the same as it was
@@ -7197,24 +7221,8 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
       vod->index = fold (build (MINUS_EXPR, integer_type_node,
                                vod->index, integer_one_node));
 
-      /* Go to the next entries in the list.  */
-      derived_virtuals = TREE_CHAIN (derived_virtuals);
-      base_virtuals = TREE_CHAIN (base_virtuals);
-    }
-
-  /* The offests are built up in reverse order, so we straighten them
-     here.  We simultaneously add them to VOD->INITS; we're walking
-     the bases in inheritance graph order, and the initializers are
-     supposed to appear in reverse inheritance order, so that's
-     correct.  */
-  while (binfo_inits)
-    {
-      tree next;
-
-      next = TREE_CHAIN (binfo_inits);
-      TREE_CHAIN (binfo_inits) = vod->inits;
-      vod->inits = binfo_inits;
-      binfo_inits = next;
+      /* Keep track of this function.  */
+      VARRAY_PUSH_TREE (vod->fns, derived_virtuals);
     }
 
   return NULL_TREE;
@@ -7229,8 +7237,6 @@ build_vcall_offset_vtbl_entries (binfo, vod)
      tree binfo;
      vcall_offset_data *vod;
 {
-  tree inits;
-
   /* Under the old ABI, the adjustments to the `this' pointer were made
      elsewhere.  */
   if (!vcall_offsets_in_vtable_p ())
@@ -7263,24 +7269,24 @@ build_vcall_offset_vtbl_entries (binfo, vod)
      appear in the same order as in the base; but the bases themselves
      appear in reverse depth-first, left-to-right order.  */
   vod->vbase = binfo;
-  inits = vod->inits;
-  vod->inits = NULL_TREE;
+  VARRAY_TREE_INIT (vod->fns, 32, "fns");
   dfs_walk_real (binfo,
                 dfs_build_vcall_offset_vtbl_entries,
                 NULL,
                 dfs_skip_vbases,
                 vod);
-  vod->inits = chainon (vod->inits, inits);
+  VARRAY_FREE (vod->fns);
 }
 
 /* Return vtbl initializers for the RTTI entries coresponding to the
    BINFO's vtable.  The RTTI entries should indicate the object given
    by RTTI_BINFO.  */
 
-static tree
-build_rtti_vtbl_entries (binfo, rtti_binfo)
+static void
+build_rtti_vtbl_entries (binfo, rtti_binfo, vod)
      tree binfo;
      tree rtti_binfo;
+     vcall_offset_data *vod;
 {
   tree b;
   tree t;
@@ -7288,15 +7294,13 @@ build_rtti_vtbl_entries (binfo, rtti_binfo)
   tree offset;
   tree decl;
   tree init;
-  tree inits;
 
   basetype = BINFO_TYPE (binfo);
-  inits = NULL_TREE;
   t = BINFO_TYPE (rtti_binfo);
 
   /* For a COM object there is no RTTI entry.  */
   if (CLASSTYPE_COM_INTERFACE (basetype))
-    return inits;
+    return;
 
   /* To find the complete object, we will first convert to our most
      primary base, and then add the offset in the vtbl to that value.  */
@@ -7340,7 +7344,8 @@ build_rtti_vtbl_entries (binfo, rtti_binfo)
       TREE_CONSTANT (init) = 1;
       init = build_vtable_entry (offset, integer_zero_node, init);
     }
-  inits = tree_cons (NULL_TREE, init, inits);
+  *vod->last_init = build_tree_list (NULL_TREE, init);
+  vod->last_init = &TREE_CHAIN (*vod->last_init);
 
   /* Add the offset-to-top entry.  It comes earlier in the vtable that
      the the typeinfo entry.  */
@@ -7350,10 +7355,9 @@ build_rtti_vtbl_entries (binfo, rtti_binfo)
         we can put it in the vtable.  */
       init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
       TREE_CONSTANT (init) = 1;
-      inits = tree_cons (NULL_TREE, init, inits);
+      *vod->last_init = build_tree_list (NULL_TREE, init);
+      vod->last_init = &TREE_CHAIN (*vod->last_init);
     }
-
-  return inits;
 }
 
 /* Build an entry in the virtual function table.  DELTA is the offset