]> gcc.gnu.org Git - gcc.git/commitdiff
call.c (build_special_member_call): Do not try to lookup VTTs by name.
authorMark Mitchell <mark@codesourcery.com>
Mon, 4 Nov 2002 01:45:58 +0000 (01:45 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 4 Nov 2002 01:45:58 +0000 (01:45 +0000)
* call.c (build_special_member_call): Do not try to lookup VTTs by
name.
* class.c (vtbl_init_data): Add generate_vcall_entries.
(get_vtable_decl): Do not look up virtual tables by name.
(copy_virtuals): Do not use BV_USE_VCALL_INDEX_P.
(set_primary_base): Do not set CLASSTYPE_RTTI.
(determine_primary_base): Likewise.
(get_matching_virtual): Remove.
(get_vcall_index): New function.
(update_vtable_entry_for_fn): Do not try to use virtual thunks
when they are not required.  Assign vcall indices at this point.
(finish_struct_1): Do not set CLASSTYPE_NEEDS_VIRTUAL_REINIT.
Do update dynamic_classes.
(build_vtt): Do not add VTTs to the symbol table.
(build_ctor_vtbl_group): Likewise.
(build_vtbl_initializer): Simplify handling of vcall indices.
(build_vcall_offset_vtbl_entries): Pretend to build vcall offsets
for the most derived class.
(add_vcall_offset_vtbl_entries_1): But do not actually add them to
the vtable.
* cp-tree.h (dynamic_classes): New macro.
(lang_type_class): Remove rtti.  Add vtables.  Add vcall_indices.
(CLASSTYPE_RTTI): Remove.
(CLASSTYPE_NEEDS_VIRTUAL_REINIT): Remove.
(CLASSTYPE_VCALL_INDICES): New macro.
(CLASSTYPE_VTABLES): Likewise.
(BV_USE_VCALL_INDEX_P): Remove.
(build_vtable_path): Remove.
* decl2.c (finish_vtable_vardecl): Remove.
(key_method): Remove #if 0'd code.
(finish_vtable_vardecl): Rename to ...
(maybe_emit_vtables): ... this.
(finish_file): Use it.
* search.c (look_for_overrides_here): Update comment.

* g++.dg/abi/thunk1.C: New test.
* g++.dg/abi/thunk2.C: Likewise.
* g++.dg/abi/vtt1.C: Likewise.

From-SVN: r58779

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/search.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/thunk1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/thunk2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/vtt1.C [new file with mode: 0644]

index ce94b3a11b8ec451fb52cb73d4d81e11a27616e0..2fb30a9467dd6c2362b6bbfed043b223c5be0a52 100644 (file)
@@ -1,3 +1,40 @@
+2002-11-03  Mark Mitchell  <mark@codesourcery.com>
+
+       * call.c (build_special_member_call): Do not try to lookup VTTs by
+       name.
+       * class.c (vtbl_init_data): Add generate_vcall_entries.
+       (get_vtable_decl): Do not look up virtual tables by name.
+       (copy_virtuals): Do not use BV_USE_VCALL_INDEX_P.
+       (set_primary_base): Do not set CLASSTYPE_RTTI.
+       (determine_primary_base): Likewise.
+       (get_matching_virtual): Remove.
+       (get_vcall_index): New function.
+       (update_vtable_entry_for_fn): Do not try to use virtual thunks
+       when they are not required.  Assign vcall indices at this point.
+       (finish_struct_1): Do not set CLASSTYPE_NEEDS_VIRTUAL_REINIT.
+       Do update dynamic_classes.
+       (build_vtt): Do not add VTTs to the symbol table.
+       (build_ctor_vtbl_group): Likewise.
+       (build_vtbl_initializer): Simplify handling of vcall indices.
+       (build_vcall_offset_vtbl_entries): Pretend to build vcall offsets
+       for the most derived class.
+       (add_vcall_offset_vtbl_entries_1): But do not actually add them to
+       the vtable.
+       * cp-tree.h (dynamic_classes): New macro.
+       (lang_type_class): Remove rtti.  Add vtables.  Add vcall_indices.
+       (CLASSTYPE_RTTI): Remove.
+       (CLASSTYPE_NEEDS_VIRTUAL_REINIT): Remove.
+       (CLASSTYPE_VCALL_INDICES): New macro.
+       (CLASSTYPE_VTABLES): Likewise.
+       (BV_USE_VCALL_INDEX_P): Remove.
+       (build_vtable_path): Remove.
+       * decl2.c (finish_vtable_vardecl): Remove.
+       (key_method): Remove #if 0'd code.
+       (finish_vtable_vardecl): Rename to ...
+       (maybe_emit_vtables): ... this.
+       (finish_file): Use it.
+       * search.c (look_for_overrides_here): Update comment.
+
 2002-11-01  Zack Weinberg  <zack@codesourcery.com>
 
        PR c/7353 redux
index a347bbacd7f2f2719d1a016ab26ea5b5f9d011d8..a7f9a917d15169f60cd5e1ea9fdb9d7d45751b0c 100644 (file)
@@ -4712,7 +4712,7 @@ build_special_member_call (tree instance, tree name, tree args,
       /* If the current function is a complete object constructor
         or destructor, then we fetch the VTT directly.
         Otherwise, we look it up using the VTT we were given.  */
-      vtt = IDENTIFIER_GLOBAL_VALUE (get_vtt_name (current_class_type));
+      vtt = TREE_CHAIN (CLASSTYPE_VTABLES (current_class_type));
       vtt = decay_conversion (vtt);
       vtt = build (COND_EXPR, TREE_TYPE (vtt),
                   build (EQ_EXPR, boolean_type_node,
index d189686fdcf4877b344de60f9a54fc75a805884c..0dffc62ea695443f51d574cb29c01a67f74780cf 100644 (file)
@@ -87,6 +87,9 @@ typedef struct vtbl_init_data_s
   /* Nonzero if we are building the initializer for a construction
      vtable.  */
   int ctor_vtbl_p;
+  /* True when adding vcall offset entries to the vtable.  False when
+     merely computing the indices.  */
+  bool generate_vcall_entries;
 } vtbl_init_data;
 
 /* The type of a function passed to walk_subobject_offsets.  */
@@ -209,6 +212,7 @@ static tree dfs_base_derived_from (tree, void *);
 static bool base_derived_from (tree, tree);
 static int empty_base_at_nonzero_offset_p (tree, tree, splay_tree);
 static tree end_of_base (tree);
+static tree get_vcall_index (tree, tree);
 
 /* Macros for dfs walking during vtt construction. See
    dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
@@ -540,21 +544,14 @@ get_vtable_decl (type, complete)
      tree type;
      int complete;
 {
-  tree name = get_vtable_name (type);
-  tree decl = IDENTIFIER_GLOBAL_VALUE (name);
-  
-  if (decl)
-    {
-      my_friendly_assert (TREE_CODE (decl) == VAR_DECL
-                          && DECL_VIRTUAL_P (decl), 20000118);
-      return decl;
-    }
-  
-  decl = build_vtable (type, name, void_type_node);
-  decl = pushdecl_top_level (decl);
-  my_friendly_assert (IDENTIFIER_GLOBAL_VALUE (name) == decl,
-                     20000517);
+  tree decl;
+
+  if (CLASSTYPE_VTABLES (type))
+    return CLASSTYPE_VTABLES (type);
   
+  decl = build_vtable (type, get_vtable_name (type), void_type_node);
+  CLASSTYPE_VTABLES (type) = decl;
+
   /* At one time the vtable info was grabbed 2 words at a time.  This
      fails on sparc unless you have 8-byte alignment.  (tiemann) */
   DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),
@@ -581,10 +578,7 @@ copy_virtuals (binfo)
 
   copies = copy_list (BINFO_VIRTUALS (binfo));
   for (t = copies; t; t = TREE_CHAIN (t))
-    {
-      BV_VCALL_INDEX (t) = NULL_TREE;
-      BV_USE_VCALL_INDEX_P (t) = 0;
-    }
+    BV_VCALL_INDEX (t) = NULL_TREE;
 
   return copies;
 }
@@ -1559,7 +1553,6 @@ set_primary_base (t, binfo)
   TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
   TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
   TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
-  CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
 }
 
 /* Determine the primary class for T.  */
@@ -1585,12 +1578,6 @@ determine_primary_base (t)
 
       if (TYPE_CONTAINS_VPTR_P (basetype))
        {
-         /* Even a virtual baseclass can contain our RTTI
-            information.  But, we prefer a non-virtual polymorphic
-            baseclass.  */
-         if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
-           CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
-
          /* We prefer a non-virtual base, although a virtual one will
             do.  */
          if (TREE_VIA_VIRTUAL (base_binfo))
@@ -2325,21 +2312,23 @@ find_final_overrider (t, binfo, fn)
   return ffod.candidates;
 }
 
-/* Returns the function from the BINFO_VIRTUALS entry in T which matches
-   the signature of FUNCTION_DECL FN, or NULL_TREE if none.  In other words,
-   the function that the slot in T's primary vtable points to.  */
+/* Return the index of the vcall offset for FN when TYPE is used as a
+   virtual base.  */
 
-static tree get_matching_virtual PARAMS ((tree, tree));
 static tree
-get_matching_virtual (t, fn)
-     tree t, fn;
+get_vcall_index (tree fn, tree type)
 {
-  tree f;
+  tree v;
 
-  for (f = BINFO_VIRTUALS (TYPE_BINFO (t)); f; f = TREE_CHAIN (f))
-    if (same_signature_p (BV_FN (f), fn))
-      return BV_FN (f);
-  return NULL_TREE;
+  for (v = CLASSTYPE_VCALL_INDICES (type); v; v = TREE_CHAIN (v))
+    if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (TREE_PURPOSE (v)))
+       || same_signature_p (fn, TREE_PURPOSE (v)))
+      break;
+
+  /* There should always be an appropriate index.  */
+  my_friendly_assert (v, 20021103);
+
+  return TREE_VALUE (v);
 }
 
 /* Update an entry in the vtable for BINFO, which is in the hierarchy
@@ -2407,7 +2396,6 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
   /* Compute the constant adjustment to the `this' pointer.  The
      `this' pointer, when this function is called, will point at BINFO
      (or one of its primary bases, which are at the same offset).  */
-
   if (virtual_base)
     /* The `this' pointer needs to be adjusted from the declaration to
        the nearest virtual base.  */
@@ -2420,36 +2408,11 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
        will be zero, as it will be a primary base.  */
     delta = size_zero_node;
   else
-    {
-      /* The `this' pointer needs to be adjusted from pointing to
-        BINFO to pointing at the base where the final overrider
-        appears.  */
-      delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
-                          BINFO_OFFSET (binfo));
-
-      if (! integer_zerop (delta))
-       {
-         /* We'll need a thunk.  But if we have a (perhaps formerly)
-            primary virtual base, we have a vcall slot for this function,
-            so we can use it rather than create a non-virtual thunk.  */
-         
-         b = get_primary_binfo (first_defn);
-         for (; b; b = get_primary_binfo (b))
-           {
-             tree f = get_matching_virtual (BINFO_TYPE (b), fn);
-             if (!f)
-               /* b doesn't have this function; no suitable vbase.  */
-               break;
-             if (TREE_VIA_VIRTUAL (b))
-               {
-                 /* Found one; we can treat ourselves as a virtual base.  */
-                 virtual_base = binfo;
-                 delta = size_zero_node;
-                 break;
-               }
-           }
-       }
-    }
+    /* The `this' pointer needs to be adjusted from pointing to
+       BINFO to pointing at the base where the final overrider
+       appears.  */
+    delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
+                        BINFO_OFFSET (binfo));
 
   modify_vtable_entry (t, 
                       binfo, 
@@ -2458,7 +2421,9 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
                       virtuals);
 
   if (virtual_base)
-    BV_USE_VCALL_INDEX_P (*virtuals) = 1;
+    BV_VCALL_INDEX (*virtuals) 
+      = get_vcall_index (TREE_PURPOSE (overrider),
+                        BINFO_TYPE (virtual_base));
 }
 
 /* Called from modify_all_vtables via dfs_walk.  */
@@ -5101,32 +5066,8 @@ layout_class_type (tree t, tree *virtuals_p)
   splay_tree_delete (empty_base_offsets);
 }
 
-/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
-   (or C++ class declaration).
-
-   For C++, we must handle the building of derived classes.
-   Also, C++ allows static class members.  The way that this is
-   handled is to keep the field name where it is (as the DECL_NAME
-   of the field), and place the overloaded decl in the bit position
-   of the field.  layout_record and layout_union will know about this.
-
-   More C++ hair: inline functions have text in their
-   DECL_PENDING_INLINE_INFO nodes which must somehow be parsed into
-   meaningful tree structure.  After the struct has been laid out, set
-   things up so that this can happen.
-
-   And still more: virtual functions.  In the case of single inheritance,
-   when a new virtual function is seen which redefines a virtual function
-   from the base class, the new virtual function is placed into
-   the virtual function table at exactly the same address that
-   it had in the base class.  When this is extended to multiple
-   inheritance, the same thing happens, except that multiple virtual
-   function tables must be maintained.  The first virtual function
-   table is treated in exactly the same way as in the case of single
-   inheritance.  Additional virtual function tables have different
-   DELTAs, which tell how to adjust `this' to point to the right thing.
-
-   ATTRIBUTES is the set of decl attributes to be applied, if any.  */
+/* Perform processing required when the definition of T (a class type)
+   is complete.  */
 
 void
 finish_struct_1 (t)
@@ -5153,7 +5094,6 @@ finish_struct_1 (t)
   TYPE_SIZE (t) = NULL_TREE;
   CLASSTYPE_GOT_SEMICOLON (t) = 0;
   CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
-  CLASSTYPE_RTTI (t) = NULL_TREE;
 
   fixup_inline_methods (t);
   
@@ -5210,24 +5150,6 @@ finish_struct_1 (t)
        /* Here we know enough to change the type of our virtual
           function table, but we will wait until later this function.  */
        build_primary_vtable (CLASSTYPE_PRIMARY_BINFO (t), t);
-
-      /* If this type has basetypes with constructors, then those
-        constructors might clobber the virtual function table.  But
-        they don't if the derived class shares the exact vtable of the base
-        class.  */
-      CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
-    }
-  /* If we didn't need a new vtable, see if we should copy one from
-     the base.  */
-  else if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
-    {
-      tree binfo = CLASSTYPE_PRIMARY_BINFO (t);
-
-      /* If this class uses a different vtable than its primary base
-        then when we will need to initialize our vptr after the base
-        class constructor runs.  */
-      if (TYPE_BINFO_VTABLE (t) != BINFO_VTABLE (binfo))
-       CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
     }
 
   if (TYPE_CONTAINS_VPTR_P (t))
@@ -5253,6 +5175,9 @@ finish_struct_1 (t)
                        ? TARGET_VTABLE_USES_DESCRIPTORS : 1))
        if (TREE_CODE (DECL_VINDEX (BV_FN (fn))) != INTEGER_CST)
          DECL_VINDEX (BV_FN (fn)) = build_shared_int_cst (vindex);
+
+      /* Add this class to the list of dynamic classes.  */
+      dynamic_classes = tree_cons (NULL_TREE, t, dynamic_classes);
     }
 
   finish_struct_bits (t);
@@ -7068,8 +6993,10 @@ build_vtt (t)
                                 
   /* Now, build the VTT object itself.  */
   vtt = build_vtable (t, get_vtt_name (t), type);
-  pushdecl_top_level (vtt);
   initialize_array (vtt, inits);
+  /* Add the VTT to the vtables list.  */
+  TREE_CHAIN (vtt) = TREE_CHAIN (CLASSTYPE_VTABLES (t));
+  TREE_CHAIN (CLASSTYPE_VTABLES (t)) = vtt;
 
   dump_vtt (t, vtt);
 }
@@ -7404,7 +7331,7 @@ build_ctor_vtbl_group (binfo, t)
   TREE_TYPE (vtbl) = type;
 
   /* Initialize the construction vtable.  */
-  pushdecl_top_level (vtbl);
+  CLASSTYPE_VTABLES (t) = chainon (CLASSTYPE_VTABLES (t), vtbl);
   initialize_array (vtbl, inits);
   dump_vtable (t, binfo, vtbl);
 }
@@ -7621,6 +7548,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
   vid.last_init = &vid.inits;
   vid.primary_vtbl_p = (binfo == TYPE_BINFO (t));
   vid.ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
+  vid.generate_vcall_entries = true;
   /* The first vbase or vcall offset is at index -3 in the vtable.  */
   vid.index = ssize_int (-3 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
 
@@ -7704,14 +7632,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
          /* Pull the offset for `this', and the function to call, out of
             the list.  */
          delta = BV_DELTA (v);
-
-         if (BV_USE_VCALL_INDEX_P (v))
-           {
-             vcall_index = BV_VCALL_INDEX (v);
-             my_friendly_assert (vcall_index != NULL_TREE, 20000621);
-           }
-         else
-           vcall_index = NULL_TREE;
+         vcall_index = BV_VCALL_INDEX (v);
 
          my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
          my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
@@ -7900,31 +7821,37 @@ build_vcall_offset_vtbl_entries (binfo, vid)
      tree binfo;
      vtbl_init_data *vid;
 {
-  /* We only need these entries if this base is a virtual base.  */
-  if (!TREE_VIA_VIRTUAL (binfo))
-    return;
-
-  /* We need a vcall offset for each of the virtual functions in this
-     vtable.  For example:
+  /* We only need these entries if this base is a virtual base.  We
+     compute the indices -- but do not add to the vtable -- when
+     building the main vtable for a class.  */
+  if (TREE_VIA_VIRTUAL (binfo) || binfo == TYPE_BINFO (vid->derived))
+    {
+      /* We need a vcall offset for each of the virtual functions in this
+        vtable.  For example:
 
-       class A { virtual void f (); };
-       class B1 : virtual public A { virtual void f (); };
-       class B2 : virtual public A { virtual void f (); };
-       class C: public B1, public B2 { virtual void f (); };
+          class A { virtual void f (); };
+          class B1 : virtual public A { virtual void f (); };
+          class B2 : virtual public A { virtual void f (); };
+          class C: public B1, public B2 { virtual void f (); };
 
-     A C object has a primary base of B1, which has a primary base of A.  A
-     C also has a secondary base of B2, which no longer has a primary base
-     of A.  So the B2-in-C construction vtable needs a secondary vtable for
-     A, which will adjust the A* to a B2* to call f.  We have no way of
-     knowing what (or even whether) this offset will be when we define B2,
-     so we store this "vcall offset" in the A sub-vtable and look it up in
-     a "virtual thunk" for B2::f.
+        A C object has a primary base of B1, which has a primary base of A.  A
+        C also has a secondary base of B2, which no longer has a primary base
+        of A.  So the B2-in-C construction vtable needs a secondary vtable for
+        A, which will adjust the A* to a B2* to call f.  We have no way of
+        knowing what (or even whether) this offset will be when we define B2,
+        so we store this "vcall offset" in the A sub-vtable and look it up in
+        a "virtual thunk" for B2::f.
 
-     We need entries for all the functions in our primary vtable and
-     in our non-virtual bases' secondary vtables.  */
-  vid->vbase = binfo;
-  /* Now, walk through the non-virtual bases, adding vcall offsets.  */
-  add_vcall_offset_vtbl_entries_r (binfo, vid);
+        We need entries for all the functions in our primary vtable and
+        in our non-virtual bases' secondary vtables.  */
+      vid->vbase = binfo;
+      /* If we are just computing the vcall indices -- but do not need
+        the actual entries -- not that.  */
+      if (!TREE_VIA_VIRTUAL (binfo))
+       vid->generate_vcall_entries = false;
+      /* Now, walk through the non-virtual bases, adding vcall offsets.  */
+      add_vcall_offset_vtbl_entries_r (binfo, vid);
+    }
 }
 
 /* Build vcall offsets, starting with those for BINFO.  */
@@ -8025,8 +7952,6 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
     {
       tree orig_fn;
       tree fn;
-      tree base;
-      tree base_binfo;
       size_t i;
       tree vcall_offset;
 
@@ -8057,42 +7982,17 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
                 even though there are two virtual table entries.  */
              || (DECL_DESTRUCTOR_P (BV_FN (derived_entry))
                  && DECL_DESTRUCTOR_P (fn)))
-           {
-             if (!vid->ctor_vtbl_p)
-               BV_VCALL_INDEX (derived_virtuals) 
-                 = BV_VCALL_INDEX (derived_entry);
-             break;
-           }
+           break;
        }
       if (i != VARRAY_ACTIVE_SIZE (vid->fns))
        continue;
 
-      /* The FN comes from BASE.  So, we must calculate the adjustment from
-        vid->vbase to BASE.  We can just look for BASE in the complete
-        object because we are converting from a virtual base, so if there
-        were multiple copies, there would not be a unique final overrider
-        and vid->derived would be ill-formed.  */
-      base = DECL_CONTEXT (fn);
-      base_binfo = lookup_base (vid->derived, base, ba_any, NULL);
-
-      /* Compute the vcall offset.  */
-      /* As mentioned above, the vbase we're working on is a primary base of
-        vid->binfo.  But it might be a lost primary, so its BINFO_OFFSET
-         might be wrong, so we just use the BINFO_OFFSET from vid->binfo.  */
-      vcall_offset = BINFO_OFFSET (vid->binfo);
-      vcall_offset = size_diffop (BINFO_OFFSET (base_binfo),
-                                 vcall_offset);
-      vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
-                                  vcall_offset));
-      
-      *vid->last_init = build_tree_list (NULL_TREE, vcall_offset);
-      vid->last_init = &TREE_CHAIN (*vid->last_init);
-
-      /* Keep track of the vtable index where this vcall offset can be
-        found.  For a construction vtable, we already made this
-        annotation when we built the original vtable.  */
-      if (!vid->ctor_vtbl_p)
-       BV_VCALL_INDEX (derived_virtuals) = vid->index;
+      /* If we are building these vcall offsets as part of building
+        the vtable for the most derived class, remember the vcall
+        offset.  */
+      if (vid->binfo == TYPE_BINFO (vid->derived))
+       CLASSTYPE_VCALL_INDICES (vid->derived) 
+         = tree_cons (fn, vid->index, CLASSTYPE_VCALL_INDICES (vid->derived));
 
       /* The next vcall offset will be found at a more negative
         offset.  */
@@ -8101,6 +8001,35 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
 
       /* Keep track of this function.  */
       VARRAY_PUSH_TREE (vid->fns, derived_virtuals);
+
+      if (vid->generate_vcall_entries)
+       {
+         tree base;
+         tree base_binfo;
+
+         /* The FN comes from BASE.  So, we must calculate the
+            adjustment from vid->vbase to BASE.  We can just look for
+            BASE in the complete object because we are converting
+            from a virtual base, so if there were multiple copies,
+            there would not be a unique final overrider and
+            vid->derived would be ill-formed.  */
+         base = DECL_CONTEXT (fn);
+         base_binfo = lookup_base (vid->derived, base, ba_any, NULL);
+
+         /* Compute the vcall offset.  */
+         /* As mentioned above, the vbase we're working on is a
+            primary base of vid->binfo.  But it might be a lost
+            primary, so its BINFO_OFFSET might be wrong, so we just
+            use the BINFO_OFFSET from vid->binfo.  */
+         vcall_offset = BINFO_OFFSET (vid->binfo);
+         vcall_offset = size_diffop (BINFO_OFFSET (base_binfo),
+                                     vcall_offset);
+         vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
+                                      vcall_offset));
+
+         *vid->last_init = build_tree_list (NULL_TREE, vcall_offset);
+         vid->last_init = &TREE_CHAIN (*vid->last_init);
+       }
     }
 }
 
index cfe7cc9ef52140b32d5a86050a2a2972f86895b5..ad88103c92593a24d8116acd07e3727f6e096d13 100644 (file)
@@ -47,7 +47,6 @@ struct diagnostic_context;
       ICS_USER_FLAG (in _CONV)
       CLEANUP_P (in TRY_BLOCK)
       AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR)
-      BV_USE_VCALL_INDEX_P (in the BINFO_VIRTUALS TREE_LIST)
       PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
       PARMLIST_ELLIPSIS_P (in PARMLIST)
    1: IDENTIFIER_VIRTUAL_P.
@@ -133,9 +132,7 @@ struct diagnostic_context;
      of the base class.
 
      The BV_VCALL_INDEX of each node, if non-NULL, gives the vtable
-     index of the vcall offset for this entry.  If
-     BV_USE_VCALL_INDEX_P then the corresponding vtable entry should
-     use a virtual thunk, as opposed to an ordinary thunk.
+     index of the vcall offset for this entry.  
 
      The BV_FN is the declaration for the virtual function itself.
 
@@ -615,6 +612,8 @@ enum cp_tree_index
     CPTI_DSO_HANDLE,
     CPTI_DCAST,
 
+    CPTI_DYNAMIC_CLASSES,
+
     CPTI_MAX
 };
 
@@ -745,6 +744,10 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
    destructors.  */
 #define vtt_parm_type                   cp_global_trees[CPTI_VTT_PARM_TYPE]
 
+/* A TREE_LIST of all of the dynamic classes in the program.  */
+
+#define dynamic_classes                 cp_global_trees[CPTI_DYNAMIC_CLASSES]
+
 /* Global state.  */
 
 struct saved_scope GTY(())
@@ -1153,12 +1156,13 @@ struct lang_type_class GTY(())
 
   tree primary_base;
   tree vfields;
+  tree vcall_indices;
+  tree vtables;
   tree vbases;
   tree tags;
   tree as_base;
   tree pure_virtuals;
   tree friend_classes;
-  tree rtti;
   tree methods;
   tree decl_list;
   tree template_info;
@@ -1257,9 +1261,6 @@ struct lang_type GTY(())
    convenient, don't reprocess any methods that appear in its redefinition.  */
 #define TYPE_REDEFINED(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->redefined)
 
-/* The is the basetype that contains NODE's rtti.  */
-#define CLASSTYPE_RTTI(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->rtti)
-
 /* Nonzero means that this _CLASSTYPE node overloads operator().  */
 #define TYPE_OVERLOADS_CALL_EXPR(NODE) \
   (LANG_TYPE_CLASS_CHECK (NODE)->has_call_overloaded)
@@ -1431,13 +1432,6 @@ struct lang_type GTY(())
 /* Nonzero means that this aggr type has been `closed' by a semicolon.  */
 #define CLASSTYPE_GOT_SEMICOLON(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->got_semicolon)
 
-/* Nonzero means that the main virtual function table pointer needs to be
-   set because base constructors have placed the wrong value there.
-   If this is zero, it means that they placed the right value there,
-   and there is no need to change it.  */
-#define CLASSTYPE_NEEDS_VIRTUAL_REINIT(NODE) \
-  (LANG_TYPE_CLASS_CHECK (NODE)->needs_virtual_reinit)
-
 /* Nonzero means that this type has an X() constructor.  */
 #define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) \
   (LANG_TYPE_CLASS_CHECK (NODE)->h.has_default_ctor)
@@ -1629,6 +1623,19 @@ struct lang_type GTY(())
 /* Used by various search routines.  */
 #define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE)
 \f
+/* A TREE_LIST of the vcall indices associated with the class NODE.
+   The TREE_PURPOSE of each node is a FUNCTION_DECL for a virtual
+   function.  The TREE_VALUE is the index into the virtual table where
+   the vcall offset for that function is stored, when NODE is a
+   virtual base.  */
+#define CLASSTYPE_VCALL_INDICES(NODE) \
+  (LANG_TYPE_CLASS_CHECK (NODE)->vcall_indices)
+
+/* The various vtables for the class NODE.  The primary vtable will be
+   first, followed by the construction vtables and VTT, if any.  */
+#define CLASSTYPE_VTABLES(NODE) \
+  (LANG_TYPE_CLASS_CHECK (NODE)->vtables)
+
 /* Accessor macros for the vfield slots in structures.  */
 
 /* List of virtual table fields that this type contains (both the primary
@@ -1664,8 +1671,6 @@ struct lang_type GTY(())
 /* The function to call.  */
 #define BV_FN(NODE) (TREE_VALUE (NODE))
 
-/* Nonzero if we should use a virtual thunk for this entry.  */
-#define BV_USE_VCALL_INDEX_P(NODE) (TREE_LANG_FLAG_0 (NODE))
 \f
 /* Nonzero for TREE_LIST node means that this list of things
    is a list of parameters, as opposed to a list of expressions.  */
@@ -3546,7 +3551,6 @@ extern tree perform_implicit_conversion         PARAMS ((tree, tree));
 /* in class.c */
 extern tree build_base_path                    PARAMS ((enum tree_code, tree, tree, int));
 extern tree convert_to_base                     (tree, tree, bool);
-extern tree build_vbase_path                   PARAMS ((enum tree_code, tree, tree, tree, int));
 extern tree build_vtbl_ref                     PARAMS ((tree, tree));
 extern tree build_vfn_ref                      PARAMS ((tree, tree));
 extern tree get_vtable_decl                     PARAMS ((tree, int));
index 93b643f7bac2c5b8abb254cf29f176f2787fe7b7..339aba317f93d27ed5d016a784e2d984c8f9455b 100644 (file)
@@ -60,7 +60,7 @@ typedef struct priority_info_s {
 
 static void mark_vtable_entries PARAMS ((tree));
 static void grok_function_init PARAMS ((tree, tree));
-static int finish_vtable_vardecl PARAMS ((tree *, void *));
+static int maybe_emit_vtables (tree);
 static int is_namespace_ancestor PARAMS ((tree, tree));
 static void add_using_namespace PARAMS ((tree, tree, int));
 static tree ambiguous_decl PARAMS ((tree, tree, tree,int));
@@ -1658,12 +1658,7 @@ key_method (type)
        method = TREE_CHAIN (method))
     if (DECL_VINDEX (method) != NULL_TREE
        && ! DECL_DECLARED_INLINE_P (method)
-       && (! DECL_PURE_VIRTUAL_P (method)
-#if 0
-           /* This would be nice, but we didn't think of it in time.  */
-           || DECL_DESTRUCTOR_P (method)
-#endif
-           ))
+       && ! DECL_PURE_VIRTUAL_P (method))
       return method;
 
   return NULL_TREE;
@@ -1805,28 +1800,52 @@ output_vtable_inherit (vars)
   assemble_vtable_inherit (child_rtx, parent_rtx);
 }
 
+/* If necessary, write out the vtables for the dynamic class CTYPE.
+   Returns non-zero if any vtables were emitted.  */
+
 static int
-finish_vtable_vardecl (t, data)
-     tree *t;
-     void *data ATTRIBUTE_UNUSED;
+maybe_emit_vtables (tree ctype)
 {
-  tree vars = *t;
-  tree ctype = DECL_CONTEXT (vars);
+  tree vtbl;
+  tree primary_vtbl;
+
+  /* If the vtables for this class have already been emitted there is
+     nothing more to do.  */
+  primary_vtbl = CLASSTYPE_VTABLES (ctype);
+  if (TREE_ASM_WRITTEN (primary_vtbl))
+    return 0;
+  /* Ignore dummy vtables made by get_vtable_decl.  */
+  if (TREE_TYPE (primary_vtbl) == void_type_node)
+    return 0;
+
   import_export_class (ctype);
-  import_export_vtable (vars, ctype, 1);
+  import_export_vtable (primary_vtbl, ctype, 1);
 
-  if (! DECL_EXTERNAL (vars)
-      && DECL_NEEDED_P (vars)
-      && ! TREE_ASM_WRITTEN (vars))
+  /* See if any of the vtables are needed.  */
+  for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
+    if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl))
+      break;
+  
+  if (!vtbl)
+    {
+      /* If the references to this class' vtables are optimized away,
+        still emit the appropriate debugging information.  See
+        dfs_debug_mark.  */
+      if (DECL_COMDAT (primary_vtbl) 
+         && CLASSTYPE_DEBUG_REQUESTED (ctype))
+       note_debug_info_needed (ctype);
+      return 0;
+    }
+
+  /* The ABI requires that we emit all of the vtables if we emit any
+     of them.  */
+  for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
     {
-      if (TREE_TYPE (vars) == void_type_node)
-        /* It is a dummy vtable made by get_vtable_decl. Ignore it.  */
-        return 0;
-      
       /* Write it out.  */
-      mark_vtable_entries (vars);
-      if (TREE_TYPE (DECL_INITIAL (vars)) == 0)
-       store_init_value (vars, DECL_INITIAL (vars));
+      import_export_vtable (vtbl, ctype, 1);
+      mark_vtable_entries (vtbl);
+      if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
+       store_init_value (vtbl, DECL_INITIAL (vtbl));
 
       if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
        {
@@ -1851,37 +1870,29 @@ finish_vtable_vardecl (t, data)
              `S' get written (which would solve the problem) but that would
              require more intrusive changes to the g++ front end.  */
 
-         DECL_IGNORED_P (vars) = 1;
+         DECL_IGNORED_P (vtbl) = 1;
        }
 
       /* Always make vtables weak.  */
       if (flag_weak)
-       comdat_linkage (vars);
+       comdat_linkage (vtbl);
 
-      rest_of_decl_compilation (vars, NULL, 1, 1);
+      rest_of_decl_compilation (vtbl, NULL, 1, 1);
 
       if (flag_vtable_gc)
-       output_vtable_inherit (vars);
+       output_vtable_inherit (vtbl);
 
       /* Because we're only doing syntax-checking, we'll never end up
         actually marking the variable as written.  */
       if (flag_syntax_only)
-       TREE_ASM_WRITTEN (vars) = 1;
-
-      /* Since we're writing out the vtable here, also write the debug 
-        info.  */
-      note_debug_info_needed (ctype);
-
-      return 1;
+       TREE_ASM_WRITTEN (vtbl) = 1;
     }
 
-  /* If the references to this class' vtables were optimized away, still
-     emit the appropriate debugging information.  See dfs_debug_mark.  */
-  if (DECL_COMDAT (vars)
-      && CLASSTYPE_DEBUG_REQUESTED (ctype))
-    note_debug_info_needed (ctype);
+  /* Since we're writing out the vtable here, also write the debug
+     info.  */
+  note_debug_info_needed (ctype);
 
-  return 0;
+  return 1;
 }
 
 /* Determines the proper settings of TREE_PUBLIC and DECL_EXTERNAL for an
@@ -2755,6 +2766,8 @@ finish_file ()
   
   do 
     {
+      tree t;
+
       reconsider = 0;
 
       /* If there are templates that we've put off instantiating, do
@@ -2764,10 +2777,9 @@ finish_file ()
       /* Write out virtual tables as required.  Note that writing out
         the virtual table for a template class may cause the
         instantiation of members of that class.  */
-      if (walk_vtables (vtable_decl_p,
-                       finish_vtable_vardecl,
-                       /*data=*/0))
-       reconsider = 1;
+      for (t = dynamic_classes; t; t = TREE_CHAIN (t))
+       if (maybe_emit_vtables (TREE_VALUE (t)))
+         reconsider = 1;
       
       /* Write out needed type info variables. Writing out one variable
          might cause others to be needed.  */
index 3b06a0a0cceda4ffde2295e4cf4a635c449b11ac..c14287b02026e469300ebe4ba0a39d270d4e722b 100644 (file)
@@ -1955,9 +1955,8 @@ look_for_overrides (type, fndecl)
   return found;
 }
 
-/* Look in TYPE for virtual functions with the same signature as FNDECL.
-   This differs from get_matching_virtual in that it will only return
-   a function from TYPE.  */
+/* Look in TYPE for virtual functions with the same signature as
+   FNDECL.  */
 
 tree
 look_for_overrides_here (type, fndecl)
index be1e6026bdecc7d2189c3db75e340e05db7ba474..a2b9f53b5caf5b82d6122147a3ec62bfbe632765 100644 (file)
@@ -1,3 +1,9 @@
+2002-11-03  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/abi/thunk1.C: New test.
+       * g++.dg/abi/thunk2.C: Likewise.
+       * g++.dg/abi/vtt1.C: Likewise.
+
 2002-11-02  Diego Novillo  <dnovillo@redhat.com>
 
        PR optimization/8423
diff --git a/gcc/testsuite/g++.dg/abi/thunk1.C b/gcc/testsuite/g++.dg/abi/thunk1.C
new file mode 100644 (file)
index 0000000..c9ad5b4
--- /dev/null
@@ -0,0 +1,22 @@
+// { dg-do compile { target i?86-*-* } }
+
+struct A {
+  virtual void f ();
+};
+
+struct B : public virtual A {
+  virtual void f ();
+};
+
+struct C {
+  virtual void g ();
+};
+
+struct D : public C, public B {
+  virtual void f ();
+};
+
+void D::f () {}
+
+// { dg-final { scan-assembler _ZThn4_N1D1fEv } }
+// { dg-final { scan-assembler _ZTv0_n12_N1D1fEv } }
diff --git a/gcc/testsuite/g++.dg/abi/thunk2.C b/gcc/testsuite/g++.dg/abi/thunk2.C
new file mode 100644 (file)
index 0000000..b1c9788
--- /dev/null
@@ -0,0 +1,26 @@
+// { dg-do compile { target i?86-*-* } }
+// { dg-options -w }
+
+struct A {
+  virtual void f2 ();
+  virtual void f3 ();
+};
+
+struct B : virtual public A {
+  virtual void f3 ();
+};
+
+struct C : public A, public B {
+  virtual void f4 ();
+};
+
+struct D : virtual public B, virtual public C, virtual public A 
+{
+  virtual void f5 ();
+  virtual void f6 ();
+  virtual void f3 ();
+};
+
+void D::f3 () {}
+
+// { dg-final { scan-assembler _ZTvn4_n20_N1D2f3Ev } }
diff --git a/gcc/testsuite/g++.dg/abi/vtt1.C b/gcc/testsuite/g++.dg/abi/vtt1.C
new file mode 100644 (file)
index 0000000..8235c46
--- /dev/null
@@ -0,0 +1,11 @@
+// { dg-do compile }
+
+struct A {
+};
+
+struct B : virtual public A {
+};
+
+B b;
+
+// { dg-final { scan-assembler _ZTT1B } }
This page took 0.121112 seconds and 5 git commands to generate.