diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 577038eccc22fc7dd224e66bb530a1cdca4b53d4..5df346cebada76bcc381c99be5620f6f0cdb52ea 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,35 @@
+2001-06-12  Nathan Sidwell  <nathan@codesourcery.com>
+
+	PR c++/3130, c++/3131, c++/3132
+	* cp-tree.h (BINFO_UNSHARED_MARKED): New #define.
+	* class.c (force_canonical_binfo_r): Move
+	BINFO_UNSHARED_MARKED, BINFO_LOST_PRIMARY_P. Don't move
+	virtual bases unless they're primary and what they're primary
+	too has been moved.
+	(dfs_unshared_virtual_bases): Use BINFO_UNSHARED_MARKED. Cope
+	with morally virtual bases. Duplicate BINFO_LOST_PRIMARY_P and
+	BINFO_PRIMARY_BASE_OF. Clear BINFO_VTABLE for all but the most
+	derived binfo.
+	(mark_primary_bases): Use BINFO_UNSHARED_MARKED.
+	(layout_nonempty_base_or_field): Add most derived type
+	parameter. Adjust.
+	(layout_empty_base): Likewise.
+	(build_base_field): Likewise.
+	(build_base_fields): Likewise.
+	(propagate_binfo_offsets): Add most derived type
+	parameter. Skip non canonical virtual bases too.
+	(dfs_set_offset_for_unshared_vbases): Don't skip primary
+	bases. Do skip canonical bases.
+	(layout_virtual_bases): Adjust.
+	(layout_class_type): Adjust.
+	(dfs_get_primary_binfo): Build list of virtual primary base
+	candidates.
+	(get_primary_binfo): Check that the shared virtual primary
+	base candidate was found first.
+	(accumulate_vtbl_inits): Don't do anything for non-vptr
+	containing binfos. For case 1 primary virtual bases, keep
+	checking that we've not emerged from the hierarchy of RTTI_BINFO.
+
 2001-06-12  Nathan Sidwell  <nathan@codesourcery.com>
 
 	PR c++/3089
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index a0cd2ce1c9e82dd883e5465bc99acbe9ac953298..c1347b3cb336fc6c6b504544669cf44bac839b2e 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -144,9 +144,9 @@ static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
 static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *, 
 				     int *));
 static bool build_base_field PARAMS ((record_layout_info, tree, int *,
-				     splay_tree));
+				     splay_tree, tree));
 static bool build_base_fields PARAMS ((record_layout_info, int *,
-				      splay_tree));
+				      splay_tree, tree));
 static tree build_vbase_pointer_fields PARAMS ((record_layout_info, int *));
 static tree build_vtbl_or_vbase_field PARAMS ((tree, tree, tree, tree, tree,
 					       int *));
@@ -159,7 +159,7 @@ static void layout_class_type PARAMS ((tree, int *, int *, tree *, tree *));
 static void fixup_pending_inline PARAMS ((tree));
 static void fixup_inline_methods PARAMS ((tree));
 static void set_primary_base PARAMS ((tree, tree, int *));
-static void propagate_binfo_offsets PARAMS ((tree, tree));
+static void propagate_binfo_offsets PARAMS ((tree, tree, tree));
 static void layout_virtual_bases PARAMS ((tree, splay_tree));
 static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
 static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
@@ -181,9 +181,9 @@ static void initialize_vtable PARAMS ((tree, tree));
 static void initialize_array PARAMS ((tree, tree));
 static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
 						   tree, tree,
-						   splay_tree));
+						   splay_tree, tree));
 static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
-static bool layout_empty_base PARAMS ((tree, tree, splay_tree));
+static bool layout_empty_base PARAMS ((tree, tree, splay_tree, tree));
 static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
 static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
 					       tree));
@@ -1676,6 +1676,10 @@ force_canonical_binfo_r (to, from, type, mappings)
   BINFO_INDIRECT_PRIMARY_P (to)
           = BINFO_INDIRECT_PRIMARY_P (from);
   BINFO_INDIRECT_PRIMARY_P (from) = 0;
+  BINFO_UNSHARED_MARKED (to) = BINFO_UNSHARED_MARKED (from);
+  BINFO_UNSHARED_MARKED (from) = 0;
+  BINFO_LOST_PRIMARY_P (to) = BINFO_LOST_PRIMARY_P (from);
+  BINFO_LOST_PRIMARY_P (from) = 0;
   if (BINFO_PRIMARY_P (from))
     {
       tree primary = BINFO_PRIMARY_BASE_OF (from);
@@ -1689,7 +1693,8 @@ force_canonical_binfo_r (to, from, type, mappings)
       BINFO_PRIMARY_BASE_OF (to) = primary;
       BINFO_PRIMARY_BASE_OF (from) = NULL_TREE;
     }
-  my_friendly_assert (same_type_p (BINFO_TYPE (to), BINFO_TYPE (from)), 20010104);
+  my_friendly_assert (same_type_p (BINFO_TYPE (to), BINFO_TYPE (from)),
+		      20010104);
   mappings = tree_cons (from, to, mappings);
   for (i = 0; i != n_baseclasses; i++)
     {
@@ -1698,9 +1703,10 @@ force_canonical_binfo_r (to, from, type, mappings)
       
       if (TREE_VIA_VIRTUAL (from_binfo))
         {
-          tree shared_binfo = binfo_for_vbase (BINFO_TYPE (from_binfo), type);
-          
-          if (shared_binfo == from_binfo)
+	  if (BINFO_PRIMARY_P (from_binfo) &&
+	      purpose_member (BINFO_PRIMARY_BASE_OF (from_binfo), mappings))
+	    /* This base is a primary of some binfo we have already
+	       reseated. We must reseat this one too.  */
             force_canonical_binfo (to_binfo, from_binfo, type, mappings);
         }
       else
@@ -1764,7 +1770,7 @@ mark_primary_virtual_base (binfo, base_binfo, type)
   delta = size_diffop (BINFO_OFFSET (binfo), BINFO_OFFSET (base_binfo));
   if (!integer_zerop (delta))
     {
-      propagate_binfo_offsets (base_binfo, delta);
+      propagate_binfo_offsets (base_binfo, delta, type);
       BINFO_OFFSET (base_binfo) = BINFO_OFFSET (binfo);
     }
   return base_binfo;
@@ -1772,19 +1778,43 @@ mark_primary_virtual_base (binfo, base_binfo, type)
 
 /* 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. */
+   mark_primary_bases.  DATA is the most derived type. */
 
 static tree dfs_unshared_virtual_bases (binfo, data)
      tree binfo;
-     void *data ATTRIBUTE_UNUSED;
+     void *data;
 {
-  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_MARKED (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);
+  tree t = (tree) data;
+  
+  if (!BINFO_UNSHARED_MARKED (binfo)
+      && CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
+    {
+      /* This morally virtual base has a primary base when it
+         is a complete object. We need to locate the shared instance
+         of this binfo in the type dominated by T. We duplicate the
+         primary base information from there to here.  */
+      tree vbase;
+      tree unshared_base;
+      
+      for (vbase = binfo; !TREE_VIA_VIRTUAL (vbase);
+	   vbase = BINFO_INHERITANCE_CHAIN (vbase))
+	continue;
+      unshared_base = get_original_base (binfo,
+					 binfo_for_vbase (BINFO_TYPE (vbase),
+							  t));
+      my_friendly_assert (unshared_base != binfo, 20010612);
+      BINFO_LOST_PRIMARY_P (binfo) = BINFO_LOST_PRIMARY_P (unshared_base);
+      if (!BINFO_LOST_PRIMARY_P (binfo))
+	      BINFO_PRIMARY_BASE_OF (get_primary_binfo (binfo)) = binfo;
+    }
+  
+  if (binfo != TYPE_BINFO (t))
+    /* The vtable fields will have been copied when duplicating the
+       base binfos. That information is bogus, make sure we don't try
+       and use it. */
+    BINFO_VTABLE (binfo) = NULL_TREE;
   
+  BINFO_UNSHARED_MARKED (binfo) = 0;
   return NULL;
 }
 
@@ -1813,12 +1843,13 @@ mark_primary_bases (type)
 
       if (base_binfo)
         BINFO_PRIMARY_BASE_OF (base_binfo) = binfo;
-      SET_BINFO_MARKED (binfo);
+      
+      BINFO_UNSHARED_MARKED (binfo) = 1;
     }
-  /* There could remain unshared virtual bases which were not visited
+  /* There could remain unshared morally virtual bases which were not visited
      in the inheritance graph walk. These bases will have lost their
-     primary base (should they have one). We must now find them. */
-  dfs_walk (TYPE_BINFO (type), dfs_unshared_virtual_bases, NULL, NULL);
+     virtual primary base (should they have one). We must now find them. */
+  dfs_walk (TYPE_BINFO (type), dfs_unshared_virtual_bases, NULL, type);
 }
 
 /* Make the BINFO the primary base of T.  */
@@ -3933,15 +3964,16 @@ layout_conflict_p (type, offset, offsets, vbases_p)
 /* DECL is a FIELD_DECL corresponding either to a base subobject of a
    non-static data member of the type indicated by RLI.  BINFO is the
    binfo corresponding to the base subobject, OFFSETS maps offsets to
-   types already located at those offsets.  This function determines
-   the position of the DECL.  */
+   types already located at those offsets.  T is the most derived
+   type.  This function determines the position of the DECL.  */
 
 static void
-layout_nonempty_base_or_field (rli, decl, binfo, offsets)
+layout_nonempty_base_or_field (rli, decl, binfo, offsets, t)
      record_layout_info rli;
      tree decl;
      tree binfo;
      splay_tree offsets;
+     tree t;
 {
   tree offset = NULL_TREE;
   tree type = TREE_TYPE (decl);
@@ -3998,24 +4030,25 @@ layout_nonempty_base_or_field (rli, decl, binfo, offsets)
 	break;
     }
 
-  /* Now that we know where it wil be placed, update its
+  /* Now that we know where it will be placed, update its
      BINFO_OFFSET.  */
   if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
     propagate_binfo_offsets (binfo, 
-			     convert (ssizetype, offset));
+			     convert (ssizetype, offset), t);
 }
 
 /* Layout the empty base BINFO.  EOC indicates the byte currently just
    past the end of the class, and should be correctly aligned for a
    class of the type indicated by BINFO; OFFSETS gives the offsets of
-   the empty bases allocated so far. Return non-zero iff we added it
-   at the end. */
+   the empty bases allocated so far. T is the most derived
+   type.  Return non-zero iff we added it at the end. */
 
 static bool
-layout_empty_base (binfo, eoc, offsets)
+layout_empty_base (binfo, eoc, offsets, t)
      tree binfo;
      tree eoc;
      splay_tree offsets;
+     tree t;
 {
   tree alignment;
   tree basetype = BINFO_TYPE (binfo);
@@ -4035,7 +4068,7 @@ layout_empty_base (binfo, eoc, offsets)
       /* That didn't work.  Now, we move forward from the next
 	 available spot in the class.  */
       atend = true;
-      propagate_binfo_offsets (binfo, convert (ssizetype, eoc));
+      propagate_binfo_offsets (binfo, convert (ssizetype, eoc), t);
       while (1) 
 	{
 	  if (!layout_conflict_p (BINFO_TYPE (binfo),
@@ -4046,7 +4079,7 @@ layout_empty_base (binfo, eoc, offsets)
 	    break;
 
 	  /* There's overlap here, too.  Bump along to the next spot.  */
-	  propagate_binfo_offsets (binfo, alignment);
+	  propagate_binfo_offsets (binfo, alignment, t);
 	}
     }
   return atend;
@@ -4055,15 +4088,17 @@ layout_empty_base (binfo, eoc, offsets)
 /* Build a FIELD_DECL for the base given by BINFO in the class
    indicated by RLI.  If the new object is non-empty, clear *EMPTY_P.
    *BASE_ALIGN is a running maximum of the alignments of any base
-   class.  OFFSETS gives the location of empty base subobjects. Return
-   non-zero if the new object cannot be nearly-empty. */
+   class.  OFFSETS gives the location of empty base subobjects.  T is
+   the most derived type.  Return non-zero if the new object cannot be
+   nearly-empty. */
 
 static bool
-build_base_field (rli, binfo, empty_p, offsets)
+build_base_field (rli, binfo, empty_p, offsets, t)
      record_layout_info rli;
      tree binfo;
      int *empty_p;
      splay_tree offsets;
+     tree t;
 {
   tree basetype = BINFO_TYPE (binfo);
   tree decl;
@@ -4091,7 +4126,7 @@ build_base_field (rli, binfo, empty_p, offsets)
       /* Try to place the field.  It may take more than one try if we
 	 have a hard time placing the field without putting two
 	 objects of the same type at the same address.  */
-      layout_nonempty_base_or_field (rli, decl, binfo, offsets);
+      layout_nonempty_base_or_field (rli, decl, binfo, offsets, t);
     }
   else
     {
@@ -4101,7 +4136,7 @@ build_base_field (rli, binfo, empty_p, offsets)
 	 byte-aligned.  */
       eoc = tree_low_cst (rli_size_unit_so_far (rli), 0);
       eoc = CEIL (eoc, DECL_ALIGN_UNIT (decl)) * DECL_ALIGN_UNIT (decl);
-      atend |= layout_empty_base (binfo, size_int (eoc), offsets);
+      atend |= layout_empty_base (binfo, size_int (eoc), offsets, t);
     }
 
   /* Record the offsets of BINFO and its base subobjects.  */
@@ -4113,14 +4148,15 @@ build_base_field (rli, binfo, empty_p, offsets)
 }
 
 /* Layout all of the non-virtual base classes.  Record empty
-   subobjects in OFFSETS. Return non-zero if the type cannot be nearly
-   empty.  */
+   subobjects in OFFSETS.  T is the most derived type.  Return
+   non-zero if the type cannot be nearly empty.  */
 
 static bool
-build_base_fields (rli, empty_p, offsets)
+build_base_fields (rli, empty_p, offsets, t)
      record_layout_info rli;
      int *empty_p;
      splay_tree offsets;
+     tree t;
 {
   /* Chain to hold all the new FIELD_DECLs which stand in for base class
      subobjects.  */
@@ -4133,7 +4169,7 @@ build_base_fields (rli, empty_p, offsets)
      first.  */
   if (CLASSTYPE_HAS_PRIMARY_BASE_P (rec))
     build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec), 
-		      empty_p, offsets);
+		      empty_p, offsets, t);
 
   /* Now allocate the rest of the bases.  */
   for (i = 0; i < n_baseclasses; ++i)
@@ -4154,7 +4190,7 @@ build_base_fields (rli, empty_p, offsets)
 	  && !BINFO_PRIMARY_P (base_binfo))
 	continue;
 
-      atend |= build_base_field (rli, base_binfo, empty_p, offsets);
+      atend |= build_base_field (rli, base_binfo, empty_p, offsets, t);
     }
   return atend;
 }
@@ -4728,9 +4764,10 @@ fixup_inline_methods (type)
    OFFSET, which is a type offset, is number of bytes.  */
 
 static void
-propagate_binfo_offsets (binfo, offset)
+propagate_binfo_offsets (binfo, offset, t)
      tree binfo;
      tree offset;
+     tree t;
 {
   int i;
   tree primary_binfo;
@@ -4751,9 +4788,9 @@ propagate_binfo_offsets (binfo, offset)
     {
       tree base_binfo;
 
-      /* On the first through the loop, do the primary base.  Because
-	 the primary base need not be an immediate base, we must
-	 handle the primary base specially.  */
+      /* On the first time through the loop, do the primary base.
+	 Because the primary base need not be an immediate base, we
+	 must handle the primary base specially.  */
       if (i == -1) 
 	{
 	  if (!primary_binfo) 
@@ -4769,12 +4806,13 @@ propagate_binfo_offsets (binfo, offset)
 	    continue;
 	}
 
-      /* Skip virtual bases that aren't our primary base.  */
+      /* Skip virtual bases that aren't our canonical primary base.  */
       if (TREE_VIA_VIRTUAL (base_binfo)
-	  && BINFO_PRIMARY_BASE_OF (base_binfo) != binfo)
+	  && (BINFO_PRIMARY_BASE_OF (base_binfo) != binfo
+	      || base_binfo != binfo_for_vbase (BINFO_TYPE (base_binfo), t)))
 	continue;
 
-      propagate_binfo_offsets (base_binfo, offset);
+      propagate_binfo_offsets (base_binfo, offset, t);
     }
 }
 
@@ -4788,15 +4826,18 @@ dfs_set_offset_for_unshared_vbases (binfo, data)
   /* If this is a virtual base, make sure it has the same offset as
      the shared copy.  If it's a primary base, then we know it's
      correct.  */
-  if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_P (binfo))
+  if (TREE_VIA_VIRTUAL (binfo))
     {
       tree t = (tree) data;
       tree vbase;
       tree offset;
       
       vbase = binfo_for_vbase (BINFO_TYPE (binfo), t);
-      offset = size_diffop (BINFO_OFFSET (vbase), BINFO_OFFSET (binfo));
-      propagate_binfo_offsets (binfo, offset);
+      if (vbase != binfo)
+	{
+	  offset = size_diffop (BINFO_OFFSET (vbase), BINFO_OFFSET (binfo));
+	  propagate_binfo_offsets (binfo, offset, t);
+	}
     }
 
   return NULL_TREE;
@@ -4866,7 +4907,7 @@ layout_virtual_bases (t, offsets)
 	  if (is_empty_class (basetype))
 	    layout_empty_base (vbase,
 			       size_int (CEIL (dsize, BITS_PER_UNIT)),
-			       offsets);
+			       offsets, t);
 	  else
 	    {
 	      tree offset;
@@ -4877,7 +4918,7 @@ layout_virtual_bases (t, offsets)
 					     BINFO_OFFSET (vbase)));
 
 	      /* And compute the offset of the virtual base.  */
-	      propagate_binfo_offsets (vbase, offset);
+	      propagate_binfo_offsets (vbase, offset, t);
 	      /* Every virtual baseclass takes a least a UNIT, so that
 		 we can take it's address and get something different
 		 for each base.  */
@@ -5055,7 +5096,7 @@ layout_class_type (t, empty_p, vfuns_p,
   /* Build FIELD_DECLs for all of the non-virtual base-types.  */
   empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts, 
 				       NULL, NULL);
-  if (build_base_fields (rli, empty_p, empty_base_offsets))
+  if (build_base_fields (rli, empty_p, empty_base_offsets, t))
     CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
   
   /* Add pointers to all of our virtual base-classes.  */
@@ -5117,7 +5158,7 @@ layout_class_type (t, empty_p, vfuns_p,
 	padding = NULL_TREE;
 
       layout_nonempty_base_or_field (rli, field, NULL_TREE,
-				     empty_base_offsets);
+				     empty_base_offsets, t);
 
       /* If we needed additional padding after this field, add it
 	 now.  */
@@ -5134,7 +5175,7 @@ layout_class_type (t, empty_p, vfuns_p,
 	  DECL_USER_ALIGN (padding_field) = 0;
 	  layout_nonempty_base_or_field (rli, padding_field,
 					 NULL_TREE, 
-					 empty_base_offsets);
+					 empty_base_offsets, t);
 	}
     }
 
@@ -6716,18 +6757,24 @@ get_vtbl_decl_for_binfo (binfo)
   return decl;
 }
 
-/* Called from get_primary_binfo via dfs_walk.  */
+/* Called from get_primary_binfo via dfs_walk.  DATA is a TREE_LIST
+   who's TREE_PURPOSE is the TYPE of the required primary base and
+   who's TREE_VALUE is a list of candidate binfos that we fill in. */
 
 static tree
 dfs_get_primary_binfo (binfo, data)
      tree binfo;
      void *data;
 {
-  tree primary_base = (tree) data;
+  tree cons = (tree) data;
+  tree primary_base = TREE_PURPOSE (cons);
 
   if (TREE_VIA_VIRTUAL (binfo) 
-      && same_type_p (BINFO_TYPE (binfo), BINFO_TYPE (primary_base)))
-    return binfo;
+      && same_type_p (BINFO_TYPE (binfo), primary_base))
+    /* This is the right type of binfo, but it might be an unshared
+       instance, and the shared instance is later in the dfs walk.  We
+       must keep looking.  */
+    TREE_VALUE (cons) = tree_cons (NULL, binfo, TREE_VALUE (cons));
   
   return NULL_TREE;
 }
@@ -6745,7 +6792,8 @@ get_primary_binfo (binfo)
 {
   tree primary_base;
   tree result;
-
+  tree virtuals;
+  
   primary_base = CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (binfo));
   if (!primary_base)
     return NULL_TREE;
@@ -6773,9 +6821,48 @@ get_primary_binfo (binfo)
 
   /* For a primary virtual base, we have to scan the entire hierarchy
      rooted at BINFO; the virtual base could be an indirect virtual
-     base.  */
-  result = dfs_walk (binfo, dfs_get_primary_binfo, NULL, primary_base);
-  my_friendly_assert (result != NULL_TREE, 20000730);
+     base.  There could be more than one instance of the primary base
+     in the hierarchy, and if one is the canonical binfo we want that
+     one.  If it exists, it should be the first one we find, but as a
+     consistency check we find them all and make sure.  */
+  virtuals = build_tree_list (BINFO_TYPE (primary_base), NULL_TREE);
+  dfs_walk (binfo, dfs_get_primary_binfo, NULL, virtuals);
+  virtuals = TREE_VALUE (virtuals);
+  
+  /* We must have found at least one instance.  */
+  my_friendly_assert (virtuals, 20010612);
+
+  if (TREE_CHAIN (virtuals))
+    {
+      /* We found more than one instance of the base. We must make
+         sure that, if one is the canonical one, it is the first one
+         we found. As the chain is in reverse dfs order, that means
+         the last on the list.  */
+      tree complete_binfo;
+      tree canonical;
+      
+      for (complete_binfo = binfo;
+	   BINFO_INHERITANCE_CHAIN (complete_binfo);
+	   complete_binfo = BINFO_INHERITANCE_CHAIN (complete_binfo))
+	continue;
+      canonical = binfo_for_vbase (BINFO_TYPE (primary_base),
+				   BINFO_TYPE (complete_binfo));
+      
+      for (; virtuals; virtuals = TREE_CHAIN (virtuals))
+	{
+	  result = TREE_VALUE (virtuals);
+
+	  if (canonical == result)
+	    {
+	      /* This is the unshared instance. Make sure it was the
+		 first one found.  */
+	      my_friendly_assert (!TREE_CHAIN (virtuals), 20010612);
+	      break;
+	    }
+	}
+    }
+  else
+    result = TREE_VALUE (virtuals);
   return result;
 }
 
@@ -7477,6 +7564,10 @@ accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, inits)
 				   BINFO_TYPE (orig_binfo)),
 		      20000517);
 
+  /* If it doesn't have a vpte, we don't do anything. */
+  if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo)))
+    return;
+  
   /* If we're building a construction vtable, we're not interested in
      subobjects that don't require construction vtables.  */
   if (ctor_vtbl_p 
@@ -7562,10 +7653,20 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
 
 	      for (; b; b = BINFO_PRIMARY_BASE_OF (b))
 		{
+		  tree probe;
+
+		  /* See if B is still within the hierarchy starting
+		     at RTTI_BINFO. */
+		  for (probe = b; probe;
+		       probe = BINFO_INHERITANCE_CHAIN (probe))
+		    if (probe == rtti_binfo)
+		      break;
+		  
+		  if (!probe)
+		    break;
+		  
 		  primary = b;
 		  orig_primary = BINFO_PRIMARY_BASE_OF (orig_primary);
-		  if (b == rtti_binfo)
-		    break;
 		}
 	    }
 	  else
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b73626a331000a03ff99c74323bf2bd0340fb186..5da11ee3151b127d8694edc8ec31243892c2952a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1627,6 +1627,10 @@ struct lang_type
    inheritance is indicated by the absence of the other two flags, not
    by TREE_VIA_PRIVATE, which is unused.  */
 
+/* Mark the binfo, whether shared or not. Each instance of a virtual
+   base can be separately marked.  */
+#define BINFO_UNSHARED_MARKED(NODE) TREE_LANG_FLAG_0(NODE)
+
 /* Nonzero means marked by DFS or BFS search, including searches
    by `get_binfo' and `get_base_distance'.  */
 #define BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED(BINFO_TYPE(NODE)):TREE_LANG_FLAG_0(NODE))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index dfc4b53d9d65acd90168d89cc4f1b7cb34d5c50e..01139ba0dc39bfb61210a3a4a184fd606e902777 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2001-06-12  Nathan Sidwell  <nathan@codesourcery.com>
+
+	* g++.old-deja/g++.abi/vbase5.C: New test.
+	* g++.old-deja/g++.abi/vbase6.C: New test.
+	* g++.old-deja/g++.abi/vbase7.C: New test.
+
 2001-06-12  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
 	* gcc.c-torture/compile/20010610-1.c: New test.
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vbase5.C b/gcc/testsuite/g++.old-deja/g++.abi/vbase5.C
new file mode 100644
index 0000000000000000000000000000000000000000..6a3bbfbfb4b4119f79ed079b8ce35187302efe95
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.abi/vbase5.C
@@ -0,0 +1,22 @@
+// Build don't link:
+// 
+// Copyright (C) 2001 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 12 Jun 2001 <nathan@codesourcery.com>
+
+// 3130. A virtual base can have canonical and non-canonical instances
+// of its primary. The canonical one should be first in dfs order.
+
+struct A
+{
+  virtual ~A ();
+};
+
+struct B
+{
+  virtual ~B ();
+};
+
+
+struct C : virtual public A, virtual public B {};
+class D : public virtual C {};
+class E : public virtual C, public virtual D {};
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vbase6.C b/gcc/testsuite/g++.old-deja/g++.abi/vbase6.C
new file mode 100644
index 0000000000000000000000000000000000000000..e8b959db32c9b97e3fc037b0a44e612f9df19a79
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.abi/vbase6.C
@@ -0,0 +1,22 @@
+// Build don't link:
+// 
+// Copyright (C) 2001 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 12 Jun 2001 <nathan@codesourcery.com>
+
+// 3131. 
+
+struct A
+{
+  virtual ~A ();
+};
+
+struct B
+{
+  virtual ~B ();
+};
+
+
+struct C : virtual public B {};
+struct D : virtual public A, virtual public C {};
+struct E : public virtual C {};
+struct F : public virtual D, public virtual E {};
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vbase7.C b/gcc/testsuite/g++.old-deja/g++.abi/vbase7.C
new file mode 100644
index 0000000000000000000000000000000000000000..5a4a3b5fdba0872035571eb20b4b7fc5a75d3bea
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.abi/vbase7.C
@@ -0,0 +1,40 @@
+// Build don't run
+// 
+// Copyright (C) 2001 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 12 Jun 2001 <nathan@codesourcery.com>
+
+// 3132. A virtual thunk was missing.
+
+struct A
+{
+  int x;
+  virtual ~A() {}
+};
+
+struct B
+{
+  virtual ~B() { }
+};
+
+
+struct C
+{
+  virtual ~C () {}
+};
+
+
+struct D : public virtual A {};
+struct E : virtual public B, virtual public D {};
+struct F : virtual public C, virtual public E {};
+struct G : public virtual E {};
+
+struct H : public virtual F, public virtual G
+{
+  virtual ~H ();
+};
+H::~H() {}
+
+int main ()
+{
+  return 0;
+}