cp-tree.h (THUNK_GENERATE_WITH_VTABLE_P): Lose.
authorJason Merrill <jason@redhat.com>
Wed, 6 Jun 2001 21:52:52 +0000 (17:52 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 6 Jun 2001 21:52:52 +0000 (17:52 -0400)
        * cp-tree.h (THUNK_GENERATE_WITH_VTABLE_P): Lose.
        (struct lang_decl_flags): Lose generate_with_vtable_p.
        (BV_GENERATE_THUNK_WITH_VTABLE_P): Lose.
        * class.c (copy_virtuals): Adjust.
        * decl2.c (mark_vtable_entries): Adjust.
        * method.c (make_thunk, build_vtable_entry): Adjust.
        * class.c (update_vtable_entry_for_fn): Only look as far as the
        first defining class.
        (build_vtbl_initializer): Put nothing in the slot for a function only
        defined in a lost primary virtual base.
        (add_vcall_offset_vtbl_entries_1): Use the same code for
        the lost primary case and the normal case.
        (dfs_unshared_virtual_bases): Don't lose a non-virtual primary base.
        (get_vfield_offset, get_derived_offset): Lose.
        (dfs_find_final_overrider): Use look_for_overrides_here.
        (get_matching_virtual): New fn.
        * semantics.c (emit_associated_thunks): Check BV_USE_VCALL_INDEX_P,
        not BV_VCALL_INDEX.
        * search.c (look_for_overrides_here): Split out from...
        (look_for_overrides_r): Here.

        * class.c (find_final_overrider): Return error_mark_node on error.

From-SVN: r42949

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/method.c
gcc/cp/search.c
gcc/cp/semantics.c
gcc/testsuite/g++.dg/mangle1.C

index 4e458c5..8ba7f9f 100644 (file)
@@ -1,3 +1,30 @@
+2001-06-06  Jason Merrill  <jason_merrill@redhat.com>
+
+       * cp-tree.h (THUNK_GENERATE_WITH_VTABLE_P): Lose.
+       (struct lang_decl_flags): Lose generate_with_vtable_p.
+       (BV_GENERATE_THUNK_WITH_VTABLE_P): Lose.
+       * class.c (copy_virtuals): Adjust.
+       * decl2.c (mark_vtable_entries): Adjust.
+       * method.c (make_thunk, build_vtable_entry): Adjust.
+       * class.c (update_vtable_entry_for_fn): Only look as far as the
+       first defining class.
+       (build_vtbl_initializer): Put nothing in the slot for a function only 
+       defined in a lost primary virtual base.
+       (add_vcall_offset_vtbl_entries_1): Use the same code for 
+       the lost primary case and the normal case.
+       (dfs_unshared_virtual_bases): Don't lose a non-virtual primary base.
+       (get_vfield_offset, get_derived_offset): Lose.
+       (dfs_find_final_overrider): Use look_for_overrides_here.
+       (get_matching_virtual): New fn.
+       * semantics.c (emit_associated_thunks): Check BV_USE_VCALL_INDEX_P,
+       not BV_VCALL_INDEX.
+       * search.c (look_for_overrides_here): Split out from...
+       (look_for_overrides_r): Here.
+
+       * class.c (find_final_overrider): Return error_mark_node on error.
+
+       * decl2.c (key_method): #if 0 accidental change.
+
 2001-06-06  John David Anglin  <dave@hiauly1.hia.nrc.ca>
 
        * call.c (convert_default_arg): Use INTEGRAL_TYPE_P.
index afe2da4..cdd92b5 100644 (file)
@@ -74,7 +74,7 @@ typedef struct vtbl_init_data_s
   /* 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.  */
+  /* The last (i.e., most negative) entry in INITS.  */
   tree* last_init;
   /* The binfo for the virtual base for which we're building
      vcall offset initializers.  */
@@ -107,9 +107,8 @@ varray_type local_classes;
 static tree get_vfield_name PARAMS ((tree));
 static void finish_struct_anon PARAMS ((tree));
 static tree build_vbase_pointer PARAMS ((tree, tree));
-static tree build_vtable_entry PARAMS ((tree, tree, tree, int));
+static tree build_vtable_entry PARAMS ((tree, tree, tree));
 static tree get_vtable_name PARAMS ((tree));
-static tree get_derived_offset PARAMS ((tree, tree));
 static tree get_basefndecls PARAMS ((tree, tree));
 static int build_primary_vtable PARAMS ((tree, tree));
 static int build_secondary_vtable PARAMS ((tree, tree));
@@ -684,37 +683,6 @@ get_vtt_name (type)
   return mangle_vtt_for_type (type);
 }
 
-/* Return the offset to the main vtable for a given base BINFO.  */
-
-tree
-get_vfield_offset (binfo)
-     tree binfo;
-{
-  return
-    size_binop (PLUS_EXPR, byte_position (TYPE_VFIELD (BINFO_TYPE (binfo))),
-               BINFO_OFFSET (binfo));
-}
-
-/* Get the offset to the start of the original binfo that we derived
-   this binfo from.  If we find TYPE first, return the offset only
-   that far.  The shortened search is useful because the this pointer
-   on method calling is expected to point to a DECL_CONTEXT (fndecl)
-   object, and not a baseclass of it.   */
-
-static tree
-get_derived_offset (binfo, type)
-     tree binfo, type;
-{
-  tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
-  tree offset2;
-
-  while (!same_type_p (BINFO_TYPE (binfo), type))
-    binfo = get_primary_binfo (binfo);
-
-  offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
-  return size_binop (MINUS_EXPR, offset1, offset2);
-}
-
 /* Create a VAR_DECL for a primary or secondary vtable for CLASS_TYPE.
    (For a secondary vtable for B-in-D, CLASS_TYPE should be D, not B.)
    Use NAME for the name of the vtable, and VTABLE_TYPE for its type.  */
@@ -796,7 +764,6 @@ copy_virtuals (binfo)
     {
       BV_VCALL_INDEX (t) = NULL_TREE;
       BV_USE_VCALL_INDEX_P (t) = 0;
-      BV_GENERATE_THUNK_WITH_VTABLE_P (t) = 0;
     }
 
   return copies;
@@ -1024,9 +991,11 @@ make_new_vtable (t, binfo)
 {
   if (binfo == TYPE_BINFO (t))
     /* In this case, it is *type*'s vtable we are modifying.  We start
-       with the approximation that it's vtable is that of the
+       with the approximation that its vtable is that of the
        immediate base class.  */
-    return build_primary_vtable (TYPE_BINFO (DECL_CONTEXT (TYPE_VFIELD (t))), 
+    /* ??? This actually passes TYPE_BINFO (t), not the primary base binfo,
+       since we've updated DECL_CONTEXT (TYPE_VFIELD (t)) by now.  */
+    return build_primary_vtable (TYPE_BINFO (DECL_CONTEXT (TYPE_VFIELD (t))),
                                 t);
   else
     /* This is our very own copy of `basetype' to play with.  Later,
@@ -1077,7 +1046,12 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
       BV_FN (v) = fndecl;
 
       /* Now assign virtual dispatch information, if unset.  We can
-        dispatch this, through any overridden base function.  */
+        dispatch this through any overridden base function.
+
+        FIXME this can choose a secondary vtable if the primary is not
+        also lexically first, leading to useless conversions.
+        In the V3 ABI, there's no reason for DECL_VIRTUAL_CONTEXT to
+        ever be different from DECL_CONTEXT.  */
       if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
        {
          DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
@@ -1808,7 +1782,7 @@ mark_primary_virtual_base (binfo, base_binfo, type)
   return base_binfo;
 }
 
-/* If BINFO is an unmarked virtual binfo for a class with a primary
+/* If BINFO is an unmarked virtual binfo for a class with a primary virtual
    base, then BINFO has no primary base in this graph.  Called from
    mark_primary_bases. */
 
@@ -1817,7 +1791,8 @@ static tree dfs_unshared_virtual_bases (binfo, data)
      void *data ATTRIBUTE_UNUSED;
 {
   if (TREE_VIA_VIRTUAL (binfo) && !BINFO_MARKED (binfo)
-      && CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
+      && CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo))
+      && TREE_VIA_VIRTUAL (CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (binfo))))
     BINFO_LOST_PRIMARY_P (binfo) = 1;
 
   CLEAR_BINFO_MARKED (binfo);
@@ -2542,13 +2517,8 @@ dfs_find_final_overrider (binfo, data)
           path; 
           path = TREE_CHAIN (path))
        {
-         for (method = TYPE_METHODS (BINFO_TYPE (TREE_VALUE (path)));
-              method;
-              method = TREE_CHAIN (method))
-           if (DECL_VIRTUAL_P (method) 
-               && same_signature_p (method, ffod->fn))
-             break;
-
+         method = look_for_overrides_here (BINFO_TYPE (TREE_VALUE (path)),
+                                           ffod->fn);
          if (method)
            break;
        }
@@ -2676,7 +2646,7 @@ find_final_overrider (t, binfo, fn)
        struct T : virtual public R { virtual void f (); };
        struct U : public S, public T { };
 
-     is not -- there's no way  to decide whether to put `S::f' or
+     is not -- there's no way to decide whether to put `S::f' or
      `T::f' in the vtable for `R'.  
      
      The solution is to look at all paths to BINFO.  If we find
@@ -2695,14 +2665,36 @@ find_final_overrider (t, binfo, fn)
 
   /* If there was no winner, issue an error message.  */
   if (!ffod.overriding_fn)
-    cp_error ("no unique final overrider for `%D' in `%T'", fn, t);
+    {
+      cp_error ("no unique final overrider for `%D' in `%T'", fn, t);
+      return error_mark_node;
+    }
 
   return build_tree_list (ffod.overriding_fn, ffod.overriding_base);
 }
 
-/* Update a entry in the vtable for BINFO, which is in the hierarchy
-   dominated by T.  FN has been overridden in BINFO; VIRTUALS points
-   to the corresponding position in the BINFO_VIRTUALS list.  */
+#if 0
+/* 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.  */
+
+static tree get_matching_virtual PARAMS ((tree, tree));
+static tree
+get_matching_virtual (t, fn)
+     tree t, fn;
+{
+  tree f;
+
+  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;
+}
+#endif
+
+/* Update an entry in the vtable for BINFO, which is in the hierarchy
+   dominated by T.  FN has been overriden in BINFO; VIRTUALS points to the
+   corresponding position in the BINFO_VIRTUALS list.  */
 
 static void
 update_vtable_entry_for_fn (t, binfo, fn, virtuals)
@@ -2715,93 +2707,92 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
   tree overrider;
   tree delta;
   tree virtual_base;
-  int generate_thunk_with_vtable_p;
+  tree first_defn;
 
-  /* Find the function which originally caused this vtable
-     entry to be present.  */
-  b = binfo;
-  while (1)
+  /* Find the nearest primary base (possibly binfo itself) which defines
+     this function; this is the class the caller will convert to when
+     calling FN through BINFO.  */
+  for (b = binfo; ; b = get_primary_binfo (b))
     {
-      tree primary_base;
-      tree f;
-
-      primary_base = get_primary_binfo (b);
-      if (!primary_base)
+      if (look_for_overrides_here (BINFO_TYPE (b), fn))
        break;
-
-      for (f = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (primary_base)));
-          f;
-          f = TREE_CHAIN (f))
-       if (same_signature_p (BV_FN (f), fn))
-         break;
-
-      if (!f)
-       break;
-
-      fn = BV_FN (f);
-      b = primary_base;
     }
+  first_defn = b;
 
   /* Find the final overrider.  */
   overrider = find_final_overrider (t, b, fn);
   if (overrider == error_mark_node)
     return;
 
-  /* Compute the constant adjustment to the `this' pointer.  The
-     `this' pointer, when this function is called, will point at the
-     class whose vtable this is.  */
-  delta = size_binop (PLUS_EXPR,
-                     get_derived_offset (binfo,
-                                         DECL_VIRTUAL_CONTEXT (fn)),
-                     BINFO_OFFSET (binfo));
-
   /* Assume that we will produce a thunk that convert all the way to
      the final overrider, and not to an intermediate virtual base.  */
   virtual_base = NULL_TREE;
 
-  /* Assume that we will always generate thunks with the vtables that
-     reference them.  */
-  generate_thunk_with_vtable_p = 1;
-
   /* Under the new ABI, we will convert to an intermediate virtual
      base first, and then use the vcall offset located there to finish
      the conversion.  */
   while (b)
     {
-      /* If we find BINFO, then the final overrider is in a class
-        derived from BINFO, so the thunks can be generated with
-        the final overrider.  */
-      if (!virtual_base
-         && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo)))
-       generate_thunk_with_vtable_p = 0;
-
-         /* If we find the final overrider, then we can stop
-            walking.  */
+      /* If we find the final overrider, then we can stop
+        walking.  */
       if (same_type_p (BINFO_TYPE (b), 
                       BINFO_TYPE (TREE_VALUE (overrider))))
        break;
 
-         /* If we find a virtual base, and we haven't yet found the
-            overrider, then there is a virtual base between the
-            declaring base and the final overrider.  */
+      /* If we find a virtual base, and we haven't yet found the
+        overrider, then there is a virtual base between the
+        declaring base (first_defn) and the final overrider.  */
       if (!virtual_base && TREE_VIA_VIRTUAL (b))
-       {
-         generate_thunk_with_vtable_p = 1;
-         virtual_base = b;
-       }
+       virtual_base = b;
 
       b = BINFO_INHERITANCE_CHAIN (b);
     }
 
+  /* 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 to the nearest virtual
        base.  */
-    delta = size_diffop (BINFO_OFFSET (virtual_base), delta);
+    delta = size_diffop (BINFO_OFFSET (virtual_base),
+                        BINFO_OFFSET (binfo));
   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)), delta);
+    {
+      /* 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 0
+      /* Disable this optimization pending an ABI change, or until
+        we can force emission of the non-virtual thunk even if we don't
+        use it.  */
+      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;
+               }
+           }
+       }
+#endif
+    }
 
   modify_vtable_entry (t, 
                       binfo, 
@@ -2811,8 +2802,6 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
 
   if (virtual_base)
     BV_USE_VCALL_INDEX_P (*virtuals) = 1;
-  if (generate_thunk_with_vtable_p)
-    BV_GENERATE_THUNK_WITH_VTABLE_P (*virtuals) = 1;
 }
 
 /* Called from modify_all_vtables via dfs_walk.  */
@@ -2823,9 +2812,9 @@ dfs_modify_vtables (binfo, data)
      void *data;
 {
   if (/* There's no need to modify the vtable for a non-virtual
-         primary base; we're not going to use that vtable anyhow
-         (virtual primary bases can become non-primary in a
-         class derivation of this one.) */
+         primary base; we're not going to use that vtable anyhow.
+        We do still need to do this for virtual primary bases, as they
+        could become non-primary in a construction vtable.  */
       (!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo))
       /* Similarly, a base without a vtable needs no modification.  */
       && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
@@ -5310,9 +5299,7 @@ finish_struct_1 (t)
   layout_class_type (t, &empty, &vfuns,
                     &new_virtuals, &overridden_virtuals);
 
-  /* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we
-     might need to know it for setting up the offsets in the vtable
-     (or in thunks) below.  */
+  /* Make sure that we get our own copy of the vfield FIELD_DECL.  */
   vfield = TYPE_VFIELD (t);
   if (vfield != NULL_TREE
       && DECL_FIELD_CONTEXT (vfield) != t)
@@ -7667,7 +7654,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
      tree rtti_binfo;
      int *non_fn_entries_p;
 {
-  tree v;
+  tree v, b;
   tree vfun_inits;
   tree vbase;
   vtbl_init_data vid;
@@ -7714,7 +7701,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
       tree fn;
       tree pfn;
       tree init;
-      int generate_with_vtable_p = BV_GENERATE_THUNK_WITH_VTABLE_P (v);
       
       /* Pull the offset for `this', and the function to call, out of
         the list.  */
@@ -7725,15 +7711,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
          vcall_index = BV_VCALL_INDEX (v);
          my_friendly_assert (vcall_index != NULL_TREE, 20000621);
        }
-      else if (vid.ctor_vtbl_p && BV_VCALL_INDEX (v))
-        {
-          /* In the original, we did not need to use the vcall index, even
-             though there was one, but in a ctor vtable things might be
-             different (a primary virtual base might have moved). Be
-             conservative and use a vcall adjusting thunk.  */
-         vcall_index = BV_VCALL_INDEX (v);
-          generate_with_vtable_p = 1;
-        }
       else
         vcall_index = NULL_TREE;
 
@@ -7751,9 +7728,35 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
       pfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
       /* The address of a function can't change.  */
       TREE_CONSTANT (pfn) = 1;
+
       /* Enter it in the vtable.  */
-      init = build_vtable_entry (delta, vcall_index, pfn,
-                                generate_with_vtable_p);
+      init = build_vtable_entry (delta, vcall_index, pfn);
+
+      /* If the only definition of this function signature along our
+        primary base chain is from a lost primary, this vtable slot will
+        never be used, so just zero it out.  This is important to avoid
+        requiring extra thunks which cannot be generated with the function.
+
+        We could also handle this in update_vtable_entry_for_fn; doing it
+        here means we zero out unused slots in ctor vtables as well,
+        rather than filling them with erroneous values (though harmless,
+        apart from relocation costs).  */
+      if (fn != abort_fndecl)
+       for (b = binfo; ; b = get_primary_binfo (b))
+         {
+           /* We found a defn before a lost primary; go ahead as normal.  */
+           if (look_for_overrides_here (BINFO_TYPE (b), fn))
+             break;
+
+           /* The nearest definition is from a lost primary; clear the
+              slot.  */
+           if (BINFO_LOST_PRIMARY_P (b))
+             {
+               init = size_zero_node;
+               break;
+             }
+         }
+
       /* And add it to the chain of initializers.  */
       vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
     }
@@ -7769,7 +7772,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
   return chainon (vid.inits, vfun_inits);
 }
 
-/* Sets vid->inits to be the initializers for the vbase and vcall
+/* Adds to vid->inits the initializers for the vbase and vcall
    offsets in BINFO, which is in the hierarchy dominated by T.  */
 
 static void
@@ -7877,8 +7880,8 @@ build_vbase_offset_vtbl_entries (binfo, vid)
 }
 
 /* Adds the initializers for the vcall offset entries in the vtable
-   for BINFO (which is part of the class hierarchy dominated by T) to
-   VID->INITS.  */
+   for BINFO (which is part of the class hierarchy dominated by VID->DERIVED)
+   to VID->INITS.  */
 
 static void
 build_vcall_offset_vtbl_entries (binfo, vid)
@@ -7898,22 +7901,20 @@ build_vcall_offset_vtbl_entries (binfo, vid)
      vtable.  For example:
 
        class A { virtual void f (); };
-       class B : virtual public A { };
-       class C: virtual public A, public B {};
-      
-     Now imagine:
-
-       B* b = new C;
-       b->f();
-
-     The location of `A' is not at a fixed offset relative to `B'; the
-     offset depends on the complete object derived from `B'.  So, 
-     `B' vtable contains an entry for `f' that indicates by what
-     amount the `this' pointer for `B' needs to be adjusted to arrive
-     at `A'.  
+       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.
 
      We need entries for all the functions in our primary vtable and
-     in our non-virtual bases vtables.  */
+     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);
@@ -7930,7 +7931,9 @@ add_vcall_offset_vtbl_entries_r (binfo, vid)
   tree primary_binfo;
 
   /* Don't walk into virtual bases -- except, of course, for the
-     virtual base for which we are building vcall offsets.  */
+     virtual base for which we are building vcall offsets.  Any
+     primary virtual base will have already had its offsets generated
+     through the recursion in build_vcall_and_vbase_vtbl_entries.  */
   if (TREE_VIA_VIRTUAL (binfo) && vid->vbase != binfo)
     return;
   
@@ -7964,43 +7967,30 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
   tree base_virtuals;
   tree orig_virtuals;
   tree binfo_inits;
-  int lost_primary = 0;
-  /* If BINFO is a primary base, this is the least derived class of
-     BINFO that is not a primary base.  */
+  /* If BINFO is a primary base, the most derived class which has BINFO as
+     a primary base; otherwise, just BINFO.  */
   tree non_primary_binfo;
 
   binfo_inits = NULL_TREE;
 
-  /* We might be a primary base class.  Go up the inheritance
-     hierarchy until we find the class of which we are a primary base:
+  /* We might be a primary base class.  Go up the inheritance hierarchy
+     until we find the most derived class of which we are a primary base:
      it is the BINFO_VIRTUALS there that we need to consider.  */
   non_primary_binfo = binfo;
   while (BINFO_INHERITANCE_CHAIN (non_primary_binfo))
     {
       tree b;
 
-      /* If we have reached a virtual base, then it must be the
-        virtual base for which we are building vcall offsets.  In
-        turn, the virtual base must be a (possibly indirect) primary
-        base of the class that we are initializing, or we wouldn't
-        care about its vtable offsets.  */
+      /* If we have reached a virtual base, then it must be vid->vbase,
+        because we ignore other virtual bases in
+        add_vcall_offset_vtbl_entries_r.  In turn, it must be a primary
+        base (possibly multi-level) of vid->binfo, or we wouldn't
+        have called build_vcall_and_vbase_vtbl_entries for it.  But it
+        might be a lost primary, so just skip down to vid->binfo.  */
       if (TREE_VIA_VIRTUAL (non_primary_binfo))
        {
-         if (vid->ctor_vtbl_p)
-           {
-             tree probe;
-         
-             for (probe = vid->binfo;
-                  probe != non_primary_binfo;
-                  probe = get_primary_binfo (probe))
-               {
-                  if (BINFO_LOST_PRIMARY_P (probe))
-                    {
-                      lost_primary = 1;
-                      break;
-                    }
-               }
-            }
+         if (non_primary_binfo != vid->vbase)
+           abort ();
          non_primary_binfo = vid->binfo;
          break;
        }
@@ -8034,13 +8024,12 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
       tree vcall_offset;
 
       /* Find the declaration that originally caused this function to
-        be present.  */
+        be present in BINFO_TYPE (binfo).  */
       orig_fn = BV_FN (orig_virtuals);
 
-      /* We do not need an entry if this function is declared in a
-        virtual base (or one of its virtual bases), and not
-        overridden in the section of the hierarchy dominated by the
-        virtual base for which we are building vcall offsets.  */
+      /* When processing BINFO, we only want to generate vcall slots for
+        function slots introduced in BINFO.  So don't try to generate
+        one if the function isn't even defined in BINFO.  */
       if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo)))
        continue;
 
@@ -8071,16 +8060,19 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
       if (i != VARRAY_ACTIVE_SIZE (vid->fns))
        continue;
 
-      /* The FN comes from BASE.  So, we must calculate the adjustment
-        from the virtual base that derived from BINFO to BASE.  */
+      /* 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 = get_binfo (base, vid->derived, /*protect=*/0);
 
       /* Compute the vcall offset.  */
-      vcall_offset = BINFO_OFFSET (vid->vbase);
-      if (lost_primary)
-        vcall_offset = size_binop (PLUS_EXPR, vcall_offset,
-                                   BINFO_OFFSET (vid->binfo));
+      /* 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,
@@ -8091,7 +8083,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
 
       /* Keep track of the vtable index where this vcall offset can be
         found.  For a construction vtable, we already made this
-        annotation when we build the original vtable.  */
+        annotation when we built the original vtable.  */
       if (!vid->ctor_vtbl_p)
        BV_VCALL_INDEX (derived_virtuals) = vid->index;
 
@@ -8172,11 +8164,10 @@ build_rtti_vtbl_entries (binfo, vid)
    ABI.)  */
 
 static tree
-build_vtable_entry (delta, vcall_index, entry, generate_with_vtable_p)
+build_vtable_entry (delta, vcall_index, entry)
      tree delta;
      tree vcall_index;
      tree entry;
-     int generate_with_vtable_p;
 {
   if (flag_vtable_thunks)
     {
@@ -8186,8 +8177,7 @@ build_vtable_entry (delta, vcall_index, entry, generate_with_vtable_p)
       if ((!integer_zerop (delta) || vcall_index != NULL_TREE)
          && fn != abort_fndecl)
        {
-         entry = make_thunk (entry, delta, vcall_index,
-                             generate_with_vtable_p);
+         entry = make_thunk (entry, delta, vcall_index);
          entry = build1 (ADDR_EXPR, vtable_entry_type, entry);
          TREE_READONLY (entry) = 1;
          TREE_CONSTANT (entry) = 1;
index e820303..b73626a 100644 (file)
@@ -55,7 +55,6 @@ Boston, MA 02111-1307, USA.  */
       BASELINK_P (in TREE_LIST)
       ICS_ELLIPSIS_FLAG (in _CONV)
       BINFO_ACCESS (in BINFO)
-      BV_GENERATE_THUNK_WITH_VTABLE_P (in TREE_LIST)
    2: IDENTIFIER_OPNAME_P.
       TYPE_POLYMORHPIC_P (in _TYPE)
       ICS_THIS_FLAG (in _CONV)
@@ -133,10 +132,6 @@ Boston, MA 02111-1307, USA.  */
 
      The BV_FN is the declaration for the virtual function itself.
 
-     The BV_OVERRIDING_BASE is the binfo for the final overrider for
-     this function.  (That binfo's BINFO_TYPE will always be the same
-     as the DECL_CLASS_CONTEXT for the function.)
-
    BINFO_VTABLE
      Sometimes this is a VAR_DECL.  Under the new ABI, it is instead
      an expression with POINTER_TYPE pointing that gives the value
@@ -1736,14 +1731,6 @@ struct lang_type
 /* Nonzero if we should use a virtual thunk for this entry.  */
 #define BV_USE_VCALL_INDEX_P(NODE) \
    (TREE_LANG_FLAG_0 (NODE))
-
-/* Nonzero if we should generate this thunk when the vtable that
-   references it is emitted, rather than with the final overrider.  */
-#define BV_GENERATE_THUNK_WITH_VTABLE_P(NODE) \
-  (TREE_LANG_FLAG_1 (NODE))
-
-/* The most derived class.  */
-
 \f
 /* Nonzero for TREE_LIST node means that this list of things
    is a list of parameters, as opposed to a list of expressions.  */
@@ -1806,8 +1793,7 @@ struct lang_decl_flags
   unsigned global_dtor_p : 1;
   unsigned assignment_operator_p : 1;
   unsigned anticipated_p : 1;
-  unsigned generate_with_vtable_p : 1;
-  /* Two unused bits.  */
+  /* Three unused bits.  */
 
   union {
     /* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
@@ -3036,11 +3022,6 @@ enum ptrmemfunc_vbit_where_t
 #define THUNK_VCALL_OFFSET(DECL) \
   (DECL_LANG_SPECIFIC (DECL)->decl_flags.u2.vcall_offset)
 
-/* Nonzero if this thunk should be generated with the vtable that
-   references it.  */
-#define THUNK_GENERATE_WITH_VTABLE_P(DECL) \
-  (DECL_LANG_SPECIFIC (DECL)->decl_flags.generate_with_vtable_p)
-
 /* These macros provide convenient access to the various _STMT nodes
    created when parsing template declarations.  */
 #define TRY_STMTS(NODE)         TREE_OPERAND (TRY_BLOCK_CHECK (NODE), 0)
@@ -3716,7 +3697,6 @@ extern tree get_vtable_decl                     PARAMS ((tree, int));
 extern void add_method                         PARAMS ((tree, tree, int));
 extern int currently_open_class                        PARAMS ((tree));
 extern tree currently_open_derived_class       PARAMS ((tree));
-extern tree get_vfield_offset                  PARAMS ((tree));
 extern void duplicate_tag_error                        PARAMS ((tree));
 extern tree finish_struct                      PARAMS ((tree, tree));
 extern void finish_struct_1                    PARAMS ((tree));
@@ -4083,7 +4063,7 @@ extern void init_method                           PARAMS ((void));
 extern void set_mangled_name_for_decl           PARAMS ((tree));
 extern tree build_opfncall                     PARAMS ((enum tree_code, int, tree, tree, tree));
 extern tree hack_identifier                    PARAMS ((tree, tree));
-extern tree make_thunk                         PARAMS ((tree, tree, tree, int));
+extern tree make_thunk                         PARAMS ((tree, tree, tree));
 extern void use_thunk                          PARAMS ((tree, int));
 extern void synthesize_method                  PARAMS ((tree));
 extern tree implicitly_declare_fn               PARAMS ((special_function_kind, tree, int));
@@ -4202,6 +4182,7 @@ extern tree context_for_name_lookup               PARAMS ((tree));
 extern tree lookup_conversions                 PARAMS ((tree));
 extern tree binfo_for_vtable                   PARAMS ((tree));
 extern tree binfo_from_vbase                   PARAMS ((tree));
+extern tree look_for_overrides_here            PARAMS ((tree, tree));
 extern tree dfs_walk                            PARAMS ((tree,
                                                       tree (*) (tree, void *),
                                                       tree (*) (tree, void *),
index c1aa328..56c4dbc 100644 (file)
@@ -2265,7 +2265,7 @@ mark_vtable_entries (decl)
         we know all the thunks we'll need when we emit a virtual
         function, so we emit the thunks there instead.  */
       if (DECL_THUNK_P (fn)) 
-       use_thunk (fn, THUNK_GENERATE_WITH_VTABLE_P (fn));
+       use_thunk (fn, /*emit_p=*/0);
       mark_used (fn);
     }
 }
@@ -2369,7 +2369,12 @@ key_method (type)
        method = TREE_CHAIN (method))
     if (DECL_VINDEX (method) != NULL_TREE
        && ! DECL_DECLARED_INLINE_P (method)
-       && (! DECL_PURE_VIRTUAL_P (method) || DECL_DESTRUCTOR_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
+           ))
       return method;
 
   return NULL_TREE;
index e7d2bbb..4acf6b6 100644 (file)
@@ -295,11 +295,10 @@ request for member `%D' is ambiguous in multiple inheritance lattice",
    DELTA is the offset to this and VCALL_INDEX is zero.  */
 
 tree
-make_thunk (function, delta, vcall_index, generate_with_vtable_p)
+make_thunk (function, delta, vcall_index)
      tree function;
      tree delta;
      tree vcall_index;
-     int generate_with_vtable_p;
 {
   tree thunk_id;
   tree thunk;
@@ -348,7 +347,6 @@ make_thunk (function, delta, vcall_index, generate_with_vtable_p)
       DECL_INITIAL (thunk) = function;
       THUNK_DELTA (thunk) = d;
       THUNK_VCALL_OFFSET (thunk) = vcall_offset;
-      THUNK_GENERATE_WITH_VTABLE_P (thunk) = generate_with_vtable_p;
       /* The thunk itself is not a constructor or destructor, even if
          the thing it is thunking to is.  */
       DECL_INTERFACE_KNOWN (thunk) = 1;
@@ -381,7 +379,6 @@ void
 use_thunk (thunk_fndecl, emit_p)
      tree thunk_fndecl;
      int emit_p;
-     
 {
   tree fnaddr;
   tree function;
index fe95c95..81826c1 100644 (file)
@@ -2024,56 +2024,72 @@ look_for_overrides (type, fndecl)
   return found;
 }
 
-/* Look in TYPE for virtual functions overridden by FNDECL. Check both
-   TYPE itself and its bases. */
+/* 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.  */
 
-static int
-look_for_overrides_r (type, fndecl)
+tree
+look_for_overrides_here (type, fndecl)
      tree type, fndecl;
 {
   int ix;
-  
-  if (DECL_DESTRUCTOR_P (fndecl))
+
+  if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fndecl))
     ix = CLASSTYPE_DESTRUCTOR_SLOT;
   else
     ix = lookup_fnfields_1 (type, DECL_NAME (fndecl));
   if (ix >= 0)
     {
       tree fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ix);
-      tree dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
-      tree thistype = DECL_STATIC_FUNCTION_P (fndecl)
-                      ? NULL_TREE : TREE_TYPE (TREE_VALUE (dtypes));
   
       for (; fns; fns = OVL_NEXT (fns))
         {
           tree fn = OVL_CURRENT (fns);
-          tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn));
-          
+
           if (!DECL_VIRTUAL_P (fn))
-            /*  Not a virtual */;
+            /* Not a virtual.  */;
           else if (DECL_CONTEXT (fn) != type)
-            /*  Introduced with a using declaration */;
-         else if (thistype == NULL_TREE)
+            /* Introduced with a using declaration.  */;
+         else if (DECL_STATIC_FUNCTION_P (fndecl))
            {
-             if (compparms (TREE_CHAIN (btypes), dtypes))
-                {
-                  /* A static member function cannot match an inherited
-                     virtual member function.  */
-                  cp_error_at ("`%#D' cannot be declared", fndecl);
-                  cp_error_at ("  since `%#D' declared in base class", fn);
-                  return 1;
-                }
+             tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn));
+             tree dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+             if (compparms (TREE_CHAIN (btypes), dtypes))
+               return fn;
             }
           else if (same_signature_p (fndecl, fn))
-            {
-             /* It's definitely virtual, even if not explicitly set.  */
-             DECL_VIRTUAL_P (fndecl) = 1;
-             check_final_overrider (fndecl, fn);
+           return fn;
+       }
+    }
+  return NULL_TREE;
+}
 
-             return 1;
-           }
+/* Look in TYPE for virtual functions overridden by FNDECL. Check both
+   TYPE itself and its bases. */
+
+static int
+look_for_overrides_r (type, fndecl)
+     tree type, fndecl;
+{
+  tree fn = look_for_overrides_here (type, fndecl);
+  if (fn)
+    {
+      if (DECL_STATIC_FUNCTION_P (fndecl))
+       {
+         /* A static member function cannot match an inherited
+            virtual member function.  */
+         cp_error_at ("`%#D' cannot be declared", fndecl);
+         cp_error_at ("  since `%#D' declared in base class", fn);
+       }
+      else
+       {
+         /* It's definitely virtual, even if not explicitly set.  */
+         DECL_VIRTUAL_P (fndecl) = 1;
+         check_final_overrider (fndecl, fn);
        }
+      return 1;
     }
+
   /* We failed to find one declared in this class. Look in its bases.  */
   return look_for_overrides (type, fndecl);
 }
index f1a9e77..9dddf23 100644 (file)
@@ -2300,7 +2300,7 @@ emit_associated_thunks (fn)
        for (v = BINFO_VIRTUALS (binfo); v; v = TREE_CHAIN (v))
          if (BV_FN (v) == fn
              && (!integer_zerop (BV_DELTA (v))
-                 || BV_VCALL_INDEX (v)))
+                 || BV_USE_VCALL_INDEX_P (v)))
            {
              tree thunk;
              tree vcall_index;
@@ -2317,8 +2317,7 @@ emit_associated_thunks (fn)
                                          vfunc_ptr_type_node,
                                          fn),
                                  BV_DELTA (v),
-                                 vcall_index,
-                                 /*generate_with_vtable_p=*/0);
+                                 vcall_index);
              use_thunk (thunk, /*emit_p=*/1);
            }
     }
index 499367e..808e56d 100644 (file)
@@ -26,4 +26,3 @@ C c;
 // { dg-final { scan-assembler mangle1.C "\n_ZTT1C:" } }
 // { dg-final { scan-assembler mangle1.C "\n_ZTV1A:" } }
 // { dg-final { scan-assembler mangle1.C "\n_ZTV1C:" } }
-// { dg-final { scan-assembler mangle1.C "\n_ZTv0_n\(12|24\)_N1A1fEv:" } }