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]

Oops: patch resend



Jason pointed out that I sent a message about more class.c cleanups,
but forgot to attach the patch.  Here it is.

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

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

	* class.c (handle_using_decl): Get TYPE_FIELDS and TYPE_METHODS
	out of the class, rather than taking them as parameters.
	(build_vbase_pointer_fields): Move here from tree.c.
	(build_vtbl_or_vbase_field): New function.
	(check_methods): Likewise.
	(remove_zero_width_bitfields): Likewise.
	(add_virtual_function): Use tree_cons instead of temp_tree_cons.
	(delete_duplicate_fields_1): Tidy.  Don't delete duplicate
	USING_DECLs here.
	(finish_struct_methods): Handle the case where there are no
	methods here.
	(get_basefndecls): Use tree_cons instead of temp_tree_cons.
	(check_field_decls): Call delete_duplicate_fields here.
	(finish_struct_1): Tidy.  Use check_methods and
	remove_zero_width_bitfields.
	* cp-tree.h (build_vbase_pointer_fields): Remove.
	* decl.c (grokdeclarator): Use tree_cons instead of
	temp_tree_cons.
	* decl2.c (qualified_lookup_using_namespace): Use tree_cons
	instead of temp_tree_cons.
	* lex.c (cons_up_default_function): Remove dead code.
	* method.c (fixup_pending_inline): New function, split out from	...
	(do_inline_function_hair): ... here.
	* tree.c (build_vbase_pointer_fields): Remove.
	
Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.205
diff -c -p -r1.205 class.c
*** class.c	1999/12/15 00:36:57	1.205
--- class.c	1999/12/16 02:46:38
*************** static tree delete_duplicate_fields_1 PR
*** 94,100 ****
  static void delete_duplicate_fields PROTO((tree));
  static void finish_struct_bits PROTO((tree, int));
  static int alter_access PROTO((tree, tree, tree, tree));
! static void handle_using_decl PROTO((tree, tree, tree, tree));
  static int overrides PROTO((tree, tree));
  static int strictly_overrides PROTO((tree, tree));
  static void merge_overrides PROTO((tree, tree, int, tree));
--- 94,100 ----
  static void delete_duplicate_fields PROTO((tree));
  static void finish_struct_bits PROTO((tree, int));
  static int alter_access PROTO((tree, tree, tree, tree));
! static void handle_using_decl PROTO((tree, tree));
  static int overrides PROTO((tree, tree));
  static int strictly_overrides PROTO((tree, tree));
  static void merge_overrides PROTO((tree, tree, int, tree));
*************** static void check_bitfield_decl PROTO((t
*** 125,130 ****
--- 125,133 ----
  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 remove_zero_width_bit_fields PROTO((tree));
  
  /* Variables shared between class.c and call.c.  */
  
*************** add_virtual_function (pv, phv, has_virtu
*** 1049,1057 ****
      {
        /* Need an entry in some other virtual function table.
           Deal with this after we have laid out our virtual base classes.  */
!       pending_hard_virtuals = temp_tree_cons (NULL_TREE, 
! 					      fndecl, 
! 					      pending_hard_virtuals);
      }
    *pv = pending_virtuals;
    *phv = pending_hard_virtuals;
--- 1052,1060 ----
      {
        /* Need an entry in some other virtual function table.
           Deal with this after we have laid out our virtual base classes.  */
!       pending_hard_virtuals = tree_cons (NULL_TREE, 
! 					 fndecl, 
! 					 pending_hard_virtuals);
      }
    *pv = pending_virtuals;
    *phv = pending_hard_virtuals;
*************** delete_duplicate_fields_1 (field, fields
*** 1289,1331 ****
  		    TREE_CHAIN (prev) = TREE_CHAIN (x);
  		}
  	    }
! 	  else
  	    {
! 	      if (DECL_NAME (field) == DECL_NAME (x))
  		{
! 		  if (TREE_CODE (field) == CONST_DECL
! 		      && TREE_CODE (x) == CONST_DECL)
! 		    cp_error_at ("duplicate enum value `%D'", x);
! 		  else if (TREE_CODE (field) == CONST_DECL
! 			   || TREE_CODE (x) == CONST_DECL)
! 		    cp_error_at ("duplicate field `%D' (as enum and non-enum)",
! 				x);
! 		  else if (DECL_DECLARES_TYPE_P (field)
! 			   && DECL_DECLARES_TYPE_P (x))
! 		    {
! 		      if (same_type_p (TREE_TYPE (field), TREE_TYPE (x)))
! 			continue;
! 		      cp_error_at ("duplicate nested type `%D'", x);
! 		    }
! 		  else if (DECL_DECLARES_TYPE_P (field)
! 			   || DECL_DECLARES_TYPE_P (x))
! 		    {
! 		      /* Hide tag decls.  */
! 		      if ((TREE_CODE (field) == TYPE_DECL
! 			   && DECL_ARTIFICIAL (field))
! 			  || (TREE_CODE (x) == TYPE_DECL
! 			      && DECL_ARTIFICIAL (x)))
! 			continue;
! 		      cp_error_at ("duplicate field `%D' (as type and non-type)",
! 				   x);
! 		    }
! 		  else
! 		    cp_error_at ("duplicate member `%D'", x);
! 		  if (prev == 0)
! 		    fields = TREE_CHAIN (fields);
! 		  else
! 		    TREE_CHAIN (prev) = TREE_CHAIN (x);
  		}
  	    }
  	}
      }
--- 1292,1337 ----
  		    TREE_CHAIN (prev) = TREE_CHAIN (x);
  		}
  	    }
! 	  else if (TREE_CODE (field) == USING_DECL)
! 	    /* A using declaration may is allowed to appear more than
! 	       once.  We'll prune these from the field list later, and
! 	       handle_using_decl will complain about invalid multiple
! 	       uses.  */
! 	    ;
! 	  else if (DECL_NAME (field) == DECL_NAME (x))
  	    {
! 	      if (TREE_CODE (field) == CONST_DECL
! 		  && TREE_CODE (x) == CONST_DECL)
! 		cp_error_at ("duplicate enum value `%D'", x);
! 	      else if (TREE_CODE (field) == CONST_DECL
! 		       || TREE_CODE (x) == CONST_DECL)
! 		cp_error_at ("duplicate field `%D' (as enum and non-enum)",
! 			     x);
! 	      else if (DECL_DECLARES_TYPE_P (field)
! 		       && DECL_DECLARES_TYPE_P (x))
  		{
! 		  if (same_type_p (TREE_TYPE (field), TREE_TYPE (x)))
! 		    continue;
! 		  cp_error_at ("duplicate nested type `%D'", x);
  		}
+ 	      else if (DECL_DECLARES_TYPE_P (field)
+ 		       || DECL_DECLARES_TYPE_P (x))
+ 		{
+ 		  /* Hide tag decls.  */
+ 		  if ((TREE_CODE (field) == TYPE_DECL
+ 		       && DECL_ARTIFICIAL (field))
+ 		      || (TREE_CODE (x) == TYPE_DECL
+ 			  && DECL_ARTIFICIAL (x)))
+ 		    continue;
+ 		  cp_error_at ("duplicate field `%D' (as type and non-type)",
+ 			       x);
+ 		}
+ 	      else
+ 		cp_error_at ("duplicate member `%D'", x);
+ 	      if (prev == 0)
+ 		fields = TREE_CHAIN (fields);
+ 	      else
+ 		TREE_CHAIN (prev) = TREE_CHAIN (x);
  	    }
  	}
      }
*************** alter_access (t, binfo, fdecl, access)
*** 1379,1393 ****
    return 0;
  }
  
! /* Process the USING_DECL, which is a member of T.  The METHOD_VEC, if
!    non-NULL, is the methods of T.  The FIELDS are the fields of T.  */
  
  static void
! handle_using_decl (using_decl, t, method_vec, fields)
       tree using_decl;
       tree t;
-      tree method_vec;
-      tree fields;
  {
    tree ctype = DECL_INITIAL (using_decl);
    tree name = DECL_NAME (using_decl);
--- 1385,1396 ----
    return 0;
  }
  
! /* Process the USING_DECL, which is a member of T.  */
  
  static void
! handle_using_decl (using_decl, t)
       tree using_decl;
       tree t;
  {
    tree ctype = DECL_INITIAL (using_decl);
    tree name = DECL_NAME (using_decl);
*************** handle_using_decl (using_decl, t, method
*** 1397,1402 ****
--- 1400,1407 ----
      : access_public_node;
    tree fdecl, binfo;
    tree flist = NULL_TREE;
+   tree fields = TYPE_FIELDS (t);
+   tree method_vec = CLASSTYPE_METHOD_VEC (t);
    tree tmp;
    int i;
    int n_methods;
*************** finish_struct_methods (t)
*** 1989,1997 ****
       tree t;
  {
    tree fn_fields;
!   tree method_vec = CLASSTYPE_METHOD_VEC (t);
    tree ctor_name = constructor_name (t);
!   int slot, len = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
  
    /* First fill in entry 0 with the constructors, entry 1 with destructors,
       and the next few with type conversion operators (if any).  */
--- 1994,2016 ----
       tree t;
  {
    tree fn_fields;
!   tree method_vec;
    tree ctor_name = constructor_name (t);
!   int slot, len;
! 
!   if (!TYPE_METHODS (t))
!     {
!       /* Clear these for safety; perhaps some parsing error could set
! 	 these incorrectly.  */
!       TYPE_HAS_CONSTRUCTOR (t) = 0;
!       TYPE_HAS_DESTRUCTOR (t) = 0;
!       CLASSTYPE_METHOD_VEC (t) = NULL_TREE;
!       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,
       and the next few with type conversion operators (if any).  */
*************** finish_struct_methods (t)
*** 2051,2059 ****
       no methods, then some public defaults are generated.  */
    maybe_warn_about_overly_private_class (t);
  
-   if (method_vec == NULL_TREE)
-     return;
- 
    /* Now sort the methods.  */
    while (len > 2 && TREE_VEC_ELT (method_vec, len-1) == NULL_TREE)
      len--;
--- 2070,2075 ----
*************** get_basefndecls (fndecl, t)
*** 2812,2818 ****
        if (TREE_CODE (methods) == FUNCTION_DECL
  	  && DECL_VINDEX (methods) != NULL_TREE
  	  && DECL_NAME (fndecl) == DECL_NAME (methods))
! 	base_fndecls = temp_tree_cons (fndecl, methods, base_fndecls);
  
        methods = TREE_CHAIN (methods);
      }
--- 2828,2834 ----
        if (TREE_CODE (methods) == FUNCTION_DECL
  	  && DECL_VINDEX (methods) != NULL_TREE
  	  && DECL_NAME (fndecl) == DECL_NAME (methods))
! 	base_fndecls = tree_cons (fndecl, methods, base_fndecls);
  
        methods = TREE_CHAIN (methods);
      }
*************** check_field_decls (t, access_decls, empt
*** 3386,3391 ****
--- 3402,3410 ----
    int has_pointers;
    int any_default_members;
  
+   /* First, delete any duplicate fields.  */
+   delete_duplicate_fields (TYPE_FIELDS (t));
+ 
    /* Assume there are no access declarations.  */
    *access_decls = NULL_TREE;
    /* Assume this class has no pointer members.  */
*************** check_field_decls (t, access_decls, empt
*** 3594,3599 ****
--- 3613,3804 ----
    return field;
  }
  
+ /* Return a FIELD_DECL for a pointer-to-virtual-table or
+    pointer-to-virtual-base.  The NAME, ASSEMBLER_NAME, and TYPE of the
+    field are as indicated.  The CLASS_TYPE in which this field occurs
+    is also indicated.  *EMPTY_P is set to a non-zero value by this
+    function to indicate that a class containing this field is
+    non-empty.  */
+ 
+ static tree
+ build_vtbl_or_vbase_field (name, assembler_name, type, class_type, 
+ 			   empty_p)
+      tree name;
+      tree assembler_name;
+      tree type;
+      tree class_type;
+      int *empty_p;
+ {
+   tree field;
+ 
+   /* This class is non-empty.  */
+   *empty_p = 0;
+ 
+   /* Build the FIELD_DECL.  */
+   field = build_lang_decl (FIELD_DECL, name, type);
+   DECL_ASSEMBLER_NAME (field) = assembler_name;
+   DECL_VIRTUAL_P (field) = 1;
+   DECL_ARTIFICIAL (field) = 1;
+   DECL_FIELD_CONTEXT (field) = class_type;
+   DECL_CLASS_CONTEXT (field) = class_type;
+   DECL_FCONTEXT (field) = class_type;
+   DECL_SAVED_INSNS (field) = 0;
+   DECL_FIELD_SIZE (field) = 0;
+   DECL_ALIGN (field) = TYPE_ALIGN (type);
+ 
+   /* Return it.  */
+   return field;
+ }
+ 
+ /* Returns list of virtual base class pointers in a FIELD_DECL chain.  */
+ 
+ static tree
+ build_vbase_pointer_fields (rec, empty_p)
+      tree rec;
+      int *empty_p;
+ {
+   /* Chain to hold all the new FIELD_DECLs which point at virtual
+      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;
+ 
+   /* Handle basetypes almost like fields, but record their
+      offsets differently.  */
+ 
+   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;
+ 
+       /* All basetypes are recorded in the association list of the
+ 	 derived type.  */
+ 
+       if (TREE_VIA_VIRTUAL (base_binfo))
+ 	{
+ 	  int j;
+ 	  const char *name;
+ 
+ 	  /* The offset for a virtual base class is only used in computing
+ 	     virtual function tables and for initializing virtual base
+ 	     pointers.  It is built once `get_vbase_types' is called.  */
+ 
+ 	  /* If this basetype can come from another vbase pointer
+ 	     without an additional indirection, we will share
+ 	     that pointer.  If an indirection is involved, we
+ 	     make our own pointer.  */
+ 	  for (j = 0; j < n_baseclasses; j++)
+ 	    {
+ 	      tree other_base_binfo = TREE_VEC_ELT (binfos, j);
+ 	      if (! TREE_VIA_VIRTUAL (other_base_binfo)
+ 		  && binfo_member (basetype,
+ 				   CLASSTYPE_VBASECLASSES (BINFO_TYPE
+ 							   (other_base_binfo))
+ 				   ))
+ 		goto got_it;
+ 	    }
+ 	  FORMAT_VBASE_NAME (name, basetype);
+ 	  decl = build_vtbl_or_vbase_field (get_identifier (name), 
+ 					    get_identifier (VTABLE_BASE),
+ 					    build_pointer_type (basetype),
+ 					    rec,
+ 					    empty_p);
+ 	  BINFO_VPTR_FIELD (base_binfo) = decl;
+ 	  TREE_CHAIN (decl) = vbase_decls;
+ 	  vbase_decls = decl;
+ 	  *empty_p = 0;
+ 
+ 	got_it:
+ 	  /* The space this decl occupies has already been accounted for.  */
+ 	  ;
+ 	}
+     }
+ 
+   return vbase_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
+    virtual methods.  */
+ 
+ static void
+ check_methods (t)
+      tree t;
+ {
+   tree x;
+   int has_virtual;
+ 
+   /* Assume there are no virtual methods.  */
+   has_virtual = 0;
+ 
+   for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
+     {
+       GNU_xref_member (current_class_name, x);
+ 
+       /* If this was an evil function, don't keep it in class.  */
+       if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
+ 	continue;
+ 
+       /* Do both of these, even though they're in the same union;
+ 	 if the insn `r' member and the size `i' member are
+ 	 different sizes, as on the alpha, the larger of the two
+ 	 will end up with garbage in it.  */
+       DECL_SAVED_INSNS (x) = 0;
+       DECL_FIELD_SIZE (x) = 0;
+ 
+       check_for_override (x, t);
+       if (DECL_ABSTRACT_VIRTUAL_P (x) && ! DECL_VINDEX (x))
+ 	cp_error_at ("initializer specified for non-virtual method `%D'", x);
+ 
+       /* The name of the field is the original field name
+ 	 Save this in auxiliary field for later overloading.  */
+       if (DECL_VINDEX (x))
+ 	{
+ 	  has_virtual = 1;
+ 	  if (DECL_ABSTRACT_VIRTUAL_P (x))
+ 	    CLASSTYPE_ABSTRACT_VIRTUALS (t)
+ 	      = tree_cons (NULL_TREE, x, CLASSTYPE_ABSTRACT_VIRTUALS (t));
+ 	}
+     }
+ 
+   /* A class with virtual functions needs constructing because, if
+      nothing else, the vtable pointer must be initialized.  */
+   TYPE_HAS_COMPLEX_INIT_REF (t) |= has_virtual;
+   TYPE_NEEDS_CONSTRUCTING (t) |= has_virtual;
+   /* [dcl.init.aggr]
+ 
+      An aggregate is a ... class ... with ... no virtual functions.  */
+   CLASSTYPE_NON_AGGREGATE (t) |= has_virtual;
+ }
+ 
+ /* Remove all zero-width bit-fields from T.  */
+ 
+ static void
+ remove_zero_width_bit_fields (t)
+      tree t;
+ {
+   tree *fieldsp;
+ 
+   fieldsp = &TYPE_FIELDS (t); 
+   while (*fieldsp)
+     {
+       if (TREE_CODE (*fieldsp) == FIELD_DECL
+ 	  && DECL_C_BIT_FIELD (*fieldsp) 
+ 	  && DECL_INITIAL (*fieldsp))
+ 	*fieldsp = TREE_CHAIN (*fieldsp);
+       else
+ 	fieldsp = &TREE_CHAIN (*fieldsp);
+     }
+ }
+ 
  /* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
     (or C++ class declaration).
  
*************** finish_struct_1 (t)
*** 3626,3638 ****
       tree t;
  {
    tree fields;
!   tree x, method_vec;
    tree *next_field;
    int has_virtual;
    int max_has_virtual;
    tree pending_virtuals = NULL_TREE;
    tree pending_hard_virtuals = NULL_TREE;
-   tree abstract_virtuals = NULL_TREE;
    tree vfield;
    tree vfields;
    tree virtual_dtor;
--- 3831,3842 ----
       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;
*************** finish_struct_1 (t)
*** 3646,3652 ****
    int first_vfn_base_index;
  
    int n_baseclasses;
-   int const_sans_init = 0;
    tree access_decls;
    int aggregate = 1;
    int empty = 1;
--- 3850,3855 ----
*************** finish_struct_1 (t)
*** 3670,3687 ****
    TYPE_SIZE (t) = NULL_TREE;
    CLASSTYPE_GOT_SEMICOLON (t) = 0;
  
!   /* Install struct as DECL_FIELD_CONTEXT of each field decl.
!      Also process specified field sizes.
!      Set DECL_FIELD_SIZE to the specified size, or 0 if none specified.
!      The specified size is found in the DECL_INITIAL.
!      Store 0 there, except for ": 0" fields (so we can find them
!      and delete them, below).  */
  
-   if (TYPE_BINFO_BASETYPES (t))
-     n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t));
-   else
-     n_baseclasses = 0;
- 
    if (n_baseclasses > 0)
      {
        struct base_info base_info;
--- 3873,3880 ----
    TYPE_SIZE (t) = NULL_TREE;
    CLASSTYPE_GOT_SEMICOLON (t) = 0;
  
!   n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
  
    if (n_baseclasses > 0)
      {
        struct base_info base_info;
*************** finish_struct_1 (t)
*** 3692,3698 ****
--- 3885,3893 ----
        has_virtual = base_info.has_virtual;
        max_has_virtual = base_info.max_has_virtual;
        vfield = base_info.vfield;
+       TYPE_VFIELD (t) = vfield;
        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;
*************** finish_struct_1 (t)
*** 3703,3709 ****
      {
        first_vfn_base_index = -1;
        has_virtual = 0;
!       max_has_virtual = has_virtual;
        vfield = NULL_TREE;
        vfields = NULL_TREE;
        CLASSTYPE_RTTI (t) = NULL_TREE;
--- 3898,3904 ----
      {
        first_vfn_base_index = -1;
        has_virtual = 0;
!       max_has_virtual = 0;
        vfield = NULL_TREE;
        vfields = NULL_TREE;
        CLASSTYPE_RTTI (t) = NULL_TREE;
*************** finish_struct_1 (t)
*** 3712,3786 ****
        no_const_asn_ref = 0;
      }
  
!   /* The three of these are approximations which may later be
!      modified.  Needed at this point to make add_virtual_function
!      and modify_vtable_entries work.  */
!   CLASSTYPE_VFIELDS (t) = vfields;
!   TYPE_VFIELD (t) = vfield;
! 
!   for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
!     {
!       GNU_xref_member (current_class_name, x);
  
!       /* If this was an evil function, don't keep it in class.  */
!       if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
! 	continue;
  
!       /* Do both of these, even though they're in the same union;
! 	 if the insn `r' member and the size `i' member are
! 	 different sizes, as on the alpha, the larger of the two
! 	 will end up with garbage in it.  */
!       DECL_SAVED_INSNS (x) = 0;
!       DECL_FIELD_SIZE (x) = 0;
  
!       check_for_override (x, t);
!       if (DECL_ABSTRACT_VIRTUAL_P (x) && ! DECL_VINDEX (x))
! 	cp_error_at ("initializer specified for non-virtual method `%D'", x);
  
!       /* The name of the field is the original field name
! 	 Save this in auxiliary field for later overloading.  */
!       if (DECL_VINDEX (x))
! 	{
! 	  add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
! 				&has_virtual, x, t);
! 	  if (DECL_ABSTRACT_VIRTUAL_P (x))
! 	    abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals);
! #if 0
! 	  /* XXX Why did I comment this out?  (jason) */
! 	  else
! 	    TREE_USED (x) = 1;
! #endif
! 	}
      }
  
!   if (n_baseclasses)
!     TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (t),
! 			       TYPE_FIELDS (t));
! 
!   /* Check all the data member declarations for legality.  */
!   next_field = check_field_decls (t, &access_decls, &empty,
! 				  &cant_have_default_ctor,
! 				  &cant_have_const_ctor,
! 				  &no_const_asn_ref);
!   fields = TYPE_FIELDS (t);
  
-   /* If this type has any constant members which did not come
-      with their own initialization, mark that fact here.  It is
-      not an error here, since such types can be saved either by their
-      constructors, or by fortuitous initialization.  */
-   CLASSTYPE_READONLY_FIELDS_NEED_INIT (t) = const_sans_init;
-   CLASSTYPE_ABSTRACT_VIRTUALS (t) = abstract_virtuals;
-   
    /* 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)
! 	|| has_virtual);
    TYPE_NEEDS_CONSTRUCTING (t)
!     |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t)
! 	|| has_virtual);
    CLASSTYPE_NON_AGGREGATE (t)
!       = ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t);
    CLASSTYPE_NON_POD_P (t)
      |= (CLASSTYPE_NON_AGGREGATE (t) || TYPE_HAS_DESTRUCTOR (t) 
  	|| TYPE_HAS_ASSIGN_REF (t));
--- 3907,3948 ----
        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));
*************** finish_struct_1 (t)
*** 3794,3822 ****
      = add_implicitly_declared_members (t, cant_have_default_ctor,
  				       cant_have_const_ctor,
  				       no_const_asn_ref);
-   if (virtual_dtor)
-     add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
- 			  &has_virtual, virtual_dtor, t);
  
!   if (TYPE_METHODS (t))
!     {
!       finish_struct_methods (t);
!       method_vec = CLASSTYPE_METHOD_VEC (t);
!     }
!   else
!     {
!       method_vec = 0;
  
!       /* Just in case these got accidentally
! 	 filled in by syntax errors.  */
!       TYPE_HAS_CONSTRUCTOR (t) = 0;
!       TYPE_HAS_DESTRUCTOR (t) = 0;
!     }
  
    /* Process the access-declarations.  */
    while (access_decls)
      {
!       handle_using_decl (TREE_VALUE (access_decls), t, method_vec, fields); 
        access_decls = TREE_CHAIN (access_decls);
      }
  
--- 3956,3976 ----
      = 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))
!     if (DECL_VINDEX (x))
!       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);
      }
  
*************** finish_struct_1 (t)
*** 3841,3900 ****
  	 bounds.  That's better than using `void*' or some such; it's
  	 cleaner, and it let's the alias analysis code know that these
  	 stores cannot alias stores to void*!  */
!       vfield = build_lang_decl (FIELD_DECL, get_vfield_name (t),
! 				      vtbl_ptr_type_node);
!       /* If you change any of the below, take a look at all the
! 	 other VFIELD_BASEs and VTABLE_BASEs in the code, and change
! 	 them too.  */
!       DECL_ASSEMBLER_NAME (vfield) = get_identifier (VFIELD_BASE);
        TYPE_VFIELD (t) = vfield;
-       DECL_VIRTUAL_P (vfield) = 1;
-       DECL_ARTIFICIAL (vfield) = 1;
-       DECL_FIELD_CONTEXT (vfield) = t;
-       DECL_CLASS_CONTEXT (vfield) = t;
-       DECL_FCONTEXT (vfield) = t;
-       DECL_SAVED_INSNS (vfield) = 0;
-       DECL_FIELD_SIZE (vfield) = 0;
-       DECL_ALIGN (vfield) = TYPE_ALIGN (ptr_type_node);
        *next_field = vfield;
-       empty = 0;
        vfields = chainon (vfields, build_tree_list (NULL_TREE, t));
      }
  
-   /* Now DECL_INITIAL is null on all members except for zero-width bit-fields.
- 
-      C++: maybe we will support default field initialization some day...  */
- 
-   /* Delete all duplicate fields from the fields */
-   delete_duplicate_fields (fields);
- 
-   /* Now we have the nearly final fieldlist for the data fields.  Record it,
-      then lay out the structure or union (including the fields).  */
- 
-   TYPE_FIELDS (t) = fields;
- 
-   if (n_baseclasses)
-     {
-       TYPE_FIELDS (t) = chainon (build_base_fields (t), TYPE_FIELDS (t));
- 
-       /* If all our bases are empty, we can be empty too.  */
-       for (x = TYPE_FIELDS (t); empty && x != fields; x = TREE_CHAIN (x))
- 	if (DECL_SIZE (x) != integer_zero_node)
- 	  empty = 0;
-     }
- 
    /* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS.  Thus,
       we have to save this before we start modifying
       TYPE_NONCOPIED_PARTS.  */
    inline_friends = CLASSTYPE_INLINE_FRIENDS (t);
    CLASSTYPE_INLINE_FRIENDS (t) = NULL_TREE;
  
    if (empty)
      {
-       /* C++: do not let empty structures exist.  */
        tree decl = build_lang_decl
  	(FIELD_DECL, NULL_TREE, char_type_node);
!       TREE_CHAIN (decl) = fields;
        TYPE_FIELDS (t) = decl;
        TYPE_NONCOPIED_PARTS (t) 
  	= tree_cons (NULL_TREE, decl, TYPE_NONCOPIED_PARTS (t));
--- 3995,4026 ----
  	 bounds.  That's better than using `void*' or some such; it's
  	 cleaner, and it let's the alias analysis code know that these
  	 stores cannot alias stores to void*!  */
!       vfield = build_vtbl_or_vbase_field (get_vfield_name (t),
! 					  get_identifier (VFIELD_BASE),
! 					  vtbl_ptr_type_node,
! 					  t,
! 					  &empty);
        TYPE_VFIELD (t) = vfield;
        *next_field = vfield;
        vfields = chainon (vfields, build_tree_list (NULL_TREE, t));
      }
  
    /* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS.  Thus,
       we have to save this before we start modifying
       TYPE_NONCOPIED_PARTS.  */
    inline_friends = CLASSTYPE_INLINE_FRIENDS (t);
    CLASSTYPE_INLINE_FRIENDS (t) = NULL_TREE;
  
+   /* We make all structures have at least one element, so that they
+      have non-zero size.  The field that we add here is fake, in the
+      sense that, for example, we don't want people to be able to
+      initialize it later.  So, we add it just long enough to let the
+      back-end lay out the type, and then remove it.  */
    if (empty)
      {
        tree decl = build_lang_decl
  	(FIELD_DECL, NULL_TREE, char_type_node);
!       TREE_CHAIN (decl) = TYPE_FIELDS (t);
        TYPE_FIELDS (t) = decl;
        TYPE_NONCOPIED_PARTS (t) 
  	= tree_cons (NULL_TREE, decl, TYPE_NONCOPIED_PARTS (t));
*************** finish_struct_1 (t)
*** 3903,3908 ****
--- 4029,4039 ----
  
    layout_type (t);
  
+   /* If we added an extra field to make this class non-empty, remove
+      it now.  */
+   if (empty)
+     TYPE_FIELDS (t) = TREE_CHAIN (TYPE_FIELDS (t));
+ 
    /* Remember the size and alignment of the class before adding
       the virtual bases.  */
    if (empty && flag_new_abi)
*************** finish_struct_1 (t)
*** 3930,3951 ****
    if (n_baseclasses)
      /* layout_basetypes will remove the base subobject fields.  */
      max_has_virtual = layout_basetypes (t, max_has_virtual);
-   if (empty)
-     TYPE_FIELDS (t) = fields;
- 
-   my_friendly_assert (TYPE_FIELDS (t) == fields, 981117);
  
!   /* Delete all zero-width bit-fields from the fieldlist */
!   {
!     tree *fieldsp = &fields;
!     while (*fieldsp)
!       if (TREE_CODE (*fieldsp) == FIELD_DECL
! 	  && DECL_C_BIT_FIELD (*fieldsp) && DECL_INITIAL (*fieldsp))
! 	*fieldsp = TREE_CHAIN (*fieldsp);
!       else
! 	fieldsp = &TREE_CHAIN (*fieldsp);
!   }
!   TYPE_FIELDS (t) = fields;
  
    if (TYPE_USES_VIRTUAL_BASECLASSES (t))
      {
--- 4061,4070 ----
    if (n_baseclasses)
      /* layout_basetypes will remove the base subobject fields.  */
      max_has_virtual = layout_basetypes (t, max_has_virtual);
  
!   /* Delete all zero-width bit-fields from the list of fields.  Now
!      that we have layed out the type they are no longer important.  */
!   remove_zero_width_bit_fields (t);
  
    if (TYPE_USES_VIRTUAL_BASECLASSES (t))
      {
*************** finish_struct_1 (t)
*** 3998,4007 ****
        TYPE_VFIELD (t) = vfield;
      }
      
- #ifdef NOTQUITE
-   cp_warning ("Doing hard virtuals for %T...", t);
- #endif
- 
    if (has_virtual > max_has_virtual)
      max_has_virtual = has_virtual;
    if (max_has_virtual > 0)
--- 4117,4122 ----
*************** finish_struct_1 (t)
*** 4141,4147 ****
  
    /* Complete the rtl for any static member objects of the type we're
       working on.  */
!   for (x = fields; x; x = TREE_CHAIN (x))
      {
        if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x)
  	  && TREE_TYPE (x) == t)
--- 4256,4262 ----
  
    /* Complete the rtl for any static member objects of the type we're
       working on.  */
!   for (x = TYPE_FIELDS (t); x; x = TREE_CHAIN (x))
      {
        if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x)
  	  && TREE_TYPE (x) == t)
*************** finish_struct_1 (t)
*** 4152,4171 ****
      }
  
    /* Done with FIELDS...now decide whether to sort these for
!      faster lookups later.  Don't worry about optimizing
!      for structs only declared in inline functions...they're
!      not going to be referenced anywhere else.
  
       The C front-end only does this when n_fields > 15.  We use
       a smaller number because most searches fail (succeeding
       ultimately as the search bores through the inheritance
       hierarchy), and we want this failure to occur quickly.  */
  
!   n_fields = count_fields (fields);
!   if (n_fields > 7 && !allocation_temporary_p ())
      {
        tree field_vec = make_tree_vec (n_fields);
!       add_fields_to_vec (fields, field_vec, 0);
        qsort (&TREE_VEC_ELT (field_vec, 0), n_fields, sizeof (tree),
  	     (int (*)(const void *, const void *))field_decl_cmp);
        if (! DECL_LANG_SPECIFIC (TYPE_MAIN_DECL (t)))
--- 4267,4284 ----
      }
  
    /* Done with FIELDS...now decide whether to sort these for
!      faster lookups later.
  
       The C front-end only does this when n_fields > 15.  We use
       a smaller number because most searches fail (succeeding
       ultimately as the search bores through the inheritance
       hierarchy), and we want this failure to occur quickly.  */
  
!   n_fields = count_fields (TYPE_FIELDS (t));
!   if (n_fields > 7)
      {
        tree field_vec = make_tree_vec (n_fields);
!       add_fields_to_vec (TYPE_FIELDS (t), field_vec, 0);
        qsort (&TREE_VEC_ELT (field_vec, 0), n_fields, sizeof (tree),
  	     (int (*)(const void *, const void *))field_decl_cmp);
        if (! DECL_LANG_SPECIFIC (TYPE_MAIN_DECL (t)))
*************** finish_struct_1 (t)
*** 4201,4207 ****
  		     vfield, TYPE_NONCOPIED_PARTS (t));
  
        if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t)
! 	  && DECL_VINDEX (TREE_VEC_ELT (method_vec, 1)) == NULL_TREE)
  	cp_warning ("`%#T' has virtual functions but non-virtual destructor",
  		    t);
      }
--- 4314,4320 ----
  		     vfield, TYPE_NONCOPIED_PARTS (t));
  
        if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t)
! 	  && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1)) == NULL_TREE)
  	cp_warning ("`%#T' has virtual functions but non-virtual destructor",
  		    t);
      }
*************** finish_struct_1 (t)
*** 4210,4220 ****
       the base types we marked.  */
    finish_vtbls (TYPE_BINFO (t), 1, t);
    hack_incomplete_structures (t);
- 
- #if 0
-   if (TYPE_NAME (t) && TYPE_IDENTIFIER (t))
-     undo_template_name_overload (TYPE_IDENTIFIER (t), 1);
- #endif
  
    if (warn_overloaded_virtual)
      warn_hidden (t);
--- 4323,4328 ----
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.360
diff -c -p -r1.360 cp-tree.h
*** cp-tree.h	1999/12/14 18:52:40	1.360
--- cp-tree.h	1999/12/16 02:46:41
*************** extern tree build_cplus_method_type		PRO
*** 4011,4017 ****
  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_vbase_pointer_fields		PROTO((tree));
  extern tree build_base_fields			PROTO((tree));
  extern tree hash_tree_cons			PROTO((tree, tree, tree));
  extern tree hash_tree_chain			PROTO((tree, tree));
--- 4011,4016 ----
Index: decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.518
diff -c -p -r1.518 decl.c
*** decl.c	1999/12/11 19:02:10	1.518
--- decl.c	1999/12/16 02:46:49
*************** grokdeclarator (declarator, declspecs, d
*** 9282,9289 ****
  	    /* Avoid giving two errors for this.  */
  	    IDENTIFIER_CLASS_VALUE (dname) = NULL_TREE;
  
! 	    declspecs = temp_tree_cons (NULL_TREE, integer_type_node,
! 					declspecs);
  	    *next = dname;
  	    next = 0;
  	    break;
--- 9282,9288 ----
  	    /* Avoid giving two errors for this.  */
  	    IDENTIFIER_CLASS_VALUE (dname) = NULL_TREE;
  
! 	    declspecs = tree_cons (NULL_TREE, integer_type_node, declspecs);
  	    *next = dname;
  	    next = 0;
  	    break;
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl2.c,v
retrieving revision 1.287
diff -c -p -r1.287 decl2.c
*** decl2.c	1999/12/05 00:37:56	1.287
--- decl2.c	1999/12/16 02:46:53
*************** qualified_lookup_using_namespace (name, 
*** 4334,4340 ****
    tree usings;
    while (scope && (result != error_mark_node))
      {
!       seen = temp_tree_cons (scope, NULL_TREE, seen);
        result = ambiguous_decl (name, result,
                                 binding_for_name (name, scope), flags);
        if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
--- 4334,4340 ----
    tree usings;
    while (scope && (result != error_mark_node))
      {
!       seen = tree_cons (scope, NULL_TREE, seen);
        result = ambiguous_decl (name, result,
                                 binding_for_name (name, scope), flags);
        if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
*************** qualified_lookup_using_namespace (name, 
*** 4344,4350 ****
  	  /* If this was a real directive, and we have not seen it. */
  	  if (!TREE_INDIRECT_USING (usings)
  	      && !purpose_member (TREE_PURPOSE (usings), seen))
! 	    todo = temp_tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
        if (todo)
  	{
  	  scope = TREE_PURPOSE (todo);
--- 4344,4350 ----
  	  /* If this was a real directive, and we have not seen it. */
  	  if (!TREE_INDIRECT_USING (usings)
  	      && !purpose_member (TREE_PURPOSE (usings), seen))
! 	    todo = tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
        if (todo)
  	{
  	  scope = TREE_PURPOSE (todo);
Index: lex.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/lex.c,v
retrieving revision 1.168
diff -c -p -r1.168 lex.c
*** lex.c	1999/12/14 05:33:22	1.168
--- lex.c	1999/12/16 02:46:55
*************** cons_up_default_function (type, full_nam
*** 2000,2008 ****
    switch (kind)
      {
        /* Destructors.  */
-     case 1:
-       declspecs = build_decl_list (NULL_TREE, ridpointers [(int) RID_VIRTUAL]);
-       /* Fall through...  */
      case 0:
        name = build_parse_node (BIT_NOT_EXPR, name);
        args = void_list_node;
--- 2000,2005 ----
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 02:46:56
*************** 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.167
diff -c -p -r1.167 tree.c
*** tree.c	1999/12/14 18:52:40	1.167
--- tree.c	1999/12/16 02:46:58
*************** build_base_fields (rec)
*** 989,1074 ****
    return base_decls;
  }
  
- /* Returns list of virtual base class pointers in a FIELD_DECL chain.  */
- 
- tree
- build_vbase_pointer_fields (rec)
-      tree rec;
- {
-   /* Chain to hold all the new FIELD_DECLs which point at virtual
-      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;
- 
-   /* Handle basetypes almost like fields, but record their
-      offsets differently.  */
- 
-   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;
- 
-       /* All basetypes are recorded in the association list of the
- 	 derived type.  */
- 
-       if (TREE_VIA_VIRTUAL (base_binfo))
- 	{
- 	  int j;
- 	  const char *name;
- 
- 	  /* The offset for a virtual base class is only used in computing
- 	     virtual function tables and for initializing virtual base
- 	     pointers.  It is built once `get_vbase_types' is called.  */
- 
- 	  /* If this basetype can come from another vbase pointer
- 	     without an additional indirection, we will share
- 	     that pointer.  If an indirection is involved, we
- 	     make our own pointer.  */
- 	  for (j = 0; j < n_baseclasses; j++)
- 	    {
- 	      tree other_base_binfo = TREE_VEC_ELT (binfos, j);
- 	      if (! TREE_VIA_VIRTUAL (other_base_binfo)
- 		  && binfo_member (basetype,
- 				   CLASSTYPE_VBASECLASSES (BINFO_TYPE
- 							   (other_base_binfo))
- 				   ))
- 		goto got_it;
- 	    }
- 	  FORMAT_VBASE_NAME (name, basetype);
- 	  decl = build_lang_decl (FIELD_DECL, get_identifier (name),
- 				  build_pointer_type (basetype));
- 	  /* If you change any of the below, take a look at all the
- 	     other VFIELD_BASEs and VTABLE_BASEs in the code, and change
- 	     them too.  */
- 	  DECL_ASSEMBLER_NAME (decl) = get_identifier (VTABLE_BASE);
- 	  DECL_VIRTUAL_P (decl) = 1;
- 	  DECL_ARTIFICIAL (decl) = 1;
- 	  DECL_FIELD_CONTEXT (decl) = rec;
- 	  DECL_CLASS_CONTEXT (decl) = rec;
- 	  DECL_FCONTEXT (decl) = basetype;
- 	  DECL_SAVED_INSNS (decl) = 0;
- 	  DECL_FIELD_SIZE (decl) = 0;
- 	  DECL_ALIGN (decl) = TYPE_ALIGN (ptr_type_node);
- 	  TREE_CHAIN (decl) = vbase_decls;
- 	  BINFO_VPTR_FIELD (base_binfo) = decl;
- 	  vbase_decls = decl;
- 
- 	got_it:
- 	  /* The space this decl occupies has already been accounted for.  */
- 	  ;
- 	}
-     }
- 
-   return vbase_decls;
- }
  
  /* Hashing of lists so that we don't make duplicates.
     The entry point is `list_hash_canon'.  */
--- 989,994 ----


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