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++ PATH for more class.c cleanup



Here's another round of cleanups, including fixing the bogus assert
Graham spotted.

Now, finish_struct_1 is actually separated into semantic processing
(i.e., what errors should we issue, what implicitly generated members
do we need, etc.) and ABI-specific issues like class-layout,
placemenent of virtual function tables, etc.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

1999-12-16  Mark Mitchell  <mark@codesourcery.com>

	* class.c (check_field_decls): Don't return a value.
	(avoid_overlap): Moved here from tree.c.
	(build_base_fields): Likewise.
	(check_bases): New function, split out from finish_base_struct.
	(check_bases_and_members): New function, split out from 
	finish_struct_1.
	(struct base_info): Remove cant_have_default_ctor,
	cant_have_const_ctor, cant_have_asn_ref.
	(finish_base_struct): Split semantic analysis into check_bases.
	(finish_struct_methods): Fix bogus assertion.
	(check_field_decls): Call finish_struct_anon here.
	(build_vbase_pointer_fields): Use CLASSTYPE_N_BASECLASSES.
	(finish_struct_1): Use check_bases_and_members.  Reorganize.
	* cp-tree.h (CLASSTYPE_VBASECLASSES): Improve documentation.
	(build_base_fields): Don't declare.
	* tree.c (avoid_overlap): Remove.
	(build_base_fields): Likewise.

Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.206
diff -c -p -r1.206 class.c
*** class.c	1999/12/16 03:10:12	1.206
--- class.c	1999/12/16 22:03:27
*************** static int count_fields PROTO((tree));
*** 123,134 ****
  static int add_fields_to_vec PROTO((tree, tree, int));
  static void check_bitfield_decl PROTO((tree));
  static void check_field_decl PROTO((tree, tree, int *, int *, int *, int *));
! static tree* check_field_decls PROTO((tree, tree *, int *, int *, int *, 
! 				      int *));
  static tree build_vbase_pointer_fields PROTO((tree, int *));
  static tree build_vtbl_or_vbase_field PROTO((tree, tree, tree, tree, int *));
  static void check_methods PROTO((tree));
  static void remove_zero_width_bit_fields PROTO((tree));
  
  /* Variables shared between class.c and call.c.  */
  
--- 123,138 ----
  static int add_fields_to_vec PROTO((tree, tree, int));
  static void check_bitfield_decl PROTO((tree));
  static void check_field_decl PROTO((tree, tree, int *, int *, int *, int *));
! static void check_field_decls PROTO((tree, tree *, int *, int *, int *, 
! 				     int *));
! static int avoid_overlap PROTO((tree, tree, int *));
! static tree build_base_fields PROTO((tree, int *));
  static tree build_vbase_pointer_fields PROTO((tree, int *));
  static tree build_vtbl_or_vbase_field PROTO((tree, tree, tree, tree, int *));
  static void check_methods PROTO((tree));
  static void remove_zero_width_bit_fields PROTO((tree));
+ static void check_bases PROTO((tree, int *, int *, int *));
+ static void check_bases_and_members PROTO((tree, int *));
  
  /* Variables shared between class.c and call.c.  */
  
*************** struct base_info
*** 1486,1537 ****
    tree vfield;
    tree vfields;
    tree rtti;
-   char cant_have_default_ctor;
-   char cant_have_const_ctor;
-   char no_const_asn_ref;
  };
  
! /* Record information about type T derived from its base classes.
!    Store most of that information in T itself, and place the
!    remaining information in the struct BASE_INFO.
! 
!    Propagate basetype offsets throughout the lattice.  Note that the
!    lattice topped by T is really a pair: it's a DAG that gives the
!    structure of the derivation hierarchy, and it's a list of the
!    virtual baseclasses that appear anywhere in the DAG.  When a vbase
!    type appears in the DAG, it's offset is 0, and it's children start
!    their offsets from that point.  When a vbase type appears in the list,
!    its offset is the offset it has in the hierarchy, and its children's
!    offsets include that offset in theirs.
  
!    Returns the index of the first base class to have virtual functions,
!    or -1 if no such base class.  */
! 
! static int
! finish_base_struct (t, b)
       tree t;
!      struct base_info *b;
  {
!   tree binfos = TYPE_BINFO_BASETYPES (t);
!   int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
!   int first_vfn_base_index = -1;
!   bzero ((char *) b, sizeof (struct base_info));
  
!   for (i = 0; i < n_baseclasses; i++)
!     {
!       tree base_binfo = TREE_VEC_ELT (binfos, i);
!       tree basetype = BINFO_TYPE (base_binfo);
  
!       /* Effective C++ rule 14.  We only need to check TYPE_VIRTUAL_P
! 	 here because the case of virtual functions but non-virtual
! 	 dtor is handled in finish_struct_1.  */
!       if (warn_ecpp && ! TYPE_VIRTUAL_P (basetype)
! 	  && TYPE_HAS_DESTRUCTOR (basetype))
! 	cp_warning ("base class `%#T' has a non-virtual destructor", basetype);
  
!       /* If the type of basetype is incomplete, then
! 	 we already complained about that fact
! 	 (and we should have fixed it up as well).  */
        if (TYPE_SIZE (basetype) == 0)
  	{
  	  int j;
--- 1490,1532 ----
    tree vfield;
    tree vfields;
    tree rtti;
  };
  
! /* Run through the base clases of T, updating
!    CANT_HAVE_DEFAULT_CTOR_P, CANT_HAVE_CONST_CTOR_P, and
!    NO_CONST_ASN_REF_P.  Also set flag bits in T based on properties of
!    the bases.  */
  
! static void
! check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
! 	     no_const_asn_ref_p)
       tree t;
!      int *cant_have_default_ctor_p;
!      int *cant_have_const_ctor_p;
!      int *no_const_asn_ref_p;
  {
!   int n_baseclasses;
!   int i;
!   tree binfos;
  
!   binfos = TYPE_BINFO_BASETYPES (t);
!   n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
  
!   /* An aggregate cannot have baseclasses.  */
!   CLASSTYPE_NON_AGGREGATE (t) |= (n_baseclasses != 0);
! 
!   for (i = 0; i < n_baseclasses; ++i) 
!     {
!       tree base_binfo;
!       tree basetype;
  
!       /* Figure out what base we're looking at.  */
!       base_binfo = TREE_VEC_ELT (binfos, i);
!       basetype = TREE_TYPE (base_binfo);
! 
!       /* If the type of basetype is incomplete, then we already
! 	 complained about that fact (and we should have fixed it up as
! 	 well).  */
        if (TYPE_SIZE (basetype) == 0)
  	{
  	  int j;
*************** finish_base_struct (t, b)
*** 1544,1558 ****
  	  n_baseclasses -= 1;
  	  for (j = i; j+1 < n_baseclasses; j++)
  	    TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1);
  	}
  
!       if (! TYPE_HAS_CONST_INIT_REF (basetype))
! 	b->cant_have_const_ctor = 1;
  
        if (TYPE_HAS_CONSTRUCTOR (basetype)
  	  && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype))
  	{
! 	  b->cant_have_default_ctor = 1;
  	  if (! TYPE_HAS_CONSTRUCTOR (t))
  	    {
  	      cp_pedwarn ("base `%T' with only non-default constructor",
--- 1539,1571 ----
  	  n_baseclasses -= 1;
  	  for (j = i; j+1 < n_baseclasses; j++)
  	    TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1);
+ 	  continue;
  	}
  
!       /* Effective C++ rule 14.  We only need to check TYPE_VIRTUAL_P
! 	 here because the case of virtual functions but non-virtual
! 	 dtor is handled in finish_struct_1.  */
!       if (warn_ecpp && ! TYPE_VIRTUAL_P (basetype)
! 	  && TYPE_HAS_DESTRUCTOR (basetype))
! 	cp_warning ("base class `%#T' has a non-virtual destructor",
! 		    basetype);
  
+       /* If the base class doesn't have copy constructors or
+ 	 assignment operators that take const references, then the
+ 	 derived class cannot have such a member automatically
+ 	 generated.  */
+       if (! TYPE_HAS_CONST_INIT_REF (basetype))
+ 	*cant_have_const_ctor_p = 1;
+       if (TYPE_HAS_ASSIGN_REF (basetype)
+ 	  && !TYPE_HAS_CONST_ASSIGN_REF (basetype))
+ 	*no_const_asn_ref_p = 1;
+       /* Similarly, if the base class doesn't have a default
+ 	 constructor, then the derived class won't have an
+ 	 automatically generated default constructor.  */
        if (TYPE_HAS_CONSTRUCTOR (basetype)
  	  && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype))
  	{
! 	  *cant_have_default_ctor_p = 1;
  	  if (! TYPE_HAS_CONSTRUCTOR (t))
  	    {
  	      cp_pedwarn ("base `%T' with only non-default constructor",
*************** finish_base_struct (t, b)
*** 1561,1591 ****
  	    }
  	}
  
!       if (TYPE_HAS_ASSIGN_REF (basetype)
! 	  && !TYPE_HAS_CONST_ASSIGN_REF (basetype))
! 	b->no_const_asn_ref = 1;
! 
        TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
        TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype);
!       TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype);
        TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype);
- 
        TYPE_OVERLOADS_CALL_EXPR (t) |= TYPE_OVERLOADS_CALL_EXPR (basetype);
        TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype);
        TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype);
  
        if (CLASSTYPE_COM_INTERFACE (basetype))
  	{
- 	  CLASSTYPE_COM_INTERFACE (t) = 1;
- 	}
-       else if (CLASSTYPE_COM_INTERFACE (t) && i == 0)
- 	{
  	  cp_error 
  	    ("COM interface type `%T' with non-COM leftmost base class `%T'",
  	     t, basetype);
  	  CLASSTYPE_COM_INTERFACE (t) = 0;
  	}
  
        if (TYPE_VIRTUAL_P (basetype))
  	{
  	  /* Ensure that this is set from at least a virtual base
--- 1574,1635 ----
  	    }
  	}
  
!       /* A lot of properties from the bases also apply to the derived
! 	 class.  */
        TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
        TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype);
!       TYPE_HAS_COMPLEX_ASSIGN_REF (t) 
! 	|= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype);
        TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype);
        TYPE_OVERLOADS_CALL_EXPR (t) |= TYPE_OVERLOADS_CALL_EXPR (basetype);
        TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype);
        TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype);
  
+       /* Derived classes can implicitly become COMified if their bases
+ 	 are COM.  */
        if (CLASSTYPE_COM_INTERFACE (basetype))
+ 	CLASSTYPE_COM_INTERFACE (t) = 1;
+       else if (i == 0 && CLASSTYPE_COM_INTERFACE (t))
  	{
  	  cp_error 
  	    ("COM interface type `%T' with non-COM leftmost base class `%T'",
  	     t, basetype);
  	  CLASSTYPE_COM_INTERFACE (t) = 0;
  	}
+     }
+ }
  
+ /* Record information about type T derived from its base classes.
+    Store most of that information in T itself, and place the
+    remaining information in the struct BASE_INFO.
+ 
+    Propagate basetype offsets throughout the lattice.  Note that the
+    lattice topped by T is really a pair: it's a DAG that gives the
+    structure of the derivation hierarchy, and it's a list of the
+    virtual baseclasses that appear anywhere in the DAG.  When a vbase
+    type appears in the DAG, it's offset is 0, and it's children start
+    their offsets from that point.  When a vbase type appears in the list,
+    its offset is the offset it has in the hierarchy, and its children's
+    offsets include that offset in theirs.
+ 
+    Returns the index of the first base class to have virtual functions,
+    or -1 if no such base class.  */
+ 
+ static int
+ finish_base_struct (t, b)
+      tree t;
+      struct base_info *b;
+ {
+   tree binfos = TYPE_BINFO_BASETYPES (t);
+   int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
+   int first_vfn_base_index = -1;
+   bzero ((char *) b, sizeof (struct base_info));
+ 
+   for (i = 0; i < n_baseclasses; i++)
+     {
+       tree base_binfo = TREE_VEC_ELT (binfos, i);
+       tree basetype = BINFO_TYPE (base_binfo);
+ 
        if (TYPE_VIRTUAL_P (basetype))
  	{
  	  /* Ensure that this is set from at least a virtual base
*************** finish_struct_methods (t)
*** 2009,2016 ****
        return;
      }
  
-   my_friendly_assert (method_vec != NULL_TREE, 19991215);
    method_vec = CLASSTYPE_METHOD_VEC (t);
    len = TREE_VEC_LENGTH (method_vec);
  
    /* First fill in entry 0 with the constructors, entry 1 with destructors,
--- 2053,2060 ----
        return;
      }
  
    method_vec = CLASSTYPE_METHOD_VEC (t);
+   my_friendly_assert (method_vec != NULL_TREE, 19991215);
    len = TREE_VEC_LENGTH (method_vec);
  
    /* First fill in entry 0 with the constructors, entry 1 with destructors,
*************** check_field_decl (field, t, cant_have_co
*** 3387,3393 ****
     Returns a pointer to the end of the TYPE_FIELDs chain; additional
     fields can be added by adding to this chain.  */
  
! static tree*
  check_field_decls (t, access_decls, empty_p, 
  		   cant_have_default_ctor_p, cant_have_const_ctor_p,
  		   no_const_asn_ref_p)
--- 3431,3437 ----
     Returns a pointer to the end of the TYPE_FIELDs chain; additional
     fields can be added by adding to this chain.  */
  
! static void
  check_field_decls (t, access_decls, empty_p, 
  		   cant_have_default_ctor_p, cant_have_const_ctor_p,
  		   no_const_asn_ref_p)
*************** check_field_decls (t, access_decls, empt
*** 3606,3617 ****
  	cp_warning ("  but does not override `operator=(const %T&)'", t);
      }
  
    /* We've built up the list of access declarations in reverse order.
       Fix that now.  */
    *access_decls = nreverse (*access_decls);
- 
-   /* Return the last field.  */
-   return field;
  }
  
  /* Return a FIELD_DECL for a pointer-to-virtual-table or
--- 3650,3662 ----
  	cp_warning ("  but does not override `operator=(const %T&)'", t);
      }
  
+ 
+   /* Check anonymous struct/anonymous union fields.  */
+   finish_struct_anon (t);
+ 
    /* We've built up the list of access declarations in reverse order.
       Fix that now.  */
    *access_decls = nreverse (*access_decls);
  }
  
  /* Return a FIELD_DECL for a pointer-to-virtual-table or
*************** build_vbase_pointer_fields (rec, empty_p
*** 3662,3668 ****
       base classes.  */
    tree vbase_decls = NULL_TREE;
    tree binfos = TYPE_BINFO_BASETYPES (rec);
!   int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
    tree decl;
    int i;
  
--- 3707,3713 ----
       base classes.  */
    tree vbase_decls = NULL_TREE;
    tree binfos = TYPE_BINFO_BASETYPES (rec);
!   int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
    tree decl;
    int i;
  
*************** build_vbase_pointer_fields (rec, empty_p
*** 3725,3730 ****
--- 3770,3898 ----
    return vbase_decls;
  }
  
+ /* If the empty base field in DECL overlaps with a base of the same type in
+    NEWDECL, which is either another base field or the first data field of
+    the class, pad the base just before NEWDECL and return 1.  Otherwise,
+    return 0.  */
+ 
+ static int
+ avoid_overlap (decl, newdecl, empty_p)
+      tree decl, newdecl;
+      int *empty_p;
+ {
+   tree field;
+ 
+   if (newdecl == NULL_TREE
+       || ! types_overlap_p (TREE_TYPE (decl), TREE_TYPE (newdecl)))
+     return 0;
+ 
+   for (field = decl; TREE_CHAIN (field) && TREE_CHAIN (field) != newdecl;
+        field = TREE_CHAIN (field))
+     ;
+ 
+   DECL_SIZE (field) = integer_one_node;
+   /* The containing class cannot be empty; this field takes up space.  */
+   *empty_p = 0;
+ 
+   return 1;
+ }
+ 
+ /* Returns a list of fields to stand in for the base class subobjects
+    of REC.  These fields are later removed by layout_basetypes.  */
+ 
+ static tree
+ build_base_fields (rec, empty_p)
+      tree rec;
+      int *empty_p;
+ {
+   /* Chain to hold all the new FIELD_DECLs which stand in for base class
+      subobjects.  */
+   tree base_decls = NULL_TREE;
+   tree binfos = TYPE_BINFO_BASETYPES (rec);
+   int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
+   tree decl, nextdecl;
+   int i, saw_empty = 0;
+   unsigned int base_align = 0;
+ 
+   for (i = 0; i < n_baseclasses; ++i)
+     {
+       register tree base_binfo = TREE_VEC_ELT (binfos, i);
+       register tree basetype = BINFO_TYPE (base_binfo);
+ 
+       if (TYPE_SIZE (basetype) == 0)
+ 	/* This error is now reported in xref_tag, thus giving better
+ 	   location information.  */
+ 	continue;
+ 
+       if (TREE_VIA_VIRTUAL (base_binfo))
+ 	continue;
+ 
+       decl = build_lang_decl (FIELD_DECL, NULL_TREE, basetype);
+       DECL_ARTIFICIAL (decl) = 1;
+       DECL_FIELD_CONTEXT (decl) = DECL_CLASS_CONTEXT (decl) = rec;
+       DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
+       DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
+       TREE_CHAIN (decl) = base_decls;
+       base_decls = decl;
+ 
+       if (flag_new_abi && DECL_SIZE (decl) == integer_zero_node)
+ 	saw_empty = 1;
+       else
+ 	{
+ 	  /* The containing class is non-empty because it has a
+ 	     non-empty base class.  */
+ 	  *empty_p = 0;
+ 
+ 	  if (! flag_new_abi)
+ 	    {
+ 	      /* Brain damage for backwards compatibility.  For no
+ 		 good reason, the old layout_basetypes made every base
+ 		 at least as large as the alignment for the bases up
+ 		 to that point, gratuitously wasting space.  So we do
+ 		 the same thing here.  */
+ 	      base_align = MAX (base_align, DECL_ALIGN (decl));
+ 	      DECL_SIZE (decl)
+ 		= size_int (MAX (TREE_INT_CST_LOW (DECL_SIZE (decl)),
+ 				 (int) base_align));
+ 	    }
+ 	}
+     }
+ 
+   /* Reverse the list of fields so we allocate the bases in the proper
+      order.  */
+   base_decls = nreverse (base_decls);
+ 
+   /* In the presence of empty base classes, we run the risk of allocating
+      two objects of the same class on top of one another.  Avoid that.  */
+   if (flag_new_abi && saw_empty)
+     for (decl = base_decls; decl; decl = TREE_CHAIN (decl))
+       {
+ 	if (DECL_SIZE (decl) == integer_zero_node)
+ 	  {
+ 	    /* First step through the following bases until we find
+ 	       an overlap or a non-empty base.  */
+ 	    for (nextdecl = TREE_CHAIN (decl); nextdecl;
+ 		 nextdecl = TREE_CHAIN (nextdecl))
+ 	      {
+ 		if (avoid_overlap (decl, nextdecl, empty_p)
+ 		    || DECL_SIZE (nextdecl) != integer_zero_node)
+ 		  goto nextbase;
+ 	      }
+ 
+ 	    /* If we're still looking, also check against the first
+ 	       field.  */
+ 	    for (nextdecl = TYPE_FIELDS (rec);
+ 		 nextdecl && TREE_CODE (nextdecl) != FIELD_DECL;
+ 		 nextdecl = TREE_CHAIN (nextdecl))
+ 	      /* keep looking */;
+ 	    avoid_overlap (decl, nextdecl, empty_p);
+ 	  }
+       nextbase:;
+       }
+ 
+   return base_decls;
+ }
+ 
  /* Go through the TYPE_METHODS of T issuing any appropriate
     diagnostics, figuring out which methods override which other
     methods, and so forth.  Returns non-zero if this class has any
*************** remove_zero_width_bit_fields (t)
*** 3800,3805 ****
--- 3968,4047 ----
      }
  }
  
+ /* Check the validity of the bases and members declared in T.  Add any
+    implicitly-generated functions (like copy-constructors and
+    assignment operators).  Compute various flag bits (like
+    CLASSTYPE_NON_POD_T) for T.  This routine works purely at the C++
+    level: i.e., independently of the ABI in use.  */
+ 
+ static void
+ check_bases_and_members (t, empty_p)
+      tree t;
+      int *empty_p;
+ {
+   /* Nonzero if we are not allowed to generate a default constructor
+      for this case.  */
+   int cant_have_default_ctor;
+   /* Nonzero if the implicitly generated copy constructor should take
+      a non-const reference argument.  */
+   int cant_have_const_ctor;
+   /* Nonzero if the the implicitly generated assignment operator
+      should take a non-const reference argument.  */
+   int no_const_asn_ref;
+   tree access_decls;
+ 
+   /* By default, we use const reference arguments and generate default
+      constructors.  */
+   cant_have_default_ctor = 0;
+   cant_have_const_ctor = 0;
+   no_const_asn_ref = 0;
+ 
+   /* Check all the base-classes. */
+   check_bases (t, &cant_have_default_ctor, &cant_have_const_ctor,
+ 	       &no_const_asn_ref);
+ 
+   /* Check all the data member declarations.  */
+   check_field_decls (t, &access_decls, empty_p,
+ 		     &cant_have_default_ctor,
+ 		     &cant_have_const_ctor,
+ 		     &no_const_asn_ref);
+ 
+   /* Check all the method declarations.  */
+   check_methods (t);
+ 
+   /* Do some bookkeeping that will guide the generation of implicitly
+      declared member functions.  */
+   TYPE_HAS_COMPLEX_INIT_REF (t)
+     |= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t));
+   TYPE_NEEDS_CONSTRUCTING (t)
+     |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t));
+   CLASSTYPE_NON_AGGREGATE (t) |= TYPE_HAS_CONSTRUCTOR (t);
+   CLASSTYPE_NON_POD_P (t)
+     |= (CLASSTYPE_NON_AGGREGATE (t) || TYPE_HAS_DESTRUCTOR (t) 
+ 	|| TYPE_HAS_ASSIGN_REF (t));
+   TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t);
+   TYPE_HAS_COMPLEX_ASSIGN_REF (t)
+     |= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t);
+ 
+   /* Synthesize any needed methods.  Note that methods will be synthesized
+      for anonymous unions; grok_x_components undoes that.  */
+   add_implicitly_declared_members (t, cant_have_default_ctor,
+ 				   cant_have_const_ctor,
+ 				   no_const_asn_ref);
+ 
+   /* Build and sort the CLASSTYPE_METHOD_VEC.  */
+   finish_struct_methods (t);
+ 
+   /* Process the access-declarations.  We wait until now to do this
+      because handle_using_decls requires that the CLASSTYPE_METHOD_VEC
+      be set up correctly.  */
+   while (access_decls)
+     {
+       handle_using_decl (TREE_VALUE (access_decls), t);
+       access_decls = TREE_CHAIN (access_decls);
+     }
+ }
+ 
  /* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
     (or C++ class declaration).
  
*************** void
*** 3831,3849 ****
  finish_struct_1 (t)
       tree t;
  {
-   tree fields;
    tree x;
-   tree *next_field;
    int has_virtual;
    int max_has_virtual;
    tree pending_virtuals = NULL_TREE;
    tree pending_hard_virtuals = NULL_TREE;
    tree vfield;
    tree vfields;
-   tree virtual_dtor;
-   int cant_have_default_ctor;
-   int cant_have_const_ctor;
-   int no_const_asn_ref;
    int n_fields = 0;
  
    /* The index of the first base class which has virtual
--- 4073,4085 ----
*************** finish_struct_1 (t)
*** 3851,3858 ****
    int first_vfn_base_index;
  
    int n_baseclasses;
-   tree access_decls;
-   int aggregate = 1;
    int empty = 1;
    tree inline_friends;
  
--- 4087,4092 ----
*************** finish_struct_1 (t)
*** 3874,3881 ****
--- 4108,4132 ----
    TYPE_SIZE (t) = NULL_TREE;
    CLASSTYPE_GOT_SEMICOLON (t) = 0;
  
+   first_vfn_base_index = -1;
+   has_virtual = 0;
+   max_has_virtual = 0;
+   vfield = NULL_TREE;
+   vfields = NULL_TREE;
+   CLASSTYPE_RTTI (t) = NULL_TREE;
    n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
  
+   /* Do end-of-class semantic processing: checking the validity of the
+      bases and members and adding implicitly generated methods.  */
+   check_bases_and_members (t, &empty);
+ 
+   /* Add pointers to all of our virtual base-classes.  */
+   TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (t, &empty),
+ 			     TYPE_FIELDS (t));
+   /* Build FIELD_DECLs for all of the non-virtual base-types.  */
+   TYPE_FIELDS (t) = chainon (build_base_fields (t, &empty), 
+ 			     TYPE_FIELDS (t));
+ 
    if (n_baseclasses > 0)
      {
        struct base_info base_info;
*************** finish_struct_1 (t)
*** 3890,3963 ****
        vfields = base_info.vfields;
        CLASSTYPE_VFIELDS (t) = vfields;
        CLASSTYPE_RTTI (t) = base_info.rtti;
-       cant_have_default_ctor = base_info.cant_have_default_ctor;
-       cant_have_const_ctor = base_info.cant_have_const_ctor;
-       no_const_asn_ref = base_info.no_const_asn_ref;
-       aggregate = 0;
-     }
-   else
-     {
-       first_vfn_base_index = -1;
-       has_virtual = 0;
-       max_has_virtual = 0;
-       vfield = NULL_TREE;
-       vfields = NULL_TREE;
-       CLASSTYPE_RTTI (t) = NULL_TREE;
-       cant_have_default_ctor = 0;
-       cant_have_const_ctor = 0;
-       no_const_asn_ref = 0;
-     }
- 
-   /* Check all the data member declarations.  */
-   next_field = check_field_decls (t, &access_decls, &empty,
- 				  &cant_have_default_ctor,
- 				  &cant_have_const_ctor,
- 				  &no_const_asn_ref);
- 
-   /* Add pointers to all of our virtual base-classes.  */
-   if (n_baseclasses)
-     TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (t, &empty),
- 			       TYPE_FIELDS (t));
- 
-   /* Build FIELD_DECLs for all of the non-virtual base-types.  */
-   fields = TYPE_FIELDS (t);
-   if (n_baseclasses)
-     {
-       TYPE_FIELDS (t) = chainon (build_base_fields (t), TYPE_FIELDS (t));
- 
-       /* If any base is non-empty, then we are non-empty.  */
-       for (x = TYPE_FIELDS (t); empty && x != fields; x = TREE_CHAIN (x))
- 	if (DECL_SIZE (x) != integer_zero_node)
- 	  empty = 0;
- 
-       fields = TYPE_FIELDS (t);
      }
  
-   /* Check all the method declarations.  */
-   check_methods (t);
- 
-   /* Do some bookkeeping that will guide the generation of implicitly
-      declared member functions.  */
-   TYPE_HAS_COMPLEX_INIT_REF (t)
-     |= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t));
-   TYPE_NEEDS_CONSTRUCTING (t)
-     |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t));
-   CLASSTYPE_NON_AGGREGATE (t)
-       = ! aggregate || TYPE_HAS_CONSTRUCTOR (t);
-   CLASSTYPE_NON_POD_P (t)
-     |= (CLASSTYPE_NON_AGGREGATE (t) || TYPE_HAS_DESTRUCTOR (t) 
- 	|| TYPE_HAS_ASSIGN_REF (t));
-   TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t);
-   TYPE_HAS_COMPLEX_ASSIGN_REF (t)
-     |= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t);
- 
-   /* Synthesize any needed methods.  Note that methods will be synthesized
-      for anonymous unions; grok_x_components undoes that.  */
-   virtual_dtor 
-     = add_implicitly_declared_members (t, cant_have_default_ctor,
- 				       cant_have_const_ctor,
- 				       no_const_asn_ref);
- 
    /* Loop over the virtual functions, adding them to our various
       vtables.  */
    for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
--- 4141,4148 ----
*************** finish_struct_1 (t)
*** 3965,3980 ****
        add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
  			    &has_virtual, x, t);
  
-   /* Build and sort the CLASSTYPE_METHOD_VEC.  */
-   finish_struct_methods (t);
- 
-   /* Process the access-declarations.  */
-   while (access_decls)
-     {
-       handle_using_decl (TREE_VALUE (access_decls), t);
-       access_decls = TREE_CHAIN (access_decls);
-     }
- 
    if (vfield == NULL_TREE && has_virtual)
      {
        /* We build this decl with vtbl_ptr_type_node, which is a
--- 4150,4155 ----
*************** finish_struct_1 (t)
*** 4002,4008 ****
  					  t,
  					  &empty);
        TYPE_VFIELD (t) = vfield;
!       *next_field = vfield;
        vfields = chainon (vfields, build_tree_list (NULL_TREE, t));
      }
  
--- 4177,4183 ----
  					  t,
  					  &empty);
        TYPE_VFIELD (t) = vfield;
!       TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), vfield);
        vfields = chainon (vfields, build_tree_list (NULL_TREE, t));
      }
  
*************** finish_struct_1 (t)
*** 4045,4052 ****
    else
      CLASSTYPE_SIZE (t) = TYPE_SIZE (t);
    CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t);
- 
-   finish_struct_anon (t);
  
    /* Set the TYPE_DECL for this type to contain the right
       value for DECL_OFFSET, so that we can use it as part
--- 4220,4225 ----
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.362
diff -c -p -r1.362 cp-tree.h
*** cp-tree.h	1999/12/16 03:10:12	1.362
--- cp-tree.h	1999/12/16 22:03:30
*************** struct lang_type
*** 1388,1394 ****
  /* The number of virtual functions defined for this
     _CLASSTYPE node.  */
  #define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize)
! /* The virtual base classes that this type uses.  */
  #define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases)
  /* The virtual function pointer fields that this type contains.  */
  #define CLASSTYPE_VFIELDS(NODE) (TYPE_LANG_SPECIFIC(NODE)->vfields)
--- 1388,1395 ----
  /* The number of virtual functions defined for this
     _CLASSTYPE node.  */
  #define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize)
! /* The direct and indirect virtual base classes that this type uses in
!    depth-first left-to-right order.  */
  #define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases)
  /* The virtual function pointer fields that this type contains.  */
  #define CLASSTYPE_VFIELDS(NODE) (TYPE_LANG_SPECIFIC(NODE)->vfields)
*************** extern tree build_cplus_method_type		PRO
*** 4012,4018 ****
  extern tree build_cplus_staticfn_type		PROTO((tree, tree, tree));
  extern tree build_cplus_array_type		PROTO((tree, tree));
  extern int layout_basetypes			PROTO((tree, int));
- extern tree build_base_fields			PROTO((tree));
  extern tree hash_tree_cons			PROTO((tree, tree, tree));
  extern tree hash_tree_chain			PROTO((tree, tree));
  extern tree hash_chainon			PROTO((tree, tree));
--- 4013,4018 ----
Index: method.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/method.c,v
retrieving revision 1.127
diff -c -p -r1.127 method.c
*** method.c	1999/11/14 20:29:03	1.127
--- method.c	1999/12/16 22:03:32
*************** static int is_back_referenceable_type PR
*** 98,103 ****
--- 98,104 ----
  static int check_btype PROTO((tree));
  static void build_mangled_name_for_type PROTO((tree));
  static void build_mangled_name_for_type_with_Gcode PROTO((tree, int));
+ static void fixup_pending_inline PROTO((struct pending_inline *));
  
  # define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0)
  # define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C)))
*************** init_method ()
*** 142,147 ****
--- 143,169 ----
     value.  */
  static char digit_buffer[128];
  
+ /* Fixup the inline function given by INFO now that the class is
+    complete.  */
+ 
+ static void
+ fixup_pending_inline (info)
+      struct pending_inline *info;
+ {
+   if (info)
+     {
+       tree args;
+       tree fn = info->fndecl;
+ 
+       args = DECL_ARGUMENTS (fn);
+       while (args)
+ 	{
+ 	  DECL_CONTEXT (args) = fn;
+ 	  args = TREE_CHAIN (args);
+ 	}
+     }
+ }
+ 
  /* Move inline function definitions out of structure so that they
     can be processed normally.  CNAME is the name of the class
     we are working from, METHOD_LIST is the list of method lists
*************** do_inline_function_hair (type, friend_li
*** 163,206 ****
        else
  	method = TREE_VEC_ELT (method, 2);
      }
- 
-   while (method)
-     {
-       /* Do inline member functions.  */
-       struct pending_inline *info = DECL_PENDING_INLINE_INFO (method);
-       if (info)
- 	{
- 	  tree args;
- 
- 	  my_friendly_assert (info->fndecl == method, 238);
- 	  args = DECL_ARGUMENTS (method);
- 	  while (args)
- 	    {
- 	      DECL_CONTEXT (args) = method;
- 	      args = TREE_CHAIN (args);
- 	    }
- 	}
-       method = TREE_CHAIN (method);
-     }
-   while (friend_list)
-     {
-       tree fndecl = TREE_VALUE (friend_list);
-       struct pending_inline *info = DECL_PENDING_INLINE_INFO (fndecl);
-       if (info)
- 	{
- 	  tree args;
  
! 	  my_friendly_assert (info->fndecl == fndecl, 239);
! 	  args = DECL_ARGUMENTS (fndecl);
! 	  while (args)
! 	    {
! 	      DECL_CONTEXT (args) = fndecl;
! 	      args = TREE_CHAIN (args);
! 	    }
! 	}
! 
!       friend_list = TREE_CHAIN (friend_list);
!     }
  }
  
  /* Here is where overload code starts.  */
--- 185,198 ----
        else
  	method = TREE_VEC_ELT (method, 2);
      }
  
!   /* Do inline member functions.  */
!   for (; method; method = TREE_CHAIN (method))
!     fixup_pending_inline (DECL_PENDING_INLINE_INFO (method));
! 
!   /* Do friends.  */
!   for (; friend_list; friend_list = TREE_CHAIN (friend_list))
!     fixup_pending_inline (DECL_PENDING_INLINE_INFO (TREE_VALUE (friend_list)));
  }
  
  /* Here is where overload code starts.  */
Index: tree.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/tree.c,v
retrieving revision 1.170
diff -c -p -r1.170 tree.c
*** tree.c	1999/12/16 03:10:12	1.170
--- tree.c	1999/12/16 22:03:34
*************** static void list_hash_add PROTO((int, tr
*** 38,44 ****
  static int list_hash PROTO((tree, tree, tree));
  static tree list_hash_lookup PROTO((int, tree, tree, tree));
  static void propagate_binfo_offsets PROTO((tree, tree));
- static int avoid_overlap PROTO((tree, tree));
  static cp_lvalue_kind lvalue_p_1 PROTO((tree, int));
  static tree no_linkage_helper PROTO((tree *, int *, void *));
  static tree build_srcloc PROTO((char *, int));
--- 38,43 ----
*************** layout_basetypes (rec, max)
*** 876,992 ****
      }
  
    return max;
- }
- 
- /* If the empty base field in DECL overlaps with a base of the same type in
-    NEWDECL, which is either another base field or the first data field of
-    the class, pad the base just before NEWDECL and return 1.  Otherwise,
-    return 0.  */
- 
- static int
- avoid_overlap (decl, newdecl)
-      tree decl, newdecl;
- {
-   tree field;
- 
-   if (newdecl == NULL_TREE
-       || ! types_overlap_p (TREE_TYPE (decl), TREE_TYPE (newdecl)))
-     return 0;
- 
-   for (field = decl; TREE_CHAIN (field) && TREE_CHAIN (field) != newdecl;
-        field = TREE_CHAIN (field))
-     ;
- 
-   DECL_SIZE (field) = integer_one_node;
- 
-   return 1;
- }
- 
- /* Returns a list of fields to stand in for the base class subobjects
-    of REC.  These fields are later removed by layout_basetypes.  */
- 
- tree
- build_base_fields (rec)
-      tree rec;
- {
-   /* Chain to hold all the new FIELD_DECLs which stand in for base class
-      subobjects.  */
-   tree base_decls = NULL_TREE;
-   tree binfos = TYPE_BINFO_BASETYPES (rec);
-   int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-   tree decl, nextdecl;
-   int i, saw_empty = 0;
-   unsigned int base_align = 0;
- 
-   for (i = 0; i < n_baseclasses; ++i)
-     {
-       register tree base_binfo = TREE_VEC_ELT (binfos, i);
-       register tree basetype = BINFO_TYPE (base_binfo);
- 
-       if (TYPE_SIZE (basetype) == 0)
- 	/* This error is now reported in xref_tag, thus giving better
- 	   location information.  */
- 	continue;
- 
-       if (TREE_VIA_VIRTUAL (base_binfo))
- 	continue;
- 
-       decl = build_lang_decl (FIELD_DECL, NULL_TREE, basetype);
-       DECL_ARTIFICIAL (decl) = 1;
-       DECL_FIELD_CONTEXT (decl) = DECL_CLASS_CONTEXT (decl) = rec;
-       DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
-       DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
-       TREE_CHAIN (decl) = base_decls;
-       base_decls = decl;
- 
-       if (! flag_new_abi)
- 	{
- 	  /* Brain damage for backwards compatibility.  For no good reason,
- 	     the old layout_basetypes made every base at least as large as
- 	     the alignment for the bases up to that point, gratuitously
- 	     wasting space.  So we do the same thing here.  */
- 	  base_align = MAX (base_align, DECL_ALIGN (decl));
- 	  DECL_SIZE (decl)
- 	    = size_int (MAX (TREE_INT_CST_LOW (DECL_SIZE (decl)),
- 			     (int) base_align));
- 	}
-       else if (DECL_SIZE (decl) == integer_zero_node)
- 	saw_empty = 1;
-     }
- 
-   /* Reverse the list of fields so we allocate the bases in the proper
-      order.  */
-   base_decls = nreverse (base_decls);
- 
-   /* In the presence of empty base classes, we run the risk of allocating
-      two objects of the same class on top of one another.  Avoid that.  */
-   if (flag_new_abi && saw_empty)
-     for (decl = base_decls; decl; decl = TREE_CHAIN (decl))
-       {
- 	if (DECL_SIZE (decl) == integer_zero_node)
- 	  {
- 	    /* First step through the following bases until we find
- 	       an overlap or a non-empty base.  */
- 	    for (nextdecl = TREE_CHAIN (decl); nextdecl;
- 		 nextdecl = TREE_CHAIN (nextdecl))
- 	      {
- 		if (avoid_overlap (decl, nextdecl)
- 		    || DECL_SIZE (nextdecl) != integer_zero_node)
- 		  goto nextbase;
- 	      }
- 
- 	    /* If we're still looking, also check against the first
- 	       field.  */
- 	    for (nextdecl = TYPE_FIELDS (rec);
- 		 nextdecl && TREE_CODE (nextdecl) != FIELD_DECL;
- 		 nextdecl = TREE_CHAIN (nextdecl))
- 	      /* keep looking */;
- 	    avoid_overlap (decl, nextdecl);
- 	  }
-       nextbase:;
-       }
- 
-   return base_decls;
  }
  
  
--- 875,880 ----


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