OSDN Git Service

cp:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 12 Jun 2001 08:47:48 +0000 (08:47 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 12 Jun 2001 08:47:48 +0000 (08:47 +0000)
PR c++/3089
* class.c (dfs_accumulate_vtbl_inits): Always walk down the
hierarchy looking for primary bases for a ctor
vtable. Recursively call oneself, if we meet our primary via
this route and haven't met it yet via inheritance graph order.
testsuite:
* g++.old-deja/g++.abi/vbase4.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@43248 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.old-deja/g++.abi/vbase4.C [new file with mode: 0644]

index 8d84da6..577038e 100644 (file)
@@ -1,3 +1,11 @@
+2001-06-12  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/3089
+       * class.c (dfs_accumulate_vtbl_inits): Always walk down the
+       hierarchy looking for primary bases for a ctor
+       vtable. Recursively call oneself, if we meet our primary via
+       this route and haven't met it yet via inheritance graph order.
+
 2001-06-11  Mark Mitchell  <mark@codesourcery.com>
 
        * lang-options.h: Emit documentation for -fno-honor-std, not
index 499053c..a0cd2ce 100644 (file)
@@ -7409,7 +7409,7 @@ build_ctor_vtbl_group (binfo, t)
   tree id;
   tree vbase;
 
-  /* See if we've already create this construction vtable group.  */
+  /* See if we've already created this construction vtable group.  */
   id = mangle_ctor_vtbl_for_type (t, binfo);
   if (IDENTIFIER_GLOBAL_VALUE (id))
     return;
@@ -7525,91 +7525,118 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
   tree vtbl = NULL_TREE;
   int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
 
-  if (ctor_vtbl_p
-      && TREE_VIA_VIRTUAL (orig_binfo) && BINFO_PRIMARY_P (orig_binfo))
+  if (ctor_vtbl_p)
     {
-      /* In the hierarchy of BINFO_TYPE (RTTI_BINFO), this is a primary
-         virtual base.  If it is not the same primary in the hierarchy of T,
-         we'll need to generate a ctor vtable for it, to place at its
-         location in T.  If it is the same primary, we still need a VTT
-         entry for the vtable, but it should point to the ctor vtable for the
-        base it is a primary for within the sub-hierarchy of RTTI_BINFO.
-
-        There are three possible cases:
-
-         1) We are in the same place.
-        2) We are a primary base within a lost primary virtual base of
-           RTTI_BINFO.
-        3) We are not primary to anything else in RTTI_BINFO.  */
-
-      tree primary = NULL_TREE;
-      if (tree_int_cst_equal (BINFO_OFFSET (orig_binfo),
-                             size_diffop (BINFO_OFFSET (binfo),
-                                          BINFO_OFFSET (rtti_binfo))))
+      tree primary = binfo;
+      tree orig_primary = orig_binfo;
+      
+      if (TREE_VIA_VIRTUAL (orig_binfo) && BINFO_PRIMARY_P (orig_binfo))
        {
-         /* Case 1: We're in the same place relative to RTTI_BINFO as we
-            were in the complete type, so we are primary either to
-            RTTI_BINFO or one of its secondary bases.  */
-
-         tree b = BINFO_PRIMARY_BASE_OF (binfo);
-
-         /* Walk down our until we either find the last primary base or
-            rtti_binfo.  */
-         for (; b; b = BINFO_PRIMARY_BASE_OF (b))
+         /* In the hierarchy of BINFO_TYPE (RTTI_BINFO), this is a
+             primary virtual base.  If it is not the same primary in
+             the hierarchy of T, we'll need to generate a ctor vtable
+             for it, to place at its location in T.  If it is the same
+             primary, we still need a VTT entry for the vtable, but it
+             should point to the ctor vtable for the base it is a
+             primary for within the sub-hierarchy of RTTI_BINFO.
+             
+            There are three possible cases:
+             
+             1) We are in the same place.
+            2) We are a primary base within a lost primary virtual base of
+            RTTI_BINFO.
+            3) We are not primary to anything else in RTTI_BINFO.  */
+         
+         if (tree_int_cst_equal (BINFO_OFFSET (orig_binfo),
+                                 size_diffop (BINFO_OFFSET (binfo),
+                                              BINFO_OFFSET (rtti_binfo))))
            {
-             primary = b;
-             if (b == rtti_binfo)
-               break;
-           }
-        }
-      else
-       {
-         /* Case 2 or 3: We're not in the same place.  We might still be
-            primary to something within a lost primary virtual base of
-            RTTI_BINFO.  */
-
-         tree b = BINFO_PRIMARY_BASE_OF (binfo);
-         tree last;
+             /* Case 1: We're in the same place relative to
+                RTTI_BINFO as we were in the complete type, so we are
+                primary either to RTTI_BINFO or one of its secondary
+                bases.  */
+             
+             /* Walk down our until we either find the last
+                primary base or rtti_binfo.  */
+             tree b = BINFO_PRIMARY_BASE_OF (binfo);
 
-         /* First, look through the bases we are primary to for a virtual
-            base.  */
-         for (; b; b = BINFO_PRIMARY_BASE_OF (b))
+             for (; b; b = BINFO_PRIMARY_BASE_OF (b))
+               {
+                 primary = b;
+                 orig_primary = BINFO_PRIMARY_BASE_OF (orig_primary);
+                 if (b == rtti_binfo)
+                   break;
+               }
+           }
+         else
            {
-             last = b;
-             if (TREE_VIA_VIRTUAL (b))
-               break;
+             /* Case 2 or 3: We're not in the same place.  We might
+                still be primary to something within a lost primary
+                virtual base of RTTI_BINFO.  */
+             tree b;
+             tree last, orig_last;
+
+             /* First, look through the bases we are primary to for a
+                virtual base.  */
+             for (b = BINFO_PRIMARY_BASE_OF (binfo), orig_last = orig_binfo;
+                  b;
+                  b = BINFO_PRIMARY_BASE_OF (b))
+               {
+                 last = b;
+                 if (orig_last)
+                   orig_last = BINFO_PRIMARY_BASE_OF (orig_last);
+                 if (TREE_VIA_VIRTUAL (b))
+                   break;
+               }
+             /* If we run out of primary links, keep looking down our
+                inheritance chain; we might be an indirect primary of
+                a virtual base.  */
+             if (b == NULL_TREE)
+               for (b = last; b; b = BINFO_INHERITANCE_CHAIN (b))
+                 if (TREE_VIA_VIRTUAL (b))
+                   break;
+
+             /* If we found a virtual base B and it is a base of
+                RTTI_BINFO, we share our vtable with LAST, i.e. the
+                derived-most base within B of which we are a primary.
+                Otherwise, we get our own.  */
+             if (b && binfo_for_vbase (BINFO_TYPE (b),
+                                       BINFO_TYPE (rtti_binfo)))
+               {
+                 my_friendly_assert (orig_last, 20010611);
+                 primary = last;
+                 orig_primary = orig_last;
+               }
            }
-         /* If we run out of primary links, keep looking down our
-            inheritance chain; we might be an indirect primary of a
-            virtual base.  */
-         if (b == NULL_TREE)
-           for (b = last; b; b = BINFO_INHERITANCE_CHAIN (b))
-             if (TREE_VIA_VIRTUAL (b))
-               break;
-
-         /* If we found a virtual base B and it is a base of RTTI_BINFO, we
-            share our vtable with LAST, i.e. the derived-most base within
-            B of which we are a primary.  Otherwise, we get our own.  */
-         if (b && binfo_for_vbase (BINFO_TYPE (b),
-                                   BINFO_TYPE (rtti_binfo)))
-           primary = last;
        }
-
-      if (primary)
+      
+      vtbl = BINFO_VTABLE (primary);
+      if (vtbl && TREE_CODE (vtbl) == TREE_LIST
+         && TREE_PURPOSE (vtbl) == rtti_binfo)
        {
-          vtbl = BINFO_VTABLE (primary);
-         /* If we haven't already been here for our primary derivation,
-            all bets are off.  Especially for case 2 above, we need
-            the derived vtable to have been generated.  */
-         my_friendly_assert (TREE_CODE (vtbl) == TREE_LIST
-                             && TREE_PURPOSE (vtbl) == rtti_binfo,
-                             20010126);
          vtbl = TREE_VALUE (vtbl);
+         if (primary == binfo)
+           /* We created this vtable because we met its primary base
+              earlier in the inheritance graph walk of
+              RTTI_BINFO.  */
+           return inits;
        }
+      else if (primary != binfo)
+       {
+         /* We're the primary of some binfo that we've not yet
+            met in the inheritance graph walk of RTTI_BINFO. We
+            must create that vtable now. */
+         inits = dfs_accumulate_vtbl_inits (primary, orig_primary,
+                                            rtti_binfo, t, l);
+         vtbl = BINFO_VTABLE (primary);
+         vtbl = TREE_VALUE (vtbl);
+       }
+      else
+       vtbl = NULL;
     }
   else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo, BINFO_TYPE (rtti_binfo)))
     return inits;
-  
+
   if (!vtbl)
     {
       tree index;
@@ -7635,19 +7662,16 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
       TREE_CONSTANT (vtbl) = 1;
     }
 
-  if (!ctor_vtbl_p)
-    {
-      /* For an ordinary vtable, set BINFO_VTABLE.  */
-      if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo))
-       inits = NULL_TREE;
-      else
-       BINFO_VTABLE (binfo) = vtbl;
-    }
-  else
+  if (ctor_vtbl_p)
     /* For a construction vtable, we can't overwrite BINFO_VTABLE.
        So, we make a TREE_LIST.  Later, dfs_fixup_binfo_vtbls will
        straighten this out.  */
     BINFO_VTABLE (binfo) = tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo));
+  else if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo))
+    inits = NULL_TREE;
+  else
+     /* For an ordinary vtable, set BINFO_VTABLE.  */
+    BINFO_VTABLE (binfo) = vtbl;
 
   return inits;
 }
index be457a8..a4dfba0 100644 (file)
@@ -1,3 +1,7 @@
+2001-06-12  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * g++.old-deja/g++.abi/vbase4.C: New test.
+
 2001-06-11  Stephane Carrez  <Stephane.Carrez@worldnet.fr>
 
        * gcc.c-torture/execute/920501-8.x: New file, sprintf() does not
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vbase4.C b/gcc/testsuite/g++.old-deja/g++.abi/vbase4.C
new file mode 100644 (file)
index 0000000..116d79b
--- /dev/null
@@ -0,0 +1,165 @@
+// Copyright (C) 2001 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 9 Jun 2001 <nathan@codesourcery.com>
+
+// Bug 3089. We ICE'd in construction vtables.
+
+int failed;
+
+void fail (int val)
+{
+  if (!failed)
+    failed = val;
+}
+
+struct A
+{
+  virtual ~A();
+  A ();
+  virtual void check (void *whole, void *base);
+};
+
+A::A ()
+{
+  check (this, this);
+}
+A::~A ()
+{
+  check (this, this);
+}
+
+void A::check (void *whole, void *base)
+{
+  if (dynamic_cast <void *> (this) != whole)
+    fail (1);
+  else if (this != base)
+    fail (2);
+}
+
+struct B
+{
+  virtual ~B ();
+  B ();
+  virtual void check (void *whole, void *base);
+};
+
+B::B ()
+{
+  check (this, this);
+}
+B::~B ()
+{
+  check (this, this);
+}
+void B::check (void *whole, void *base)
+{
+  if (dynamic_cast <void *> (this) != whole)
+    fail (3);
+  else if (this != base)
+    fail (4);
+}
+
+struct C : virtual public B, virtual public A
+{
+  virtual ~C ();
+  C ();
+  virtual void check (void *whole, void *base);
+};
+C::C ()
+{
+  check (this, this);
+}
+C::~C ()
+{
+  check (this, this);
+}
+void C::check (void *whole, void *base)
+{
+  if (dynamic_cast <void *> (this) != whole)
+    fail (5);
+  else if (this != base)
+    fail (6);
+  A::check (whole, static_cast <A *> (this));
+  B::check (whole, static_cast <B *> (this));
+}
+
+struct D : virtual public A
+{
+  virtual ~D ();
+  D ();
+  virtual void check (void *whole, void *base);
+};
+D::D ()
+{
+  check (this, this);
+}
+D::~D ()
+{
+  check (this, this);
+}
+void D::check (void *whole, void *base)
+{
+  if (dynamic_cast <void *> (this) != whole)
+    fail (5);
+  else if (this != base)
+    fail (6);
+  A::check (whole, static_cast <A *> (this));
+}
+
+struct E : virtual public C, virtual public D
+{
+  virtual ~E ();
+  E ();
+  virtual void check (void *whole, void *base);
+};
+E::E ()
+{
+  check (this, this);
+}
+E::~E ()
+{
+  check (this, this);
+}
+void E::check (void *whole, void *base)
+{
+  if (dynamic_cast <void *> (this) != whole)
+    fail (5);
+  else if (this != base)
+    fail (6);
+  C::check (whole, static_cast <C *> (this));
+  D::check (whole, static_cast <D *> (this));
+}
+
+struct F : virtual public E
+{
+  virtual ~F ();
+  F ();
+  virtual void check (void *whole, void *base);
+};
+F::F ()
+{
+  check (this, this);
+}
+F::~F ()
+{
+  check (this, this);
+}
+void F::check (void *whole, void *base)
+{
+  if (dynamic_cast <void *> (this) != whole)
+    fail (5);
+  else if (this != base)
+    fail (6);
+  E::check (whole, static_cast <F *> (this));
+}
+
+int main ()
+{
+  A a;
+  B b;
+  C c;
+  D d;
+  E e;
+  F f;
+  
+  return failed;
+}