This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[C++ PATCH]: Fix bug 1944


Hi,
I've installed the attached patch for bug 1944 on both mainline and branch.
Some classes which should be nearly empty were not (an ABI breakage).
And we weren't setting some internal flags properly (an internal inconsistency).

built & tested on i686-pc-linux-gnu, approved by Mark.

nathan
-- 
Dr Nathan Sidwell   ::   http://www.codesourcery.com   ::   CodeSourcery LLC
         'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2001-04-11  Nathan Sidwell  <nathan@codesourcery.com>

	* class.c (dfs_unshared_virtual_bases): New function.
	(mark_primary_bases): Call it.
	(check_bases): Ignore virtual bases when determining
	nearly-emptiness.

2001-04-11  Nathan Sidwell  <nathan@codesourcery.com>

	* g++.old-deja/g++.abi/primary3.C (main): Correct expected layout.

Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.358.2.13
diff -c -3 -p -r1.358.2.13 class.c
*** class.c	2001/04/10 18:06:54	1.358.2.13
--- class.c	2001/04/12 07:36:34
*************** static void build_vcall_and_vbase_vtbl_e
*** 190,195 ****
--- 190,196 ----
  							vtbl_init_data *));
  static void force_canonical_binfo_r PARAMS ((tree, tree, tree, tree));
  static void force_canonical_binfo PARAMS ((tree, tree, tree, tree));
+ static tree dfs_unshared_virtual_bases PARAMS ((tree, void *));
  static void mark_primary_bases PARAMS ((tree));
  static tree mark_primary_virtual_base PARAMS ((tree, tree, tree));
  static void clone_constructors_and_destructors PARAMS ((tree));
*************** check_bases (t, cant_have_default_ctor_p
*** 1597,1608 ****
  {
    int n_baseclasses;
    int i;
!   int seen_nearly_empty_base_p;
    tree binfos;
  
    binfos = TYPE_BINFO_BASETYPES (t);
    n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
!   seen_nearly_empty_base_p = 0;
  
    /* An aggregate cannot have baseclasses.  */
    CLASSTYPE_NON_AGGREGATE (t) |= (n_baseclasses != 0);
--- 1598,1609 ----
  {
    int n_baseclasses;
    int i;
!   int seen_non_virtual_nearly_empty_base_p;
    tree binfos;
  
    binfos = TYPE_BINFO_BASETYPES (t);
    n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
!   seen_non_virtual_nearly_empty_base_p = 0;
  
    /* An aggregate cannot have baseclasses.  */
    CLASSTYPE_NON_AGGREGATE (t) |= (n_baseclasses != 0);
*************** check_bases (t, cant_have_default_ctor_p
*** 1663,1681 ****
                          basetype);
  	}
  
!       /* If the base class is not empty or nearly empty, then this
! 	 class cannot be nearly empty.  */
!       if (!CLASSTYPE_NEARLY_EMPTY_P (basetype) && !is_empty_class (basetype))
! 	CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
!       /* And if there is more than one nearly empty base, then the
! 	 derived class is not nearly empty either.  */
!       else if (CLASSTYPE_NEARLY_EMPTY_P (basetype) 
! 	       && seen_nearly_empty_base_p)
! 	CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
!       /* If this is the first nearly empty base class, then remember
! 	 that we saw it.  */
        else if (CLASSTYPE_NEARLY_EMPTY_P (basetype))
! 	seen_nearly_empty_base_p = 1;
  
        /* A lot of properties from the bases also apply to the derived
  	 class.  */
--- 1664,1686 ----
                          basetype);
  	}
  
!       if (TREE_VIA_VIRTUAL (base_binfo))
! 	/* A virtual base does not effect nearly emptiness. */
! 	;
        else if (CLASSTYPE_NEARLY_EMPTY_P (basetype))
! 	{
! 	  if (seen_non_virtual_nearly_empty_base_p)
! 	    /* And if there is more than one nearly empty base, then the
! 	       derived class is not nearly empty either.  */
! 	    CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
! 	  else
! 	    /* Remember we've seen one. */
! 	    seen_non_virtual_nearly_empty_base_p = 1;
! 	}
!       else if (!is_empty_class (basetype))
! 	/* If the base class is not empty or nearly empty, then this
! 	   class cannot be nearly empty.  */
! 	CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
  
        /* A lot of properties from the bases also apply to the derived
  	 class.  */
*************** mark_primary_virtual_base (binfo, base_b
*** 1815,1820 ****
--- 1820,1842 ----
    return base_binfo;
  }
  
+ /* If BINFO is an unmarked virtual binfo for a class with a primary
+    base, then BINFO has no primary base in this graph.  Called from
+    mark_primary_bases. */
+ 
+ static tree dfs_unshared_virtual_bases (binfo, data)
+      tree binfo;
+      void *data;
+ {
+   if (TREE_VIA_VIRTUAL (binfo) && !BINFO_MARKED (binfo)
+       && CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
+     BINFO_LOST_PRIMARY_P (binfo) = 1;
+ 
+   CLEAR_BINFO_MARKED (binfo);
+   
+   return NULL;
+ }
+ 
  /* Set BINFO_PRIMARY_BASE_OF for all binfos in the hierarchy
     dominated by TYPE that are primary bases.  */
  
*************** mark_primary_bases (type)
*** 1840,1846 ****
--- 1862,1873 ----
  
        if (base_binfo)
          BINFO_PRIMARY_BASE_OF (base_binfo) = binfo;
+       SET_BINFO_MARKED (binfo);
      }
+   /* There could remain unshared 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);
  }
  
  /* Make the BINFO the primary base of T.  */
Index: testsuite/g++.old-deja/g++.abi/primary3.C
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/g++.old-deja/g++.abi/primary3.C,v
retrieving revision 1.1
diff -c -3 -p -r1.1 primary3.C
*** primary3.C	2001/02/05 11:45:16	1.1
--- primary3.C	2001/04/11 14:57:20
*************** int main ()
*** 21,34 ****
    A *apd = &d;
    B1 *b1pd = &d;
    B2 *b2pd = &d;
    
  #if __GXX_ABI_VERSION >= 100
    if (static_cast <void *> (apc) != static_cast <void *> (b1pc))
      return 1;
!   if (static_cast <void *> (apd) != static_cast <void *> (b1pd))
      return 2;
!   if (static_cast <void *> (apd) != static_cast <void *> (&d))
      return 3;
  #endif
    return 0;
  }
--- 21,44 ----
    A *apd = &d;
    B1 *b1pd = &d;
    B2 *b2pd = &d;
+   C *cpd = &d;
    
  #if __GXX_ABI_VERSION >= 100
    if (static_cast <void *> (apc) != static_cast <void *> (b1pc))
      return 1;
!   if (static_cast <void *> (&c) != static_cast <void *> (b2pc))
      return 2;
!   if (static_cast <void *> (b1pc) == static_cast <void *> (b2pc))
      return 3;
+   
+   if (static_cast <void *> (apd) != static_cast <void *> (b1pd))
+     return 11;
+   if (static_cast <void *> (b2pd) != static_cast <void *> (&d))
+     return 12;
+   if (static_cast <void *> (b2pd) != static_cast <void *> (cpd))
+     return 13;
+   if (static_cast <void *> (b1pd) == static_cast <void *> (b2pd))
+     return 14;
  #endif
    return 0;
  }
// Build don't link:
// 
// Copyright (C) 2001 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 11 Apr 2001 <nathan@codesourcery.com>

// Bug 1944. We failed to calculate nearly emptiness properly, and
// lost primary too.

struct A1 {};
struct A2 {};

struct B1 : virtual A1 {};
struct B2 : virtual A2 {};

struct C1 : virtual B2 {};
struct C2 : virtual B2 {};

struct D1 : virtual C1, virtual C2 {};
struct D2 : virtual C2, virtual B1 {};

struct E : virtual D1, virtual D2 {};

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]