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]
Other format: [Raw text]

C++ PATCH: Fix ABI bug and crash


This patch:

  2002-05-14  Alexandre Oliva  <aoliva@redhat.com>

	* cp-tree.h (struct lang_type): Added non_zero_init.

contained this red-flag comment:

!       /* This is a default initialization of an aggregate, but not one of
! 	 non-POD class type.  We cleverly notice that the initialization
! 	 rules in such a case are the same as for initialization with an
! 	 empty brace-initialization list.  */

Note the user of clever. :-)

The approach used in this patch doesn't work; this, for example, is a
failing test case, distilled from our ABI testsuite:

  struct S {
    S ();
    int S::* sp;
    int i;
  };

  S s[2] = {};

(The root problem that Alexandre was trying to fix is that the new C++
ABI "cleverly" uses -1 to represent a NULL pointer-to-data-member;
that decision means that "zero-initialization" in the sense of the
language standard no longer means "fill with zeros".)

I fixed this by doing what I've talked about doing for ages; creating
separate variants of each type for the base class case vs. the
complete object case.  That allows us to tell the middle end the truth
about the layout of a C++ class type, and that, in turn, makes it easy
to generate the correct zero-initializations.

This is not very clever, but I hope it will be right.

Our ABI testsuite also found a related problem again involving empty
base classes; I fixed that as well with -fabi-version=0.  Here's a
test case:

  struct S1 {};
  struct S2 { virtual void f () {} S1 s1[4]; };
  struct S3 : virtual public S2 {};
  struct S4 : virtual public S2 { int i; };
  struct S5 : public S3, virtual public S4 {};
  struct S6 { S5 s5; };
  struct S7 { S1 s1[5]; };
  struct S8 : public S1, public S6, virtual public S7 { };

  S8 s8;

  int main () {
    if ((char *)(S7 *)&s8 - (char *)&s8 != 24)
      return 1;
  }

Brownie points if you can figure out why we got that wrong. :-) [Hint;
I think you really do need all those classes to manfiest the bug.  Or
at least almost all of them.]

Bootstrapped and tested on i686-pc-linux-gnu, applied on the mainline.

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

2002-09-30  Mark Mitchell  <mark@codesourcery.com>

	* store-layout.c (finish_record_layout): Add free_p parameter.
	(layout_type): Pass it.
	* tree.h (finish_record_layout): Update prototype.
	
2002-09-30  Mark Mitchell  <mark@codesourcery.com>

	* class.c (walk_subobject_offsets): Correct the calculation of
	offsets for virtual bases.  Correct the counting of array
	elements.
	(layout_nonempty_base_or_field): Simplify.  Correct the
	calculation of offsets to be propagated through the binfo
	hierarchy.
	(build_base_field): Avoid creating a FIELD_DECL for empty bases.
	Add the FIELD_DECL to TYPE_FIELDS.
	(build_base_fields): Adjust accordingly.
	(layout_virtual_bases): Use build_base_field.
	(end_of_class): Return a tree, not an integer.
	(warn_about_ambiguous_direct_bases): Rename to ...
	(warn_about_ambiguous_bases): ... this.
	(include_empty_classes): New function.
	(layout_class_type): Create an alternative version of the type to
	be used when as a base class type.  Do not call
	finish_record_layout until we are done laying out the class.
	* cp-tree.h (lang_type_class): Remove size, size_unit.  Add
	as_base.
	(CLASSTYPE_SIZE): Reimplement.
	(CLASSTYPE_SIZE_UNIT): Likewise.
	(CLASSTYPE_ALIGN): Likweise.
	(CLASSTYPE_USER_ALIGN): Likewise.
	(CLASSTYPE_AS_BASE): New macro.
	(DECL_INITIALIZED_P): Likewise.
	(extract_init): Remove prototype.
	(build_forced_zero_init): Rename to ...
	(build_zero_init): ... this.
	(force_store_init_value): Remove.
	* decl.c (obscure_complex_init): Remove.
	(duplicate_decls): Copy DECL_INITIALIZED_P.
	(check_initializer): Do not leave junk in DECL_INITIAL.
	(cp_finish_decl): Handle zero-initialization of entities with
	static storage duration.
	* expr.c (extract_init): Remove.
	* init.c (build_forced_zero_init): Remove.
	(build_zero_init): New function.
	(build_default_init): Use it.
	(build_field_list): Skip FIELD_DECLs for base subobjects.
	(push_base_cleanups): Likewise.
	* method.c (do_build_assign_ref): Likewise.
	(synthesize_exception_spec): Likewise.
	* pt.c (tsubst_decl): Clear DECL_INITIALIZED_P.
	(regenerate_decl_from_template): To not set DECL_INITIAL for a
	static data member whose initialization took place in its class.
	(instantiate_decl): Do not pass an initializer to cp_finish_decl
	in that situation.
	* search.c (dfs_push_decls): Skip FIELD_DECLs for base subobjects.
	(dfs_unuse_fields): Likewise.
	* tree.c (pod_type_p): Handle error_mark_node.
	(zero_init_p): Likewise.
	* typeck.c (lookup_anon_field): Skip FIELD_DECLs for base 
	subobjects.
	* typeck2.c (store_init_value): Remove #if 0'd code.
	(force_store_init_value): Remove.
	(process_init_constructor): Use build_zero_init.
	
2002-09-30  Mark Mitchell  <mark@codesourcery.com>

	* g++.dg/abi/empty7.C: New test.
	* g++.dg/init/pm2.C: Likewise.
	
Index: stor-layout.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stor-layout.c,v
retrieving revision 1.129
diff -c -5 -p -r1.129 stor-layout.c
*** stor-layout.c	18 Sep 2002 18:51:13 -0000	1.129
--- stor-layout.c	30 Sep 2002 16:04:42 -0000
*************** finalize_type_size (type)
*** 1482,1496 ****
      }
  }
  
  /* Do all of the work required to layout the type indicated by RLI,
     once the fields have been laid out.  This function will call `free'
!    for RLI.  */
  
  void
! finish_record_layout (rli)
       record_layout_info rli;
  {
    /* Compute the final size.  */
    finalize_record_size (rli);
  
    /* Compute the TYPE_MODE for the record.  */
--- 1482,1499 ----
      }
  }
  
  /* Do all of the work required to layout the type indicated by RLI,
     once the fields have been laid out.  This function will call `free'
!    for RLI, unless FREE_P is false.  Passing a value other than false
!    for FREE_P is bad practice; this option only exists to support the
!    G++ 3.2 ABI.  */
  
  void
! finish_record_layout (rli, free_p)
       record_layout_info rli;
+      int free_p;
  {
    /* Compute the final size.  */
    finalize_record_size (rli);
  
    /* Compute the TYPE_MODE for the record.  */
*************** finish_record_layout (rli)
*** 1506,1516 ****
        layout_decl (TREE_VALUE (rli->pending_statics), 0);
        rli->pending_statics = TREE_CHAIN (rli->pending_statics);
      }
  
    /* Clean up.  */
!   free (rli);
  }
  
  /* Calculate the mode, size, and alignment for TYPE.
     For an array type, calculate the element separation as well.
     Record TYPE on the chain of permanent or temporary types
--- 1509,1520 ----
        layout_decl (TREE_VALUE (rli->pending_statics), 0);
        rli->pending_statics = TREE_CHAIN (rli->pending_statics);
      }
  
    /* Clean up.  */
!   if (free_p)
!     free (rli);
  }
  
  /* Calculate the mode, size, and alignment for TYPE.
     For an array type, calculate the element separation as well.
     Record TYPE on the chain of permanent or temporary types
*************** layout_type (type)
*** 1761,1771 ****
  
  	if (lang_adjust_rli)
  	  (*lang_adjust_rli) (rli);
  
  	/* Finish laying out the record.  */
! 	finish_record_layout (rli);
        }
        break;
  
      case SET_TYPE:  /* Used by Chill and Pascal.  */
        if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST
--- 1765,1775 ----
  
  	if (lang_adjust_rli)
  	  (*lang_adjust_rli) (rli);
  
  	/* Finish laying out the record.  */
! 	finish_record_layout (rli, /*free_p=*/true);
        }
        break;
  
      case SET_TYPE:  /* Used by Chill and Pascal.  */
        if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.353
diff -c -5 -p -r1.353 tree.h
*** tree.h	20 Sep 2002 07:33:25 -0000	1.353
--- tree.h	30 Sep 2002 16:04:43 -0000
*************** extern void normalize_offset		PARAMS ((t
*** 2422,2432 ****
  extern tree rli_size_unit_so_far	PARAMS ((record_layout_info));
  extern tree rli_size_so_far		PARAMS ((record_layout_info));
  extern void normalize_rli		PARAMS ((record_layout_info));
  extern void place_field			PARAMS ((record_layout_info, tree));
  extern void compute_record_mode		PARAMS ((tree));
! extern void finish_record_layout	PARAMS ((record_layout_info));
  
  /* Given a hashcode and a ..._TYPE node (for which the hashcode was made),
     return a canonicalized ..._TYPE node, so that duplicates are not made.
     How the hash code is computed is up to the caller, as long as any two
     callers that could hash identical-looking type nodes agree.  */
--- 2422,2432 ----
  extern tree rli_size_unit_so_far	PARAMS ((record_layout_info));
  extern tree rli_size_so_far		PARAMS ((record_layout_info));
  extern void normalize_rli		PARAMS ((record_layout_info));
  extern void place_field			PARAMS ((record_layout_info, tree));
  extern void compute_record_mode		PARAMS ((tree));
! extern void finish_record_layout	PARAMS ((record_layout_info, int));
  
  /* Given a hashcode and a ..._TYPE node (for which the hashcode was made),
     return a canonicalized ..._TYPE node, so that duplicates are not made.
     How the hash code is computed is up to the caller, as long as any two
     callers that could hash identical-looking type nodes agree.  */
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.469
diff -c -5 -p -r1.469 class.c
*** cp/class.c	25 Sep 2002 19:07:32 -0000	1.469
--- cp/class.c	30 Sep 2002 16:04:45 -0000
*************** static int count_fields PARAMS ((tree));
*** 135,159 ****
  static int add_fields_to_vec PARAMS ((tree, tree, int));
  static void check_bitfield_decl PARAMS ((tree));
  static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
  static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *, 
  				     int *));
! static bool build_base_field PARAMS ((record_layout_info, tree, int *,
! 				     splay_tree, tree));
! static bool build_base_fields PARAMS ((record_layout_info, int *,
! 				      splay_tree, tree));
  static void check_methods PARAMS ((tree));
  static void remove_zero_width_bit_fields PARAMS ((tree));
  static void check_bases PARAMS ((tree, int *, int *, int *));
  static void check_bases_and_members PARAMS ((tree, int *));
  static tree create_vtable_ptr PARAMS ((tree, int *, tree *));
  static void layout_class_type PARAMS ((tree, int *, int *, tree *));
  static void fixup_pending_inline PARAMS ((tree));
  static void fixup_inline_methods PARAMS ((tree));
  static void set_primary_base PARAMS ((tree, tree, int *));
  static void propagate_binfo_offsets PARAMS ((tree, tree, tree));
! static void layout_virtual_bases PARAMS ((tree, splay_tree));
  static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
  static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
  static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *));
  static void add_vcall_offset_vtbl_entries_1 PARAMS ((tree, vtbl_init_data *));
  static void build_vcall_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
--- 135,160 ----
  static int add_fields_to_vec PARAMS ((tree, tree, int));
  static void check_bitfield_decl PARAMS ((tree));
  static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
  static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *, 
  				     int *));
! static tree *build_base_field PARAMS ((record_layout_info, tree, int *,
! 				       splay_tree, tree *));
! static void build_base_fields PARAMS ((record_layout_info, int *,
! 				      splay_tree, tree *));
  static void check_methods PARAMS ((tree));
  static void remove_zero_width_bit_fields PARAMS ((tree));
  static void check_bases PARAMS ((tree, int *, int *, int *));
  static void check_bases_and_members PARAMS ((tree, int *));
  static tree create_vtable_ptr PARAMS ((tree, int *, tree *));
+ static void include_empty_classes (record_layout_info);
  static void layout_class_type PARAMS ((tree, int *, int *, tree *));
  static void fixup_pending_inline PARAMS ((tree));
  static void fixup_inline_methods PARAMS ((tree));
  static void set_primary_base PARAMS ((tree, tree, int *));
  static void propagate_binfo_offsets PARAMS ((tree, tree, tree));
! static void layout_virtual_bases (record_layout_info, splay_tree);
  static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
  static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
  static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *));
  static void add_vcall_offset_vtbl_entries_1 PARAMS ((tree, vtbl_init_data *));
  static void build_vcall_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
*************** static void dump_vtable PARAMS ((tree, t
*** 169,181 ****
  static void dump_vtt PARAMS ((tree, tree));
  static tree build_vtable PARAMS ((tree, tree, tree));
  static void initialize_vtable PARAMS ((tree, tree));
  static void initialize_array PARAMS ((tree, tree));
  static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
! 						   tree, tree,
! 						   splay_tree, tree));
! static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
  static bool layout_empty_base PARAMS ((tree, tree, splay_tree, tree));
  static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
  static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
  					       tree));
  static void set_vindex PARAMS ((tree, int *));
--- 170,181 ----
  static void dump_vtt PARAMS ((tree, tree));
  static tree build_vtable PARAMS ((tree, tree, tree));
  static void initialize_vtable PARAMS ((tree, tree));
  static void initialize_array PARAMS ((tree, tree));
  static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
! 						   tree, tree, splay_tree));
! static tree end_of_class PARAMS ((tree, int));
  static bool layout_empty_base PARAMS ((tree, tree, splay_tree, tree));
  static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
  static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
  					       tree));
  static void set_vindex PARAMS ((tree, int *));
*************** static int walk_subobject_offsets PARAMS
*** 206,216 ****
  					   tree, splay_tree, tree, int));
  static void record_subobject_offsets PARAMS ((tree, tree, splay_tree, int));
  static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int));
  static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
  						    splay_tree_key k2));
! static void warn_about_ambiguous_direct_bases PARAMS ((tree));
  static bool type_requires_array_cookie PARAMS ((tree));
  static bool contains_empty_class_p (tree);
  
  /* Macros for dfs walking during vtt construction. See
     dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
--- 206,216 ----
  					   tree, splay_tree, tree, int));
  static void record_subobject_offsets PARAMS ((tree, tree, splay_tree, int));
  static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int));
  static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
  						    splay_tree_key k2));
! static void warn_about_ambiguous_bases PARAMS ((tree));
  static bool type_requires_array_cookie PARAMS ((tree));
  static bool contains_empty_class_p (tree);
  
  /* Macros for dfs walking during vtt construction. See
     dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
*************** walk_subobject_offsets (type, f, offset,
*** 3510,3530 ****
      return 0;
  
    if (CLASS_TYPE_P (type))
      {
        tree field;
        int i;
  
        /* Record the location of TYPE.  */
        r = (*f) (type, offset, offsets);
        if (r)
  	return r;
  
        /* Iterate through the direct base classes of TYPE.  */
        for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
  	{
! 	  tree binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
  
  	  if (!vbases_p 
  	      && TREE_VIA_VIRTUAL (binfo) 
  	      && !BINFO_PRIMARY_P (binfo))
  	    continue;
--- 3510,3535 ----
      return 0;
  
    if (CLASS_TYPE_P (type))
      {
        tree field;
+       tree binfo;
        int i;
  
        /* Record the location of TYPE.  */
        r = (*f) (type, offset, offsets);
        if (r)
  	return r;
  
        /* Iterate through the direct base classes of TYPE.  */
        for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
  	{
! 	  binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
! 
! 	  if (abi_version_at_least (2) 
! 	      && TREE_VIA_VIRTUAL (binfo))
! 	    continue;
  
  	  if (!vbases_p 
  	      && TREE_VIA_VIRTUAL (binfo) 
  	      && !BINFO_PRIMARY_P (binfo))
  	    continue;
*************** walk_subobject_offsets (type, f, offset,
*** 3534,3551 ****
  				      size_binop (PLUS_EXPR,
  						  offset,
  						  BINFO_OFFSET (binfo)),
  				      offsets,
  				      max_offset,
! 				      vbases_p);
  	  if (r)
  	    return r;
  	}
  
        /* Iterate through the fields of TYPE.  */
        for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
! 	if (TREE_CODE (field) == FIELD_DECL)
  	  {
  	    tree field_offset;
  
  	    if (abi_version_at_least (2))
  	      field_offset = byte_position (field);
--- 3539,3582 ----
  				      size_binop (PLUS_EXPR,
  						  offset,
  						  BINFO_OFFSET (binfo)),
  				      offsets,
  				      max_offset,
! 				      (abi_version_at_least (2) 
! 				       ? /*vbases_p=*/0 : vbases_p));
  	  if (r)
  	    return r;
  	}
  
+       /* Iterate through the virtual base classes of TYPE.  In G++
+ 	 3.2, we included virtual bases in the direct base class loop
+ 	 above, which results in incorrect results; the correct
+ 	 offsets for virtual bases are only known when working with
+ 	 the most derived type.  */
+       if (abi_version_at_least (2) && vbases_p)
+ 	{
+ 	  tree vbase;
+ 
+ 	  for (vbase = CLASSTYPE_VBASECLASSES (type);
+ 	       vbase;
+ 	       vbase = TREE_CHAIN (vbase))
+ 	    {
+ 	      binfo = TREE_VALUE (vbase);
+ 	      r = walk_subobject_offsets (BINFO_TYPE (binfo),
+ 					  f,
+ 					  size_binop (PLUS_EXPR,
+ 						      offset,
+ 						      BINFO_OFFSET (binfo)),
+ 					  offsets,
+ 					  max_offset,
+ 					  /*vbases_p=*/0);
+ 	    }
+ 	}
+ 
        /* Iterate through the fields of TYPE.  */
        for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
! 	if (TREE_CODE (field) == FIELD_DECL && !DECL_ARTIFICIAL (field))
  	  {
  	    tree field_offset;
  
  	    if (abi_version_at_least (2))
  	      field_offset = byte_position (field);
*************** walk_subobject_offsets (type, f, offset,
*** 3569,3580 ****
      {
        tree domain = TYPE_DOMAIN (type);
        tree index;
  
        /* Step through each of the elements in the array.  */
!       for (index = size_zero_node; 
! 	   INT_CST_LT (index, TYPE_MAX_VALUE (domain));
  	   index = size_binop (PLUS_EXPR, index, size_one_node))
  	{
  	  r = walk_subobject_offsets (TREE_TYPE (type),
  				      f,
  				      offset,
--- 3600,3614 ----
      {
        tree domain = TYPE_DOMAIN (type);
        tree index;
  
        /* Step through each of the elements in the array.  */
!       for (index = size_zero_node;
! 	   /* G++ 3.2 had an off-by-one error here.  */
! 	   (abi_version_at_least (2) 
! 	    ? !INT_CST_LT (TYPE_MAX_VALUE (domain), index)
! 	    : INT_CST_LT (index, TYPE_MAX_VALUE (domain)));
  	   index = size_binop (PLUS_EXPR, index, size_one_node))
  	{
  	  r = walk_subobject_offsets (TREE_TYPE (type),
  				      f,
  				      offset,
*************** layout_conflict_p (type, offset, offsets
*** 3638,3663 ****
  }
  
  /* DECL is a FIELD_DECL corresponding either to a base subobject of a
     non-static data member of the type indicated by RLI.  BINFO is the
     binfo corresponding to the base subobject, OFFSETS maps offsets to
!    types already located at those offsets.  T is the most derived
!    type.  This function determines the position of the DECL.  */
  
  static void
! layout_nonempty_base_or_field (rli, decl, binfo, offsets, t)
!      record_layout_info rli;
!      tree decl;
!      tree binfo;
!      splay_tree offsets;
!      tree t;
  {
    tree offset = NULL_TREE;
!   tree type = TREE_TYPE (decl);
!   /* If we are laying out a base class, rather than a field, then
!      DECL_ARTIFICIAL will be set on the FIELD_DECL.  */
!   int field_p = !DECL_ARTIFICIAL (decl);
  
    /* Try to place the field.  It may take more than one try if we have
       a hard time placing the field without putting two objects of the
       same type at the same address.  */
    while (1)
--- 3672,3709 ----
  }
  
  /* DECL is a FIELD_DECL corresponding either to a base subobject of a
     non-static data member of the type indicated by RLI.  BINFO is the
     binfo corresponding to the base subobject, OFFSETS maps offsets to
!    types already located at those offsets.  This function determines
!    the position of the DECL.  */
  
  static void
! layout_nonempty_base_or_field (record_layout_info rli, 
! 			       tree decl, 
! 			       tree binfo, 
! 			       splay_tree offsets)
  {
+   tree t = rli->t;
    tree offset = NULL_TREE;
!   bool field_p;
!   tree type;
!   
!   if (binfo)
!     {
!       /* For the purposes of determining layout conflicts, we want to
! 	 use the class type of BINFO; TREE_TYPE (DECL) will be the
! 	 CLASSTYPE_AS_BASE version, which does not contain entries for
! 	 zero-sized bases.  */
!       type = TREE_TYPE (binfo);
!       field_p = false;
!     }
!   else
!     {
!       type = TREE_TYPE (decl);
!       field_p = true;
!     }
  
    /* Try to place the field.  It may take more than one try if we have
       a hard time placing the field without putting two objects of the
       same type at the same address.  */
    while (1)
*************** layout_nonempty_base_or_field (rli, decl
*** 3681,3694 ****
  	 as the S we already allocated.  So, we have to skip ahead.
  	 Since all data members, including those whose type is an
  	 empty class, have nonzero size, any overlap can happen only
  	 with a direct or indirect base-class -- it can't happen with
  	 a data member.  */
!       if (layout_conflict_p (TREE_TYPE (decl),
! 			     offset,
! 			     offsets, 
! 			     field_p))
  	{
  	  /* Strip off the size allocated to this field.  That puts us
  	     at the first place we could have put the field with
  	     proper alignment.  */
  	  *rli = old_rli;
--- 3727,3737 ----
  	 as the S we already allocated.  So, we have to skip ahead.
  	 Since all data members, including those whose type is an
  	 empty class, have nonzero size, any overlap can happen only
  	 with a direct or indirect base-class -- it can't happen with
  	 a data member.  */
!       if (layout_conflict_p (type, offset, offsets, field_p))
  	{
  	  /* Strip off the size allocated to this field.  That puts us
  	     at the first place we could have put the field with
  	     proper alignment.  */
  	  *rli = old_rli;
*************** layout_nonempty_base_or_field (rli, decl
*** 3707,3718 ****
      }
  
    /* Now that we know where it will be placed, update its
       BINFO_OFFSET.  */
    if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
      propagate_binfo_offsets (binfo, 
! 			     convert (ssizetype, offset), t);
  }
  
  /* Layout the empty base BINFO.  EOC indicates the byte currently just
     past the end of the class, and should be correctly aligned for a
     class of the type indicated by BINFO; OFFSETS gives the offsets of
--- 3750,3768 ----
      }
  
    /* Now that we know where it will be placed, update its
       BINFO_OFFSET.  */
    if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
+     /* Indirect virtual bases may have a non-zero BINFO_OFFSET at
+        this point because their BINFO_OFFSET is copied from another
+        hierarchy.  Therefore, we may not need to add the entire
+        OFFSET.  */
      propagate_binfo_offsets (binfo, 
! 			     size_diffop (convert (ssizetype, offset),
! 					  convert (ssizetype, 
! 						   BINFO_OFFSET (binfo))),
! 			     t);
  }
  
  /* Layout the empty base BINFO.  EOC indicates the byte currently just
     past the end of the class, and should be correctly aligned for a
     class of the type indicated by BINFO; OFFSETS gives the offsets of
*************** layout_empty_base (binfo, eoc, offsets, 
*** 3766,3884 ****
  	}
      }
    return atend;
  }
  
! /* Build a FIELD_DECL for the base given by BINFO in the class
!    indicated by RLI.  If the new object is non-empty, clear *EMPTY_P.
!    *BASE_ALIGN is a running maximum of the alignments of any base
!    class.  OFFSETS gives the location of empty base subobjects.  T is
!    the most derived type.  Return nonzero if the new object cannot be
!    nearly-empty.  */
! 
! static bool
! build_base_field (rli, binfo, empty_p, offsets, t)
!      record_layout_info rli;
!      tree binfo;
!      int *empty_p;
!      splay_tree offsets;
!      tree t;
  {
    tree basetype = BINFO_TYPE (binfo);
-   tree decl;
-   bool atend = false;
  
    if (!COMPLETE_TYPE_P (basetype))
      /* This error is now reported in xref_tag, thus giving better
         location information.  */
!     return atend;
    
!   decl = build_decl (FIELD_DECL, NULL_TREE, basetype);
!   DECL_ARTIFICIAL (decl) = 1;
!   DECL_FIELD_CONTEXT (decl) = rli->t;
!   DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
!   DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
!   DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
!   DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
!   /* Tell the backend not to round up to TYPE_ALIGN.  */
!   DECL_PACKED (decl) = 1;
!   
!   if (!integer_zerop (DECL_SIZE (decl)))
      {
        /* The containing class is non-empty because it has a non-empty
  	 base class.  */
!       *empty_p = 0;
! 
        /* Try to place the field.  It may take more than one try if we
  	 have a hard time placing the field without putting two
  	 objects of the same type at the same address.  */
!       layout_nonempty_base_or_field (rli, decl, binfo, offsets, t);
      }
    else
      {
!       unsigned HOST_WIDE_INT eoc;
  
        /* On some platforms (ARM), even empty classes will not be
  	 byte-aligned.  */
!       eoc = tree_low_cst (rli_size_unit_so_far (rli), 0);
!       eoc = CEIL (eoc, DECL_ALIGN_UNIT (decl)) * DECL_ALIGN_UNIT (decl);
!       atend |= layout_empty_base (binfo, size_int (eoc), offsets, t);
      }
  
    /* Record the offsets of BINFO and its base subobjects.  */
    record_subobject_offsets (BINFO_TYPE (binfo), 
  			    BINFO_OFFSET (binfo),
  			    offsets, 
  			    /*vbases_p=*/0);
!   return atend;
  }
  
  /* Layout all of the non-virtual base classes.  Record empty
!    subobjects in OFFSETS.  T is the most derived type.  Return
!    nonzero if the type cannot be nearly empty.  */
  
! static bool
! build_base_fields (rli, empty_p, offsets, t)
!      record_layout_info rli;
!      int *empty_p;
!      splay_tree offsets;
!      tree t;
  {
    /* Chain to hold all the new FIELD_DECLs which stand in for base class
       subobjects.  */
!   tree rec = rli->t;
!   int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
    int i;
-   bool atend = 0;
  
    /* The primary base class is always allocated first.  */
!   if (CLASSTYPE_HAS_PRIMARY_BASE_P (rec))
!     build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec), 
! 		      empty_p, offsets, t);
  
    /* Now allocate the rest of the bases.  */
    for (i = 0; i < n_baseclasses; ++i)
      {
        tree base_binfo;
  
!       base_binfo = BINFO_BASETYPE (TYPE_BINFO (rec), i);
  
        /* The primary base was already allocated above, so we don't
  	 need to allocate it again here.  */
!       if (base_binfo == CLASSTYPE_PRIMARY_BINFO (rec))
  	continue;
  
        /* A primary virtual base class is allocated just like any other
  	 base class, but a non-primary virtual base is allocated
  	 later, in layout_virtual_bases.  */
        if (TREE_VIA_VIRTUAL (base_binfo) 
  	  && !BINFO_PRIMARY_P (base_binfo))
  	continue;
  
!       atend |= build_base_field (rli, base_binfo, empty_p, offsets, t);
      }
-   return atend;
  }
  
  /* Go through the TYPE_METHODS of T issuing any appropriate
     diagnostics, figuring out which methods override which other
     methods, and so forth.  */
--- 3816,3947 ----
  	}
      }
    return atend;
  }
  
! /* Layout the the base given by BINFO in the class indicated by RLI.
!    If the new object is non-empty, and EMPTY_P is non-NULL, clear
!    *EMPTY_P.  *BASE_ALIGN is a running maximum of the alignments of
!    any base class.  OFFSETS gives the location of empty base
!    subobjects.  T is the most derived type.  Return nonzero if the new
!    object cannot be nearly-empty.  A new FIELD_DECL is inserted at
!    *NEXT_FIELD, unless BINFO is for an empty base class.  
! 
!    Returns the location at which the next field should be inserted.  */
! 
! static tree *
! build_base_field (record_layout_info rli, tree binfo, int *empty_p, 
! 		  splay_tree offsets, tree *next_field)
  {
+   tree t = rli->t;
    tree basetype = BINFO_TYPE (binfo);
  
    if (!COMPLETE_TYPE_P (basetype))
      /* This error is now reported in xref_tag, thus giving better
         location information.  */
!     return next_field;
    
!   /* Place the base class.  */
!   if (!is_empty_class (basetype))
      {
+       tree decl;
+ 
        /* The containing class is non-empty because it has a non-empty
  	 base class.  */
!       if (empty_p)
! 	*empty_p = 0;
!       
!       /* Create the FIELD_DECL.  */
!       decl = build_decl (FIELD_DECL, NULL_TREE, CLASSTYPE_AS_BASE (basetype));
!       DECL_ARTIFICIAL (decl) = 1;
!       DECL_FIELD_CONTEXT (decl) = t;
!       DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
!       DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
!       DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
!       DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
!       /* Tell the backend not to round up to TYPE_ALIGN.  */
!       DECL_PACKED (decl) = 1;
!   
        /* Try to place the field.  It may take more than one try if we
  	 have a hard time placing the field without putting two
  	 objects of the same type at the same address.  */
!       layout_nonempty_base_or_field (rli, decl, binfo, offsets);
!       /* Add the new FIELD_DECL to the list of fields for T.  */
!       TREE_CHAIN (decl) = *next_field;
!       *next_field = decl;
!       next_field = &TREE_CHAIN (decl);
      }
    else
      {
!       tree eoc;
  
        /* On some platforms (ARM), even empty classes will not be
  	 byte-aligned.  */
!       eoc = round_up (rli_size_unit_so_far (rli),
! 		      CLASSTYPE_ALIGN_UNIT (basetype));
!       if (layout_empty_base (binfo, eoc, offsets, t))
! 	CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
! 
!       /* We do not create a FIELD_DECL for empty base classes because
! 	 it might overlap some other field.  We want to be able to
! 	 create CONSTRUCTORs for the class by iterating over the
! 	 FIELD_DECLs, and the back end does not handle overlapping
! 	 FIELD_DECLs.  */
      }
  
    /* Record the offsets of BINFO and its base subobjects.  */
    record_subobject_offsets (BINFO_TYPE (binfo), 
  			    BINFO_OFFSET (binfo),
  			    offsets, 
  			    /*vbases_p=*/0);
! 
!   return next_field;
  }
  
  /* Layout all of the non-virtual base classes.  Record empty
!    subobjects in OFFSETS.  T is the most derived type.  Return nonzero
!    if the type cannot be nearly empty.  The fields created
!    corresponding to the base classes will be inserted at
!    *NEXT_FIELD.  */
  
! static void
! build_base_fields (record_layout_info rli, int *empty_p, 
! 		   splay_tree offsets, tree *next_field)
  {
    /* Chain to hold all the new FIELD_DECLs which stand in for base class
       subobjects.  */
!   tree t = rli->t;
!   int n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
    int i;
  
    /* The primary base class is always allocated first.  */
!   if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
!     next_field = build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (t),
! 				   empty_p, offsets, next_field);
  
    /* Now allocate the rest of the bases.  */
    for (i = 0; i < n_baseclasses; ++i)
      {
        tree base_binfo;
  
!       base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
  
        /* The primary base was already allocated above, so we don't
  	 need to allocate it again here.  */
!       if (base_binfo == CLASSTYPE_PRIMARY_BINFO (t))
  	continue;
  
        /* A primary virtual base class is allocated just like any other
  	 base class, but a non-primary virtual base is allocated
  	 later, in layout_virtual_bases.  */
        if (TREE_VIA_VIRTUAL (base_binfo) 
  	  && !BINFO_PRIMARY_P (base_binfo))
  	continue;
  
!       next_field = build_base_field (rli, base_binfo, empty_p,
! 				     offsets, next_field);
      }
  }
  
  /* Go through the TYPE_METHODS of T issuing any appropriate
     diagnostics, figuring out which methods override which other
     methods, and so forth.  */
*************** dfs_set_offset_for_unshared_vbases (binf
*** 4565,4604 ****
      }
  
    return NULL_TREE;
  }
  
! /* Set BINFO_OFFSET for all of the virtual bases for T.  Update
     TYPE_ALIGN and TYPE_SIZE for T.  OFFSETS gives the location of
     empty subobjects of T.  */
  
  static void
! layout_virtual_bases (t, offsets)
!      tree t;
!      splay_tree offsets;
  {
!   tree vbases, dsize;
!   unsigned HOST_WIDE_INT eoc;
    bool first_vbase = true;
  
    if (CLASSTYPE_N_BASECLASSES (t) == 0)
      return;
  
  #ifdef STRUCTURE_SIZE_BOUNDARY
!   /* Packed structures don't need to have minimum size.  */
!   if (! TYPE_PACKED (t))
!     TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), STRUCTURE_SIZE_BOUNDARY);
  #endif
  
!   /* DSIZE is the size of the class without the virtual bases.  */
!   if (abi_version_at_least(2))
!     dsize = CLASSTYPE_SIZE (t);
!   else
!     dsize = TYPE_SIZE (t);
! 
!   /* Make every class have alignment of at least one.  */
!   TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT);
  
    /* Go through the virtual bases, allocating space for each virtual
       base that is not already a primary base class.  These are
       allocated in inheritance graph order.  */
    for (vbases = TYPE_BINFO (t);
--- 4628,4672 ----
      }
  
    return NULL_TREE;
  }
  
! /* Set BINFO_OFFSET for all of the virtual bases for RLI->T.  Update
     TYPE_ALIGN and TYPE_SIZE for T.  OFFSETS gives the location of
     empty subobjects of T.  */
  
  static void
! layout_virtual_bases (record_layout_info rli, splay_tree offsets)
  {
!   tree vbases;
!   tree t = rli->t;
    bool first_vbase = true;
+   tree *next_field;
  
    if (CLASSTYPE_N_BASECLASSES (t) == 0)
      return;
  
+   if (!abi_version_at_least(2))
+     {
+       /* In G++ 3.2, we incorrectly rounded the size before laying out
+ 	 the virtual bases.  */
+       finish_record_layout (rli, /*free_p=*/false);
  #ifdef STRUCTURE_SIZE_BOUNDARY
!       /* Packed structures don't need to have minimum size.  */
!       if (! TYPE_PACKED (t))
! 	TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), STRUCTURE_SIZE_BOUNDARY);
  #endif
+       rli->offset = TYPE_SIZE_UNIT (t);
+       rli->bitpos = bitsize_zero_node;
+       rli->record_align = TYPE_ALIGN (t);
+     }
  
!   /* Find the last field.  The artificial fields created for virtual
!      bases will go after the last extant field to date.  */
!   next_field = &TYPE_FIELDS (t);
!   while (*next_field)
!     next_field = &TREE_CHAIN (*next_field);
  
    /* Go through the virtual bases, allocating space for each virtual
       base that is not already a primary base class.  These are
       allocated in inheritance graph order.  */
    for (vbases = TYPE_BINFO (t);
*************** layout_virtual_bases (t, offsets)
*** 4612,4741 ****
  
        vbase = binfo_for_vbase (BINFO_TYPE (vbases), t);
  
        if (!BINFO_PRIMARY_P (vbase))
  	{
  	  /* This virtual base is not a primary base of any class in the
  	     hierarchy, so we have to add space for it.  */
! 	  tree basetype, usize;
! 	  unsigned int desired_align;
! 
! 	  basetype = BINFO_TYPE (vbase);
! 
! 	  desired_align = CLASSTYPE_ALIGN (basetype);
! 	  TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
! 
! 	  /* Add padding so that we can put the virtual base class at an
! 	     appropriately aligned offset.  */
! 	  dsize = round_up (dsize, desired_align);
! 	  usize = size_binop (CEIL_DIV_EXPR, dsize, bitsize_unit_node);
! 
! 	  /* We try to squish empty virtual bases in just like
! 	     ordinary empty bases.  */
! 	  if (is_empty_class (basetype))
! 	    layout_empty_base (vbase,
! 			       convert (sizetype, usize),
! 			       offsets, t);
! 	  else
! 	    {
! 	      tree offset;
! 
! 	      offset = convert (ssizetype, usize);
! 	      offset = size_diffop (offset, 
! 				    convert (ssizetype, 
! 					     BINFO_OFFSET (vbase)));
! 
! 	      /* And compute the offset of the virtual base.  */
! 	      propagate_binfo_offsets (vbase, offset, t);
! 	      /* Every virtual baseclass takes a least a UNIT, so that
! 		 we can take it's address and get something different
! 		 for each base.  */
! 	      dsize = size_binop (PLUS_EXPR, dsize,
! 				  size_binop (MAX_EXPR, bitsize_unit_node,
! 					      CLASSTYPE_SIZE (basetype)));
! 	    }
  
  	  /* If the first virtual base might have been placed at a
  	     lower address, had we started from CLASSTYPE_SIZE, rather
  	     than TYPE_SIZE, issue a warning.  There can be both false
  	     positives and false negatives from this warning in rare
  	     cases; to deal with all the possibilities would probably
  	     require performing both layout algorithms and comparing
  	     the results which is not particularly tractable.  */
  	  if (warn_abi
  	      && first_vbase
! 	      && tree_int_cst_lt (size_binop (CEIL_DIV_EXPR,
! 					      round_up (CLASSTYPE_SIZE (t),
! 							desired_align),
! 					      bitsize_unit_node),
! 				  BINFO_OFFSET (vbase)))
  	    warning ("offset of virtual base `%T' is not ABI-compliant and may change in a future version of GCC",
  		     basetype);
  
- 	  /* Keep track of the offsets assigned to this virtual base.  */
- 	  record_subobject_offsets (BINFO_TYPE (vbase), 
- 				    BINFO_OFFSET (vbase),
- 				    offsets,
- 				    /*vbases_p=*/0);
- 
  	  first_vbase = false;
  	}
      }
  
    /* Now, go through the TYPE_BINFO hierarchy, setting the
       BINFO_OFFSETs correctly for all non-primary copies of the virtual
       bases and their direct and indirect bases.  The ambiguity checks
       in lookup_base depend on the BINFO_OFFSETs being set
       correctly.  */
    dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_unshared_vbases, NULL, t);
- 
-   /* If we had empty base classes that protruded beyond the end of the
-      class, we didn't update DSIZE above; we were hoping to overlay
-      multiple such bases at the same location.  */
-   eoc = end_of_class (t, /*include_virtuals_p=*/1);
-   dsize = size_binop (MAX_EXPR, dsize, bitsize_int (eoc * BITS_PER_UNIT));
- 
-   /* Now, make sure that the total size of the type is a multiple of
-      its alignment.  */
-   dsize = round_up (dsize, TYPE_ALIGN (t));
-   TYPE_SIZE (t) = dsize;
-   TYPE_SIZE_UNIT (t) = convert (sizetype,
- 				size_binop (CEIL_DIV_EXPR, TYPE_SIZE (t),
- 					    bitsize_unit_node));
- 
-   /* Check for ambiguous virtual bases.  */
-   if (extra_warnings)
-     for (vbases = CLASSTYPE_VBASECLASSES (t); 
- 	 vbases; 
- 	 vbases = TREE_CHAIN (vbases))
-       {
- 	tree basetype = BINFO_TYPE (TREE_VALUE (vbases));
- 	
- 	if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
- 	  warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
- 		      basetype, t);
-       }
  }
  
  /* Returns the offset of the byte just past the end of the base class
     with the highest offset in T.  If INCLUDE_VIRTUALS_P is zero, then
     only non-virtual bases are included.  */
  
! static unsigned HOST_WIDE_INT
  end_of_class (t, include_virtuals_p)
       tree t;
       int include_virtuals_p;
  {
!   unsigned HOST_WIDE_INT result = 0;
    int i;
  
    for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
      {
        tree base_binfo;
        tree offset;
        tree size;
-       unsigned HOST_WIDE_INT end_of_base;
  
        base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
  
        if (!include_virtuals_p
  	  && TREE_VIA_VIRTUAL (base_binfo) 
--- 4680,4743 ----
  
        vbase = binfo_for_vbase (BINFO_TYPE (vbases), t);
  
        if (!BINFO_PRIMARY_P (vbase))
  	{
+ 	  tree basetype = TREE_TYPE (vbase);
+ 
  	  /* This virtual base is not a primary base of any class in the
  	     hierarchy, so we have to add space for it.  */
! 	  next_field = build_base_field (rli, vbase, /*empty_p=*/NULL, 
! 					 offsets, next_field);
  
  	  /* If the first virtual base might have been placed at a
  	     lower address, had we started from CLASSTYPE_SIZE, rather
  	     than TYPE_SIZE, issue a warning.  There can be both false
  	     positives and false negatives from this warning in rare
  	     cases; to deal with all the possibilities would probably
  	     require performing both layout algorithms and comparing
  	     the results which is not particularly tractable.  */
  	  if (warn_abi
  	      && first_vbase
! 	      && (tree_int_cst_lt 
! 		  (size_binop (CEIL_DIV_EXPR,
! 			       round_up (CLASSTYPE_SIZE (t),
! 					 CLASSTYPE_ALIGN (basetype)),
! 			       bitsize_unit_node),
! 		   BINFO_OFFSET (vbase))))
  	    warning ("offset of virtual base `%T' is not ABI-compliant and may change in a future version of GCC",
  		     basetype);
  
  	  first_vbase = false;
  	}
      }
  
    /* Now, go through the TYPE_BINFO hierarchy, setting the
       BINFO_OFFSETs correctly for all non-primary copies of the virtual
       bases and their direct and indirect bases.  The ambiguity checks
       in lookup_base depend on the BINFO_OFFSETs being set
       correctly.  */
    dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_unshared_vbases, NULL, t);
  }
  
  /* Returns the offset of the byte just past the end of the base class
     with the highest offset in T.  If INCLUDE_VIRTUALS_P is zero, then
     only non-virtual bases are included.  */
  
! static tree
  end_of_class (t, include_virtuals_p)
       tree t;
       int include_virtuals_p;
  {
!   tree result = size_zero_node;
    int i;
  
    for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
      {
        tree base_binfo;
        tree offset;
        tree size;
  
        base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
  
        if (!include_virtuals_p
  	  && TREE_VIA_VIRTUAL (base_binfo) 
*************** end_of_class (t, include_virtuals_p)
*** 4750,4791 ****
        else
  	size = CLASSTYPE_SIZE_UNIT (BINFO_TYPE (base_binfo));
        offset = size_binop (PLUS_EXPR, 
  			   BINFO_OFFSET (base_binfo),
  			   size);
!       end_of_base = tree_low_cst (offset, /*pos=*/1);
!       if (end_of_base > result)
! 	result = end_of_base;
      }
  
    return result;
  }
  
! /* Warn about direct bases of T that are inaccessible because they are
     ambiguous.  For example:
  
       struct S {};
       struct T : public S {};
       struct U : public S, public T {};
  
     Here, `(S*) new U' is not allowed because there are two `S'
     subobjects of U.  */
  
  static void
! warn_about_ambiguous_direct_bases (t)
       tree t;
  {
    int i;
  
    for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
      {
!       tree basetype = TYPE_BINFO_BASETYPE (t, i);
  
        if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
  	warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
! 		    basetype, t);
      }
  }
  
  /* Compare two INTEGER_CSTs K1 and K2.  */
  
  static int
--- 4752,4808 ----
        else
  	size = CLASSTYPE_SIZE_UNIT (BINFO_TYPE (base_binfo));
        offset = size_binop (PLUS_EXPR, 
  			   BINFO_OFFSET (base_binfo),
  			   size);
!       if (INT_CST_LT_UNSIGNED (result, offset))
! 	result = offset;
      }
  
    return result;
  }
  
! /* Warn about bases of T that are inaccessible because they are
     ambiguous.  For example:
  
       struct S {};
       struct T : public S {};
       struct U : public S, public T {};
  
     Here, `(S*) new U' is not allowed because there are two `S'
     subobjects of U.  */
  
  static void
! warn_about_ambiguous_bases (t)
       tree t;
  {
    int i;
+   tree vbases;
+   tree basetype;
  
+   /* Check direct bases.  */
    for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
      {
!       basetype = TYPE_BINFO_BASETYPE (t, i);
  
        if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
  	warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
! 		 basetype, t);
      }
+ 
+   /* Check for ambiguous virtual bases.  */
+   if (extra_warnings)
+     for (vbases = CLASSTYPE_VBASECLASSES (t); 
+ 	 vbases; 
+ 	 vbases = TREE_CHAIN (vbases))
+       {
+ 	basetype = BINFO_TYPE (TREE_VALUE (vbases));
+ 	
+ 	if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
+ 	  warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
+ 		   basetype, t);
+       }
  }
  
  /* Compare two INTEGER_CSTs K1 and K2.  */
  
  static int
*************** splay_tree_compare_integer_csts (k1, k2)
*** 4794,4803 ****
--- 4811,4843 ----
       splay_tree_key k2;
  {
    return tree_int_cst_compare ((tree) k1, (tree) k2);
  }
  
+ /* Increase the size indicated in RLI to account for empty classes
+    that are "off the end" of the class.  */
+ 
+ static void
+ include_empty_classes (record_layout_info rli)
+ {
+   tree eoc;
+ 
+   /* It might be the case that we grew the class to allocate a
+      zero-sized base class.  That won't be reflected in RLI, yet,
+      because we are willing to overlay multiple bases at the same
+      offset.  However, now we need to make sure that RLI is big enough
+      to reflect the entire class.  */
+   eoc = end_of_class (rli->t, 
+ 		      CLASSTYPE_AS_BASE (rli->t) != NULL_TREE);
+   if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST
+       && INT_CST_LT_UNSIGNED (rli_size_unit_so_far (rli), eoc))
+     {
+       rli->offset = size_binop (MAX_EXPR, rli->offset, eoc);
+       rli->bitpos = bitsize_zero_node;
+     }
+ }
+ 
  /* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T.  Calculate
     BINFO_OFFSETs for all of the base-classes.  Position the vtable
     pointer.  Accumulate declared virtual functions on VIRTUALS_P.  */
  
  static void
*************** layout_class_type (t, empty_p, vfuns_p, 
*** 4809,4824 ****
  {
    tree non_static_data_members;
    tree field;
    tree vptr;
    record_layout_info rli;
-   unsigned HOST_WIDE_INT eoc;
    /* Maps offsets (represented as INTEGER_CSTs) to a TREE_LIST of
       types that appear at that offset.  */
    splay_tree empty_base_offsets;
    /* True if the last field layed out was a bit-field.  */
    bool last_field_was_bitfield = false;
  
    /* Keep track of the first non-static data member.  */
    non_static_data_members = TYPE_FIELDS (t);
  
    /* Start laying out the record.  */
--- 4849,4867 ----
  {
    tree non_static_data_members;
    tree field;
    tree vptr;
    record_layout_info rli;
    /* Maps offsets (represented as INTEGER_CSTs) to a TREE_LIST of
       types that appear at that offset.  */
    splay_tree empty_base_offsets;
    /* True if the last field layed out was a bit-field.  */
    bool last_field_was_bitfield = false;
+   /* The location at which the next field should be inserted.  */
+   tree *next_field;
+   /* T, as a base class.  */
+   tree base_t;
  
    /* Keep track of the first non-static data member.  */
    non_static_data_members = TYPE_FIELDS (t);
  
    /* Start laying out the record.  */
*************** layout_class_type (t, empty_p, vfuns_p, 
*** 4832,4850 ****
    vptr = create_vtable_ptr (t, empty_p, virtuals_p);
  
    /* The vptr is always the first thing in the class.  */
    if (vptr)
      {
!       TYPE_FIELDS (t) = chainon (vptr, TYPE_FIELDS (t));
        place_field (rli, vptr);
      }
  
    /* Build FIELD_DECLs for all of the non-virtual base-types.  */
    empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts, 
  				       NULL, NULL);
!   if (build_base_fields (rli, empty_p, empty_base_offsets, t))
!     CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
    
    /* Layout the non-static data members.  */
    for (field = non_static_data_members; field; field = TREE_CHAIN (field))
      {
        tree type;
--- 4875,4896 ----
    vptr = create_vtable_ptr (t, empty_p, virtuals_p);
  
    /* The vptr is always the first thing in the class.  */
    if (vptr)
      {
!       TREE_CHAIN (vptr) = TYPE_FIELDS (t);
!       TYPE_FIELDS (t) = vptr;
!       next_field = &TREE_CHAIN (vptr);
        place_field (rli, vptr);
      }
+   else
+     next_field = &TYPE_FIELDS (t);
  
    /* Build FIELD_DECLs for all of the non-virtual base-types.  */
    empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts, 
  				       NULL, NULL);
!   build_base_fields (rli, empty_p, empty_base_offsets, next_field);
    
    /* Layout the non-static data members.  */
    for (field = non_static_data_members; field; field = TREE_CHAIN (field))
      {
        tree type;
*************** layout_class_type (t, empty_p, vfuns_p, 
*** 4915,4925 ****
  	}
        else
  	padding = NULL_TREE;
  
        layout_nonempty_base_or_field (rli, field, NULL_TREE,
! 				     empty_base_offsets, t);
  
        /* If a bit-field does not immediately follow another bit-field,
  	 and yet it starts in the middle of a byte, we have failed to
  	 comply with the ABI.  */
        if (warn_abi
--- 4961,4971 ----
  	}
        else
  	padding = NULL_TREE;
  
        layout_nonempty_base_or_field (rli, field, NULL_TREE,
! 				     empty_base_offsets);
  
        /* If a bit-field does not immediately follow another bit-field,
  	 and yet it starts in the middle of a byte, we have failed to
  	 comply with the ABI.  */
        if (warn_abi
*************** layout_class_type (t, empty_p, vfuns_p, 
*** 4955,5049 ****
  	  DECL_SIZE (padding_field) = padding;
  	  DECL_ALIGN (padding_field) = 1;
  	  DECL_USER_ALIGN (padding_field) = 0;
  	  layout_nonempty_base_or_field (rli, padding_field,
  					 NULL_TREE, 
! 					 empty_base_offsets, t);
  	}
  
        last_field_was_bitfield = DECL_C_BIT_FIELD (field);
      }
  
!   /* It might be the case that we grew the class to allocate a
!      zero-sized base class.  That won't be reflected in RLI, yet,
!      because we are willing to overlay multiple bases at the same
!      offset.  However, now we need to make sure that RLI is big enough
!      to reflect the entire class.  */
!   eoc = end_of_class (t, /*include_virtuals_p=*/0);
!   if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST
!       && compare_tree_int (rli_size_unit_so_far (rli), eoc) < 0)
!     {
!       rli->offset = size_binop (MAX_EXPR, rli->offset, size_int (eoc));
!       rli->bitpos = bitsize_zero_node;
!     }
! 
!   /* We make all structures have at least one element, so that they
!      have nonzero size.  The class may be empty even if it has
!      basetypes.  Therefore, we add the fake field after all the other
!      fields; if there are already FIELD_DECLs on the list, their
!      offsets will not be disturbed.  */
!   if (!eoc && *empty_p)
!     {
!       tree padding;
! 
!       padding = build_decl (FIELD_DECL, NULL_TREE, char_type_node);
!       place_field (rli, padding);
!     } 
!   else if (abi_version_at_least (2)
! 	   && !integer_zerop (rli->bitpos))
      /* Make sure that we are on a byte boundary so that the size of
         the class without virtual bases will always be a round number
         of bytes.  */
      rli->bitpos = round_up (rli->bitpos, BITS_PER_UNIT);
!   
!   /* Let the back-end lay out the type. Note that at this point we
!      have only included non-virtual base-classes; we will lay out the
!      virtual base classes later.  So, the TYPE_SIZE/TYPE_ALIGN after
!      this call are not necessarily correct; they are just the size and
!      alignment when no virtual base clases are used.  */
!   finish_record_layout (rli);
  
    /* Delete all zero-width bit-fields from the list of fields.  Now
       that the type is laid out they are no longer important.  */
    remove_zero_width_bit_fields (t);
  
!   /* Remember the size and alignment of the class before adding
!      the virtual bases.  */
!   if (*empty_p)
      {
!       CLASSTYPE_SIZE (t) = bitsize_zero_node;
!       CLASSTYPE_SIZE_UNIT (t) = size_zero_node;
!     }
!   /* If this is a POD, we can't reuse its tail padding.  */
!   else if (!CLASSTYPE_NON_POD_P (t))
!     {
!       CLASSTYPE_SIZE (t) = TYPE_SIZE (t);
!       CLASSTYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (t);
      }
    else
!     {
!       CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t);
!       CLASSTYPE_SIZE_UNIT (t) = TYPE_BINFO_SIZE_UNIT (t);
!     }
! 
!   CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t);
!   CLASSTYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (t);
  
    /* Set the TYPE_DECL for this type to contain the right
       value for DECL_OFFSET, so that we can use it as part
       of a COMPONENT_REF for multiple inheritance.  */
    layout_decl (TYPE_MAIN_DECL (t), 0);
  
    /* Now fix up any virtual base class types that we left lying
       around.  We must get these done before we try to lay out the
       virtual function table.  As a side-effect, this will remove the
       base subobject fields.  */
!   layout_virtual_bases (t, empty_base_offsets);
  
!   /* Warn about direct bases that can't be talked about due to
!      ambiguity.  */
!   warn_about_ambiguous_direct_bases (t);
  
    /* Clean up.  */
    splay_tree_delete (empty_base_offsets);
  }
  
--- 5001,5089 ----
  	  DECL_SIZE (padding_field) = padding;
  	  DECL_ALIGN (padding_field) = 1;
  	  DECL_USER_ALIGN (padding_field) = 0;
  	  layout_nonempty_base_or_field (rli, padding_field,
  					 NULL_TREE, 
! 					 empty_base_offsets);
  	}
  
        last_field_was_bitfield = DECL_C_BIT_FIELD (field);
      }
  
!   if (abi_version_at_least (2) && !integer_zerop (rli->bitpos))
      /* Make sure that we are on a byte boundary so that the size of
         the class without virtual bases will always be a round number
         of bytes.  */
      rli->bitpos = round_up (rli->bitpos, BITS_PER_UNIT);
! 
!   /* Make sure that empty classes are reflected in RLI at this 
!      point.  */
!   include_empty_classes(rli);
  
    /* Delete all zero-width bit-fields from the list of fields.  Now
       that the type is laid out they are no longer important.  */
    remove_zero_width_bit_fields (t);
  
!   /* Create the version of T used for virtual bases.  We do not use
!      make_aggr_type for this version; this is an artificial type.  For
!      a POD type, we just reuse T.  */
!   if (CLASSTYPE_NON_POD_P (t) || *empty_p)
      {
!       base_t = make_node (TREE_CODE (t));
!       
!       /* Set the size and alignment for the new type.  */
!       TYPE_SIZE (base_t) = rli_size_so_far (rli);
!       TYPE_SIZE_UNIT (base_t) = rli_size_unit_so_far (rli);
!       TYPE_ALIGN (base_t) = rli->record_align;
!       TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t);
! 
!       /* Copy the fields from T.  */
!       next_field = &TYPE_FIELDS (base_t);
!       for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
! 	if (TREE_CODE (field) == FIELD_DECL)
! 	  {
! 	    *next_field = build_decl (FIELD_DECL,
! 				      DECL_NAME (field), 
! 				      TREE_TYPE (field));
! 	    DECL_CONTEXT (*next_field) = base_t;
! 	    DECL_FIELD_OFFSET (*next_field) = DECL_FIELD_OFFSET (field);
! 	    DECL_FIELD_BIT_OFFSET (*next_field)
! 	      = DECL_FIELD_BIT_OFFSET (field);
! 	    next_field = &TREE_CHAIN (*next_field);
! 	  }
! 
!       /* Record the base version of the type.  */
!       CLASSTYPE_AS_BASE (t) = base_t;
      }
    else
!     CLASSTYPE_AS_BASE (t) = t;
  
    /* Set the TYPE_DECL for this type to contain the right
       value for DECL_OFFSET, so that we can use it as part
       of a COMPONENT_REF for multiple inheritance.  */
    layout_decl (TYPE_MAIN_DECL (t), 0);
  
    /* Now fix up any virtual base class types that we left lying
       around.  We must get these done before we try to lay out the
       virtual function table.  As a side-effect, this will remove the
       base subobject fields.  */
!   layout_virtual_bases (rli, empty_base_offsets);
! 
!   /* Make sure that empty classes are reflected in RLI at this 
!      point.  */
!   include_empty_classes(rli);
! 
!   /* Make sure not to create any structures with zero size.  */
!   if (integer_zerop (rli_size_unit_so_far (rli)) && *empty_p)
!     place_field (rli, 
! 		 build_decl (FIELD_DECL, NULL_TREE, char_type_node));
! 
!   /* Let the back-end lay out the type.  */
!   finish_record_layout (rli, /*free_p=*/true);
  
!   /* Warn about bases that can't be talked about due to ambiguity.  */
!   warn_about_ambiguous_bases (t);
  
    /* Clean up.  */
    splay_tree_delete (empty_base_offsets);
  }
  
*************** contains_empty_class_p (tree type)
*** 6412,6422 ****
  
        for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
  	if (contains_empty_class_p (TYPE_BINFO_BASETYPE (type, i)))
  	  return true;
        for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
! 	if (contains_empty_class_p (TREE_TYPE (field)))
  	  return true;
      }
    else if (TREE_CODE (type) == ARRAY_TYPE)
      return contains_empty_class_p (TREE_TYPE (type));
    return false;
--- 6452,6464 ----
  
        for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
  	if (contains_empty_class_p (TYPE_BINFO_BASETYPE (type, i)))
  	  return true;
        for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
! 	if (TREE_CODE (field) == FIELD_DECL
! 	    && !DECL_ARTIFICIAL (field)
! 	    && is_empty_class (TREE_TYPE (field)))
  	  return true;
      }
    else if (TREE_CODE (type) == ARRAY_TYPE)
      return contains_empty_class_p (TREE_TYPE (type));
    return false;
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.752
diff -c -5 -p -r1.752 cp-tree.h
*** cp/cp-tree.h	23 Sep 2002 09:22:14 -0000	1.752
--- cp/cp-tree.h	30 Sep 2002 16:04:46 -0000
*************** struct diagnostic_context;
*** 57,66 ****
--- 57,67 ----
        (TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
        TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (in _TYPE).
        INHERITED_VALUE_BINDING_P (in CPLUS_BINDING)
        ICS_ELLIPSIS_FLAG (in _CONV)
        BINFO_ACCESS (in BINFO)
+       DECL_INITIALIZED_P (in VAR_DECL)
     2: IDENTIFIER_OPNAME_P.
        TYPE_POLYMORPHIC_P (in _TYPE)
        ICS_THIS_FLAG (in _CONV)
        BINDING_HAS_LEVEL_P (in CPLUS_BINDING)
        BINFO_LOST_PRIMARY_P (in BINFO)
*************** struct diagnostic_context;
*** 94,108 ****
        DECL_TEMPLATE_PARM_P (in PARM_DECL, CONST_DECL, TYPE_DECL, or TEMPLATE_DECL)
        DECL_LOCAL_FUNCTION_P (in FUNCTION_DECL)
        DECL_MUTABLE_P (in FIELD_DECL)
     1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
        DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
-       DECL_C_BITFIELD (in FIELD_DECL)
     2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
        DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
     3: DECL_IN_AGGR_P.
!    4: DECL_C_BIT_FIELD
     5: DECL_INTERFACE_KNOWN.
     6: DECL_THIS_STATIC (in VAR_DECL or FUNCTION_DECL).
     7: DECL_DEAD_FOR_LOCAL (in VAR_DECL).
        DECL_THUNK_P (in a member FUNCTION_DECL)
  
--- 95,108 ----
        DECL_TEMPLATE_PARM_P (in PARM_DECL, CONST_DECL, TYPE_DECL, or TEMPLATE_DECL)
        DECL_LOCAL_FUNCTION_P (in FUNCTION_DECL)
        DECL_MUTABLE_P (in FIELD_DECL)
     1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
        DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
     2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
        DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
     3: DECL_IN_AGGR_P.
!    4: DECL_C_BIT_FIELD (in a FIELD_DECL)
     5: DECL_INTERFACE_KNOWN.
     6: DECL_THIS_STATIC (in VAR_DECL or FUNCTION_DECL).
     7: DECL_DEAD_FOR_LOCAL (in VAR_DECL).
        DECL_THUNK_P (in a member FUNCTION_DECL)
  
*************** struct lang_type_class GTY(())
*** 1148,1159 ****
  
    tree primary_base;
    tree vfields;
    tree vbases;
    tree tags;
!   tree size;
!   tree size_unit;
    tree pure_virtuals;
    tree friend_classes;
    tree rtti;
    tree methods;
    tree template_info;
--- 1148,1158 ----
  
    tree primary_base;
    tree vfields;
    tree vbases;
    tree tags;
!   tree as_base;
    tree pure_virtuals;
    tree friend_classes;
    tree rtti;
    tree methods;
    tree template_info;
*************** struct lang_type GTY(())
*** 1394,1409 ****
  
  /* Number of direct baseclasses of NODE.  */
  #define CLASSTYPE_N_BASECLASSES(NODE) \
    (BINFO_N_BASETYPES (TYPE_BINFO (NODE)))
  
  /* These are the size and alignment of the type without its virtual
     base classes, for when we use this type as a base itself.  */
! #define CLASSTYPE_SIZE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->size)
! #define CLASSTYPE_SIZE_UNIT(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->size_unit)
! #define CLASSTYPE_ALIGN(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->align)
! #define CLASSTYPE_USER_ALIGN(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->user_align)
  
  /* The alignment of NODE, without its virtual bases, in bytes.  */
  #define CLASSTYPE_ALIGN_UNIT(NODE) \
    (CLASSTYPE_ALIGN (NODE) / BITS_PER_UNIT)
  
--- 1393,1413 ----
  
  /* Number of direct baseclasses of NODE.  */
  #define CLASSTYPE_N_BASECLASSES(NODE) \
    (BINFO_N_BASETYPES (TYPE_BINFO (NODE)))
  
+ /* The type corresponding to NODE when NODE is used as a base class,
+    i.e., NODE without virtual base classes.  */
+ 
+ #define CLASSTYPE_AS_BASE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->as_base)
+ 
  /* These are the size and alignment of the type without its virtual
     base classes, for when we use this type as a base itself.  */
! #define CLASSTYPE_SIZE(NODE) TYPE_SIZE (CLASSTYPE_AS_BASE (NODE))
! #define CLASSTYPE_SIZE_UNIT(NODE) TYPE_SIZE_UNIT (CLASSTYPE_AS_BASE (NODE))
! #define CLASSTYPE_ALIGN(NODE) TYPE_ALIGN (CLASSTYPE_AS_BASE (NODE))
! #define CLASSTYPE_USER_ALIGN(NODE) TYPE_USER_ALIGN (CLASSTYPE_AS_BASE (NODE))
  
  /* The alignment of NODE, without its virtual bases, in bytes.  */
  #define CLASSTYPE_ALIGN_UNIT(NODE) \
    (CLASSTYPE_ALIGN (NODE) / BITS_PER_UNIT)
  
*************** struct lang_decl GTY(())
*** 1952,1961 ****
--- 1956,1970 ----
     detecting circularity in case members are multiply defined.  In the
     case of a VAR_DECL, it is also used to determine how program storage
     should be allocated.  */
  #define DECL_IN_AGGR_P(NODE) (DECL_LANG_FLAG_3 (NODE))
  
+ /* Nonzero for a VAR_DECL means that the variable's initialization has
+    been processed.  */
+ #define DECL_INITIALIZED_P(NODE) \
+    (TREE_LANG_FLAG_1 (VAR_DECL_CHECK (NODE)))
+ 
  /* Nonzero if the DECL was initialized in the class definition itself,
     rather than outside the class.  */
  #define DECL_INITIALIZED_IN_CLASS_P(DECL) \
   (DECL_LANG_SPECIFIC (DECL)->decl_flags.initialized_in_class)
  
*************** extern void mark_all_runtime_matches    
*** 3848,3858 ****
  extern int nothrow_libfn_p			PARAMS ((tree));
  extern void check_handlers			PARAMS ((tree));
  extern void choose_personality_routine		PARAMS ((enum languages));
  
  /* in expr.c */
- extern int extract_init				PARAMS ((tree, tree));
  extern rtx cxx_expand_expr			PARAMS ((tree, rtx,
  							 enum machine_mode,
  							 int));
  extern tree cplus_expand_constant               PARAMS ((tree));
  
--- 3857,3866 ----
*************** extern tree expand_member_init			PARAMS 
*** 3868,3878 ****
  extern tree build_aggr_init			PARAMS ((tree, tree, int));
  extern tree build_init				PARAMS ((tree, tree, int));
  extern int is_aggr_type				PARAMS ((tree, int));
  extern tree get_aggr_from_typedef		PARAMS ((tree, int));
  extern tree get_type_value			PARAMS ((tree));
! extern tree build_forced_zero_init		PARAMS ((tree));
  extern tree build_member_call			PARAMS ((tree, tree, tree));
  extern tree build_offset_ref			PARAMS ((tree, tree));
  extern tree resolve_offset_ref			PARAMS ((tree));
  extern tree build_new				PARAMS ((tree, tree, tree, int));
  extern tree build_vec_init			PARAMS ((tree, tree, int));
--- 3876,3886 ----
  extern tree build_aggr_init			PARAMS ((tree, tree, int));
  extern tree build_init				PARAMS ((tree, tree, int));
  extern int is_aggr_type				PARAMS ((tree, int));
  extern tree get_aggr_from_typedef		PARAMS ((tree, int));
  extern tree get_type_value			PARAMS ((tree));
! extern tree build_zero_init       		(tree, bool);
  extern tree build_member_call			PARAMS ((tree, tree, tree));
  extern tree build_offset_ref			PARAMS ((tree, tree));
  extern tree resolve_offset_ref			PARAMS ((tree));
  extern tree build_new				PARAMS ((tree, tree, tree, int));
  extern tree build_vec_init			PARAMS ((tree, tree, int));
*************** extern void cxx_incomplete_type_error		P
*** 4342,4352 ****
  extern tree error_not_base_type			PARAMS ((tree, tree));
  extern tree binfo_or_else			PARAMS ((tree, tree));
  extern void readonly_error			PARAMS ((tree, const char *, int));
  extern int abstract_virtuals_error		PARAMS ((tree, tree));
  
- extern tree force_store_init_value		PARAMS ((tree, tree));
  extern tree store_init_value			PARAMS ((tree, tree));
  extern tree digest_init				PARAMS ((tree, tree, tree *));
  extern tree build_scoped_ref			PARAMS ((tree, tree, tree *));
  extern tree build_x_arrow			PARAMS ((tree));
  extern tree build_m_component_ref		PARAMS ((tree, tree));
--- 4350,4359 ----
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.936
diff -c -5 -p -r1.936 decl.c
*** cp/decl.c	21 Sep 2002 12:51:53 -0000	1.936
--- cp/decl.c	30 Sep 2002 16:04:49 -0000
*************** static void storedecls PARAMS ((tree));
*** 65,75 ****
  static void require_complete_types_for_parms PARAMS ((tree));
  static int ambi_op_p PARAMS ((enum tree_code));
  static int unary_op_p PARAMS ((enum tree_code));
  static tree store_bindings PARAMS ((tree, tree));
  static tree lookup_tag_reverse PARAMS ((tree, tree));
- static tree obscure_complex_init PARAMS ((tree, tree));
  static tree lookup_name_real PARAMS ((tree, int, int, int));
  static void push_local_name PARAMS ((tree));
  static void warn_extern_redeclared_static PARAMS ((tree, tree));
  static tree grok_reference_init PARAMS ((tree, tree, tree));
  static tree grokfndecl PARAMS ((tree, tree, tree, tree, int,
--- 65,74 ----
*************** duplicate_decls (newdecl, olddecl)
*** 3458,3468 ****
        if (TREE_CODE (newdecl) == TYPE_DECL
  	  && newtype == DECL_ORIGINAL_TYPE (newdecl))
  	newtype = oldtype;
  
        if (TREE_CODE (newdecl) == VAR_DECL)
! 	DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
        /* Do this after calling `merge_types' so that default
  	 parameters don't confuse us.  */
        else if (TREE_CODE (newdecl) == FUNCTION_DECL
  	  && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
  	      != TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl))))
--- 3457,3471 ----
        if (TREE_CODE (newdecl) == TYPE_DECL
  	  && newtype == DECL_ORIGINAL_TYPE (newdecl))
  	newtype = oldtype;
  
        if (TREE_CODE (newdecl) == VAR_DECL)
! 	{
! 	  DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
! 	  DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
! 	}
! 
        /* Do this after calling `merge_types' so that default
  	 parameters don't confuse us.  */
        else if (TREE_CODE (newdecl) == FUNCTION_DECL
  	  && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
  	      != TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl))))
*************** grok_reference_init (decl, type, init)
*** 7546,7594 ****
    DECL_INITIAL (decl) = tmp;
  
    return NULL_TREE;
  }
  
- /* Fill in DECL_INITIAL with some magical value to prevent expand_decl from
-    mucking with forces it does not comprehend (i.e. initialization with a
-    constructor).  If we are at global scope and won't go into COMMON, fill
-    it in with a dummy CONSTRUCTOR to force the variable into .data;
-    otherwise we can use error_mark_node.  */
- 
- static tree
- obscure_complex_init (decl, init)
-      tree decl, init;
- {
-   if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
-     {
-       error ("run-time initialization of thread-local storage");
-       return NULL_TREE;
-     }
- 
-   if (! flag_no_inline && TREE_STATIC (decl))
-     {
-       if (extract_init (decl, init))
- 	return NULL_TREE;
-     }
- 
- #if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
-   if (toplevel_bindings_p () && ! DECL_COMMON (decl))
-     DECL_INITIAL (decl) = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE,
- 				 NULL_TREE);
-   else
- #endif
-     {
-       if (zero_init_p (TREE_TYPE (decl)))
- 	DECL_INITIAL (decl) = error_mark_node;
-       /* Otherwise, force_store_init_value will have already stored a
- 	 zero-init initializer in DECL_INITIAL, that should be
- 	 retained.  */
-     }
- 
-   return init;
- }
- 
  /* When parsing `int a[] = {1, 2};' we don't know the size of the
     array until we finish parsing the initializer.  If that's the
     situation we're in, update DECL accordingly.  */
  
  static void
--- 7549,7558 ----
*************** check_for_uninitialized_const_var (decl)
*** 7771,7791 ****
  static tree
  check_initializer (decl, init)
       tree decl;
       tree init;
  {
!   tree type;
! 
!   if (TREE_CODE (decl) == FIELD_DECL)
!     return init;
! 
!   type = TREE_TYPE (decl);
  
    /* If `start_decl' didn't like having an initialization, ignore it now.  */
    if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
      init = NULL_TREE;
  
    /* Check the initializer.  */
    if (init)
      {
        /* Things that are going to be initialized need to have complete
  	 type.  */
--- 7735,7756 ----
  static tree
  check_initializer (decl, init)
       tree decl;
       tree init;
  {
!   tree type = TREE_TYPE (decl);
  
    /* If `start_decl' didn't like having an initialization, ignore it now.  */
    if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
      init = NULL_TREE;
  
+   /* If an initializer is present, DECL_INITIAL has been
+      error_mark_node, to indicate that an as-of-yet unevaluated
+      initialization will occur.  From now on, DECL_INITIAL reflects
+      the static initialization -- if any -- of DECL.  */
+   DECL_INITIAL (decl) = NULL_TREE;
+ 
    /* Check the initializer.  */
    if (init)
      {
        /* Things that are going to be initialized need to have complete
  	 type.  */
*************** check_initializer (decl, init)
*** 7821,7845 ****
  
        my_friendly_assert (init != NULL_TREE, 149);
        init = NULL_TREE;
      }
    else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
!     {
!       init = grok_reference_init (decl, type, init);
!       if (init)
! 	init = obscure_complex_init (decl, init);
!     }
!   else if (!DECL_EXTERNAL (decl) && !zero_init_p (type))
!     {
!       force_store_init_value (decl, build_forced_zero_init (type));
! 
!       if (init)
! 	goto process_init;
!     }
    else if (init)
      {
-     process_init:
        if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
  	{
  	  if (TREE_CODE (type) == ARRAY_TYPE)
  	    init = digest_init (type, init, (tree *) 0);
  	  else if (TREE_CODE (init) == CONSTRUCTOR
--- 7786,7798 ----
  
        my_friendly_assert (init != NULL_TREE, 149);
        init = NULL_TREE;
      }
    else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
!     init = grok_reference_init (decl, type, init);
    else if (init)
      {
        if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
  	{
  	  if (TREE_CODE (type) == ARRAY_TYPE)
  	    init = digest_init (type, init, (tree *) 0);
  	  else if (TREE_CODE (init) == CONSTRUCTOR
*************** check_initializer (decl, init)
*** 7859,7873 ****
  	{
  	dont_use_constructor:
  	  if (TREE_CODE (init) != TREE_VEC)
  	    init = store_init_value (decl, init);
  	}
- 
-       if (init)
- 	/* We must hide the initializer so that expand_decl
- 	   won't try to do something it does not understand.  */
- 	init = obscure_complex_init (decl, init);
      }
    else if (DECL_EXTERNAL (decl))
      ;
    else if (TYPE_P (type)
  	   && (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
--- 7812,7821 ----
*************** check_initializer (decl, init)
*** 7882,7895 ****
  	    error ("structure `%D' with uninitialized reference members",
  		      decl);
  	}
  
        check_for_uninitialized_const_var (decl);
- 
-       if (COMPLETE_TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
- 	init = obscure_complex_init (decl, NULL_TREE);
- 
      }
    else
      check_for_uninitialized_const_var (decl);
  
    return init;
--- 7830,7839 ----
*************** cp_finish_decl (decl, init, asmspec_tree
*** 8253,8266 ****
  	 grokclassfn.  Lay this out fresh.  */
        SET_DECL_RTL (TREE_TYPE (decl), NULL_RTX);
        SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
        make_decl_rtl (decl, asmspec);
      }
! 
!   /* Deduce size of array from initialization, if not already known.  */
!   init = check_initializer (decl, init);
!   maybe_deduce_size_from_array_init (decl, init);
  
    /* Add this declaration to the statement-tree.  This needs to happen
       after the call to check_initializer so that the DECL_STMT for a
       reference temp is added before the DECL_STMT for the reference itself.  */
    if (building_stmt_tree ()
--- 8197,8254 ----
  	 grokclassfn.  Lay this out fresh.  */
        SET_DECL_RTL (TREE_TYPE (decl), NULL_RTX);
        SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
        make_decl_rtl (decl, asmspec);
      }
!   else if (TREE_CODE (decl) == RESULT_DECL)
!     init = check_initializer (decl, init);
!   else if (TREE_CODE (decl) == VAR_DECL)
!     {
!       /* Only PODs can have thread-local storage.  Other types may require
! 	 various kinds of non-trivial initialization.  */
!       if (DECL_THREAD_LOCAL (decl) && !pod_type_p (TREE_TYPE (decl)))
! 	error ("`%D' cannot be thread-local because it has non-POD type `%T'",
! 	       decl, TREE_TYPE (decl));
!       /* Convert the initializer to the type of DECL, if we have not
! 	 already initialized DECL.  */
!       if (!DECL_INITIALIZED_P (decl)
! 	  /* If !DECL_EXTERNAL then DECL is being defined.  In the
! 	     case of a static data memberm initialized inside the
! 	     class-specifier, there can be an initializer even if DECL
! 	     is *not* defined.  */
! 	  && (!DECL_EXTERNAL (decl) || init))
! 	{
! 	  init = check_initializer (decl, init);
! 	  /* If DECL has an array type without a specific bound, deduce the
! 	     array size from the initializer.  Note that this must be done
! 	     after check_initializer is called because of cases like this:
! 	     
!  	       struct S { int a; int b; };
! 	       struct S a[] = { 1, 2 };
! 	 
! 	     which creates a one-element array, not a two-element array.  */
! 	  maybe_deduce_size_from_array_init (decl, init);
! 	  /* Handle:
! 	     
! 	     [dcl.init]
! 	     
! 	     The memory occupied by any object of static storage
! 	     duration is zero-initialized at program startup before
! 	     any other initialization takes place.
! 	     
! 	     We cannot create an appropriate initializer until after
! 	     the type of DECL is finalized.  If DECL_INITIAL is set,
! 	     then the DECL is statically initialized, and any
! 	     necessary zero-initialization has already been performed.  */
! 	  if (TREE_STATIC (decl) && !DECL_INITIAL (decl))
! 	    DECL_INITIAL (decl) = build_zero_init (TREE_TYPE (decl),
! 						   /*static_storage_p=*/true);
! 	  /* Remember that the initialization for this variable has
! 	     taken place.  */
! 	  DECL_INITIALIZED_P (decl) = 1;
! 	}
!     }
  
    /* Add this declaration to the statement-tree.  This needs to happen
       after the call to check_initializer so that the DECL_STMT for a
       reference temp is added before the DECL_STMT for the reference itself.  */
    if (building_stmt_tree ()
Index: cp/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/expr.c,v
retrieving revision 1.65
diff -c -5 -p -r1.65 expr.c
*** cp/expr.c	14 Sep 2002 12:07:42 -0000	1.65
--- cp/expr.c	30 Sep 2002 16:04:49 -0000
*************** cxx_expand_expr (exp, target, tmode, mod
*** 125,137 ****
      }
    abort ();
    /* NOTREACHED */
    return NULL;
  }
- 
- int
- extract_init (decl, init)
-      tree decl ATTRIBUTE_UNUSED, init ATTRIBUTE_UNUSED;
- {
-   return 0;
- }
- 
--- 125,129 ----
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.292
diff -c -5 -p -r1.292 init.c
*** cp/init.c	21 Sep 2002 12:51:54 -0000	1.292
--- cp/init.c	30 Sep 2002 16:04:50 -0000
*************** initialize_vtbl_ptrs (addr)
*** 154,227 ****
  		 NULL, dfs_unmarked_real_bases_queue_p, list);
    dfs_walk (TYPE_BINFO (type), dfs_unmark,
  	    dfs_marked_real_bases_queue_p, type);
  }
  
! /* Types containing pointers to data members cannot be
!    zero-initialized with zeros, because the NULL value for such
!    pointers is -1.
! 
!    TYPE is a type that requires such zero initialization.  The
!    returned value is the initializer.  */
  
  tree
! build_forced_zero_init (type)
!      tree type;
  {
!   tree init = NULL;
  
!   if (AGGREGATE_TYPE_P (type) && !TYPE_PTRMEMFUNC_P (type))
      {
!       /* This is a default initialization of an aggregate, but not one of
! 	 non-POD class type.  We cleverly notice that the initialization
! 	 rules in such a case are the same as for initialization with an
! 	 empty brace-initialization list.  */
!       init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE);
      }
    else if (TREE_CODE (type) == REFERENCE_TYPE)
!     /*   --if T is a reference type, no initialization is performed.  */
!     return NULL_TREE;
    else
!     {
!       init = integer_zero_node;
!       
!       if (TREE_CODE (type) == ENUMERAL_TYPE)
!         /* We must make enumeral types the right type.  */
!         init = fold (build1 (NOP_EXPR, type, init));
!     }
  
!   init = digest_init (type, init, 0);
  
    return init;
  }
  
! /* [dcl.init]:
  
!   To default-initialize an object of type T means:
  
!   --if T is a non-POD class type (clause _class_), the default construc-
!     tor  for  T is called (and the initialization is ill-formed if T has
!     no accessible default constructor);
  
!   --if T is an array type, each element is default-initialized;
  
!   --otherwise, the storage for the object is zero-initialized.
  
!   A program that calls for default-initialization of an entity of refer-
!   ence type is ill-formed.  */
  
! static tree
! build_default_init (type)
!      tree type;
! {
    if (TYPE_NEEDS_CONSTRUCTING (type))
-     /* Other code will handle running the default constructor.  We can't do
-        anything with a CONSTRUCTOR for arrays here, as that would imply
-        copy-initialization.  */
      return NULL_TREE;
! 
!   return build_forced_zero_init (type);
  }
  
  /* Subroutine of emit_base_init.  */
  
  static void
--- 154,308 ----
  		 NULL, dfs_unmarked_real_bases_queue_p, list);
    dfs_walk (TYPE_BINFO (type), dfs_unmark,
  	    dfs_marked_real_bases_queue_p, type);
  }
  
! /* Return an expression for the zero-initialization of an object with
!    type T.  This expression will either be a constant (in the case
!    that T is a scalar), or a CONSTRUCTOR (in the case that T is an
!    aggregate).  In either case, the value can be used as DECL_INITIAL
!    for a decl of the indicated TYPE; it is a valid static initializer.
!    If STATIC_STORAGE_P is TRUE, initializers are only generated for
!    entities for which zero-initialization does not simply mean filling
!    the storage with zero bytes.  */
  
  tree
! build_zero_init (tree type, bool static_storage_p)
  {
!   tree init = NULL_TREE;
! 
!   /* [dcl.init]
! 
!      To zero-initialization storage for an object of type T means:
! 
!      -- if T is a scalar type, the storage is set to the value of zero
!         converted to T.
! 
!      -- if T is a non-union class type, the storage for each nonstatic
!         data member and each base-class subobject is zero-initialized.
! 
!      -- if T is a union type, the storage for its first data member is
!         zero-initialized.
! 
!      -- if T is an array type, the storage for each element is
!         zero-initialized.
! 
!      -- if T is a reference type, no initialization is performed.  */
  
!   if (type == error_mark_node)
!     ;
!   else if (static_storage_p && zero_init_p (type))
!     /* In order to save space, we do not explicitly build initializers
!        for items that do not need them.  GCC's semantics are that
!        items with static storage duration that are not otherwise
!        initialized are initialized to zero.  */
!     ;
!   else if (SCALAR_TYPE_P (type))
!     init = convert (type, integer_zero_node);
!   else if (CLASS_TYPE_P (type))
!     {
!       tree field;
!       tree inits;
! 
!       /* Build a constructor to contain the initializations.  */
!       init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
!       /* Iterate over the fields, building initializations.  */
!       inits = NULL_TREE;
!       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
! 	{
! 	  if (TREE_CODE (field) != FIELD_DECL)
! 	    continue;
! 
! 	  /* Note that for class types there will be FIELD_DECLs
! 	     corresponding to base classes as well.  Thus, iterating
! 	     over TYPE_FIELDs will result in correct initialization of
! 	     all of the subobjects.  */
! 	  if (static_storage_p && !zero_init_p (TREE_TYPE (field)))
! 	    inits = tree_cons (field, 
! 			       build_zero_init (TREE_TYPE (field),
! 						static_storage_p),
! 			       inits);
! 
! 	  /* For unions, only the first field is initialized.  */
! 	  if (TREE_CODE (type) == UNION_TYPE)
! 	    break;
! 	}
!       CONSTRUCTOR_ELTS (init) = nreverse (inits);
!     }
!   else if (TREE_CODE (type) == ARRAY_TYPE)
      {
!       tree index;
!       tree max_index;
!       tree inits;
! 
!       /* Build a constructor to contain the initializations.  */
!       init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
!       /* Iterate over the array elements, building initializations.  */
!       inits = NULL_TREE;
!       for (index = size_zero_node, max_index = array_type_nelts (type);
! 	   !tree_int_cst_lt (max_index, index);
! 	   index = size_binop (PLUS_EXPR, index, size_one_node))
! 	inits = tree_cons (index,
! 			   build_zero_init (TREE_TYPE (type), 
! 					    static_storage_p),
! 			   inits);
!       CONSTRUCTOR_ELTS (init) = nreverse (inits);
      }
    else if (TREE_CODE (type) == REFERENCE_TYPE)
!     ;
    else
!     abort ();
  
!   /* In all cases, the initializer is a constant.  */
!   if (init)
!     TREE_CONSTANT (init) = 1;
  
    return init;
  }
  
! /* Build an expression for the default-initialization of an object
!    with type T.  If initialization T requires calling constructors,
!    this function returns NULL_TREE; the caller is responsible for
!    arranging for the constructors to be called.  */
  
! static tree
! build_default_init (type)
!      tree type;
! {
!   /* [dcl.init]:
  
!     To default-initialize an object of type T means:
  
!     --if T is a non-POD class type (clause _class_), the default construc-
!       tor  for  T is called (and the initialization is ill-formed if T has
!       no accessible default constructor);
  
!     --if T is an array type, each element is default-initialized;
  
!     --otherwise, the storage for the object is zero-initialized.
  
!     A program that calls for default-initialization of an entity of refer-
!     ence type is ill-formed.  */
! 
!   /* If TYPE_NEEDS_CONSTRUCTING is true, the caller is responsible for
!      performing the initialization.  This is confusing in that some
!      non-PODs do not have TYPE_NEEDS_CONSTRUCTING set.  (For example,
!      a class with a pointer-to-data member as a non-static data member
!      does not have TYPE_NEEDS_CONSTRUCTING set.)  Therefore, we end up
!      passing non-PODs to build_zero_init below, which is contrary to
!      the semantics quoted above from [dcl.init].  
! 
!      It happens, however, that the behavior of the constructor the
!      standard says we should have generated would be precisely the
!      same as that obtained by calling build_zero_init below, so things
!      work out OK.  */
    if (TYPE_NEEDS_CONSTRUCTING (type))
      return NULL_TREE;
!       
!   /* At this point, TYPE is either a POD class type, an array of POD
!      classes, or something even more inoccuous.  */
!   return build_zero_init (type, /*static_storage_p=*/false);
  }
  
  /* Subroutine of emit_base_init.  */
  
  static void
*************** build_field_list (t, list, uses_unions_p
*** 333,343 ****
      *uses_unions_p = 1;
  
    for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))
      {
        /* Skip CONST_DECLs for enumeration constants and so forth.  */
!       if (TREE_CODE (fields) != FIELD_DECL)
  	continue;
        
        /* Keep track of whether or not any fields are unions.  */
        if (TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
  	*uses_unions_p = 1;
--- 414,424 ----
      *uses_unions_p = 1;
  
    for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))
      {
        /* Skip CONST_DECLs for enumeration constants and so forth.  */
!       if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
  	continue;
        
        /* Keep track of whether or not any fields are unions.  */
        if (TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
  	*uses_unions_p = 1;
*************** push_base_cleanups ()
*** 3335,3345 ****
      }
  
    for (member = TYPE_FIELDS (current_class_type); member;
         member = TREE_CHAIN (member))
      {
!       if (TREE_CODE (member) != FIELD_DECL)
  	continue;
        if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
  	{
  	  tree this_member = (build_class_member_access_expr 
  			      (current_class_ref, member, 
--- 3416,3426 ----
      }
  
    for (member = TYPE_FIELDS (current_class_type); member;
         member = TREE_CHAIN (member))
      {
!       if (TREE_CODE (member) != FIELD_DECL || DECL_ARTIFICIAL (member))
  	continue;
        if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
  	{
  	  tree this_member = (build_class_member_access_expr 
  			      (current_class_ref, member, 
Index: cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.230
diff -c -5 -p -r1.230 method.c
*** cp/method.c	21 Sep 2002 12:51:55 -0000	1.230
--- cp/method.c	30 Sep 2002 16:04:50 -0000
*************** do_build_assign_ref (fndecl)
*** 666,676 ****
  	   fields = TREE_CHAIN (fields))
  	{
  	  tree comp, init, t;
  	  tree field = fields;
  
! 	  if (TREE_CODE (field) != FIELD_DECL)
  	    continue;
  
  	  if (CP_TYPE_CONST_P (TREE_TYPE (field)))
  	    {
                error ("non-static const member `%#D', can't use default assignment operator", field);
--- 666,676 ----
  	   fields = TREE_CHAIN (fields))
  	{
  	  tree comp, init, t;
  	  tree field = fields;
  
! 	  if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
  	    continue;
  
  	  if (CP_TYPE_CONST_P (TREE_TYPE (field)))
  	    {
                error ("non-static const member `%#D', can't use default assignment operator", field);
*************** synthesize_exception_spec (type, extract
*** 822,832 ****
    for (; fields; fields = TREE_CHAIN (fields))
      {
        tree type = TREE_TYPE (fields);
        tree fn;
        
!       if (TREE_CODE (fields) != FIELD_DECL)
          continue;
        while (TREE_CODE (type) == ARRAY_TYPE)
    	type = TREE_TYPE (type);
        if (TREE_CODE (type) != RECORD_TYPE)
          continue;
--- 822,832 ----
    for (; fields; fields = TREE_CHAIN (fields))
      {
        tree type = TREE_TYPE (fields);
        tree fn;
        
!       if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
          continue;
        while (TREE_CODE (type) == ARRAY_TYPE)
    	type = TREE_TYPE (type);
        if (TREE_CODE (type) != RECORD_TYPE)
          continue;
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.617
diff -c -5 -p -r1.617 pt.c
*** cp/pt.c	21 Sep 2002 12:51:55 -0000	1.617
--- cp/pt.c	30 Sep 2002 16:04:53 -0000
*************** tsubst_decl (t, args, type, complain)
*** 6139,6149 ****
  	DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0;
  
  	/* Even if the original location is out of scope, the newly
  	   substituted one is not.  */
  	if (TREE_CODE (r) == VAR_DECL)
! 	  DECL_DEAD_FOR_LOCAL (r) = 0;
  
  	if (!local_p)
  	  {
  	    /* A static data member declaration is always marked
  	       external when it is declared in-class, even if an
--- 6139,6152 ----
  	DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0;
  
  	/* Even if the original location is out of scope, the newly
  	   substituted one is not.  */
  	if (TREE_CODE (r) == VAR_DECL)
! 	  {
! 	    DECL_DEAD_FOR_LOCAL (r) = 0;
! 	    DECL_INITIALIZED_P (r) = 0;
! 	  }
  
  	if (!local_p)
  	  {
  	    /* A static data member declaration is always marked
  	       external when it is declared in-class, even if an
*************** regenerate_decl_from_template (decl, tmp
*** 9858,9870 ****
    new_decl = tsubst (code_pattern, args, tf_error, NULL_TREE);
  
    if (TREE_CODE (decl) == VAR_DECL)
      {
        /* Set up DECL_INITIAL, since tsubst doesn't.  */
!       DECL_INITIAL (new_decl) = 
! 	tsubst_expr (DECL_INITIAL (code_pattern), args, 
! 		     tf_error, DECL_TI_TEMPLATE (decl));
      }
    else if (TREE_CODE (decl) == FUNCTION_DECL)
      {
        /* Convince duplicate_decls to use the DECL_ARGUMENTS from the
  	 new decl.  */ 
--- 9861,9874 ----
    new_decl = tsubst (code_pattern, args, tf_error, NULL_TREE);
  
    if (TREE_CODE (decl) == VAR_DECL)
      {
        /* Set up DECL_INITIAL, since tsubst doesn't.  */
!       if (!DECL_INITIALIZED_IN_CLASS_P (decl))
! 	DECL_INITIAL (new_decl) = 
! 	  tsubst_expr (DECL_INITIAL (code_pattern), args, 
! 		       tf_error, DECL_TI_TEMPLATE (decl));
      }
    else if (TREE_CODE (decl) == FUNCTION_DECL)
      {
        /* Convince duplicate_decls to use the DECL_ARGUMENTS from the
  	 new decl.  */ 
*************** instantiate_decl (d, defer_ok)
*** 10140,10150 ****
        else
  	{
  	  DECL_EXTERNAL (d) = 1;
  	  DECL_NOT_REALLY_EXTERN (d) = 1;
  	}
!       cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0);
      }
    else if (TREE_CODE (d) == FUNCTION_DECL)
      {
        htab_t saved_local_specializations;
  
--- 10144,10157 ----
        else
  	{
  	  DECL_EXTERNAL (d) = 1;
  	  DECL_NOT_REALLY_EXTERN (d) = 1;
  	}
!       cp_finish_decl (d, 
! 		      (!DECL_INITIALIZED_IN_CLASS_P (d) 
! 		       ? DECL_INITIAL (d) : NULL_TREE),
! 		      NULL_TREE, 0);
      }
    else if (TREE_CODE (d) == FUNCTION_DECL)
      {
        htab_t saved_local_specializations;
  
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.238
diff -c -5 -p -r1.238 search.c
*** cp/search.c	21 Sep 2002 12:51:56 -0000	1.238
--- cp/search.c	30 Sep 2002 16:04:54 -0000
*************** dfs_push_decls (binfo, data)
*** 2534,2544 ****
      {
        tree fields;
        for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
  	if (DECL_NAME (fields) 
  	    && TREE_CODE (fields) != TYPE_DECL
! 	    && TREE_CODE (fields) != USING_DECL)
  	  setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0);
  	else if (TREE_CODE (fields) == FIELD_DECL
  		 && ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
  	  dfs_push_decls (TYPE_BINFO (TREE_TYPE (fields)), data);
  	  
--- 2534,2545 ----
      {
        tree fields;
        for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
  	if (DECL_NAME (fields) 
  	    && TREE_CODE (fields) != TYPE_DECL
! 	    && TREE_CODE (fields) != USING_DECL
! 	    && !DECL_ARTIFICIAL (fields))
  	  setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0);
  	else if (TREE_CODE (fields) == FIELD_DECL
  		 && ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
  	  dfs_push_decls (TYPE_BINFO (TREE_TYPE (fields)), data);
  	  
*************** dfs_unuse_fields (binfo, data)
*** 2595,2605 ****
    tree type = TREE_TYPE (binfo);
    tree fields;
  
    for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
      {
!       if (TREE_CODE (fields) != FIELD_DECL)
  	continue;
  
        TREE_USED (fields) = 0;
        if (DECL_NAME (fields) == NULL_TREE
  	  && ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
--- 2596,2606 ----
    tree type = TREE_TYPE (binfo);
    tree fields;
  
    for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
      {
!       if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
  	continue;
  
        TREE_USED (fields) = 0;
        if (DECL_NAME (fields) == NULL_TREE
  	  && ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.301
diff -c -5 -p -r1.301 tree.c
*** cp/tree.c	21 Sep 2002 12:51:56 -0000	1.301
--- cp/tree.c	30 Sep 2002 16:04:54 -0000
*************** int
*** 1935,1944 ****
--- 1935,1946 ----
  pod_type_p (t)
       tree t;
  {
    t = strip_array_types (t);
  
+   if (t == error_mark_node)
+     return 1;
    if (INTEGRAL_TYPE_P (t))
      return 1;  /* integral, character or enumeral type */
    if (FLOAT_TYPE_P (t))
      return 1;
    if (TYPE_PTR_P (t))
*************** pod_type_p (t)
*** 1961,1970 ****
--- 1963,1975 ----
  int
  zero_init_p (t)
       tree t;
  {
    t = strip_array_types (t);
+ 
+   if (t == error_mark_node)
+     return 1;
  
    /* NULL pointers to data members are initialized with -1.  */
    if (TYPE_PTRMEM_P (t))
      return 0;
  
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.429
diff -c -5 -p -r1.429 typeck.c
*** cp/typeck.c	21 Sep 2002 12:51:56 -0000	1.429
--- cp/typeck.c	30 Sep 2002 16:04:55 -0000
*************** lookup_anon_field (t, type)
*** 1809,1819 ****
  
    for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
      {
        if (TREE_STATIC (field))
  	continue;
!       if (TREE_CODE (field) != FIELD_DECL)
  	continue;
  
        /* If we find it directly, return the field.  */
        if (DECL_NAME (field) == NULL_TREE
  	  && type == TYPE_MAIN_VARIANT (TREE_TYPE (field)))
--- 1809,1819 ----
  
    for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
      {
        if (TREE_STATIC (field))
  	continue;
!       if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
  	continue;
  
        /* If we find it directly, return the field.  */
        if (DECL_NAME (field) == NULL_TREE
  	  && type == TYPE_MAIN_VARIANT (TREE_TYPE (field)))
Index: cp/typeck2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck2.c,v
retrieving revision 1.128
diff -c -5 -p -r1.128 typeck2.c
*** cp/typeck2.c	14 Sep 2002 12:07:44 -0000	1.128
--- cp/typeck2.c	30 Sep 2002 16:04:55 -0000
*************** store_init_value (decl, init)
*** 318,333 ****
  
    type = TREE_TYPE (decl);
    if (TREE_CODE (type) == ERROR_MARK)
      return NULL_TREE;
  
- #if 0
-   /* This breaks arrays, and should not have any effect for other decls.  */
-   /* Take care of C++ business up here.  */
-   type = TYPE_MAIN_VARIANT (type);
- #endif
- 
    if (IS_AGGR_TYPE (type))
      {
        if (! TYPE_HAS_TRIVIAL_INIT_REF (type)
  	  && TREE_CODE (init) != CONSTRUCTOR)
  	abort ();
--- 318,327 ----
*************** store_init_value (decl, init)
*** 335,373 ****
        if (TREE_CODE (init) == TREE_LIST)
  	{
  	  error ("constructor syntax used, but no constructor declared for type `%T'", type);
  	  init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (init));
  	}
- #if 0
-       if (TREE_CODE (init) == CONSTRUCTOR)
- 	{
- 	  tree field;
- 
- 	  /* Check that we're really an aggregate as ARM 8.4.1 defines it.  */
- 	  if (CLASSTYPE_N_BASECLASSES (type))
- 	    cp_error_at ("initializer list construction invalid for derived class object `%D'", decl);
- 	  if (CLASSTYPE_VTBL_PTR (type))
- 	    cp_error_at ("initializer list construction invalid for polymorphic class object `%D'", decl);
- 	  if (TYPE_NEEDS_CONSTRUCTING (type))
- 	    {
- 	      cp_error_at ("initializer list construction invalid for `%D'", decl);
- 	      error ("due to the presence of a constructor");
- 	    }
- 	  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- 	    if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
- 	      {
- 		cp_error_at ("initializer list construction invalid for `%D'", decl);
- 		cp_error_at ("due to non-public access of member `%D'", field);
- 	      }
- 	  for (field = TYPE_METHODS (type); field; field = TREE_CHAIN (field))
- 	    if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
- 	      {
- 		cp_error_at ("initializer list construction invalid for `%D'", decl);
- 		cp_error_at ("due to non-public access of member `%D'", field);
- 	      }
- 	}
- #endif
      }
    else if (TREE_CODE (init) == TREE_LIST
  	   && TREE_TYPE (init) != unknown_type_node)
      {
        if (TREE_CODE (decl) == RESULT_DECL)
--- 329,338 ----
*************** store_init_value (decl, init)
*** 455,485 ****
       when we output this function.  */
    DECL_INITIAL (decl) = value;
    return NULL_TREE;
  }
  
- /* Same as store_init_value, but used for known-to-be-valid static
-    initializers.  Used to introduce a static initializer even in data
-    structures that may require dynamic initialization.  */
- 
- tree
- force_store_init_value (decl, init)
-      tree decl, init;
- {
-   tree type = TREE_TYPE (decl);
-   int needs_constructing = TYPE_NEEDS_CONSTRUCTING (type);
- 
-   TYPE_NEEDS_CONSTRUCTING (type) = 0;
- 
-   init = store_init_value (decl, init);
-   if (init)
-     abort ();
- 
-   TYPE_NEEDS_CONSTRUCTING (type) = needs_constructing;
- 
-   return init;
- }  
  
  /* Digest the parser output INIT as an initializer for type TYPE.
     Return a C expression of type TYPE to represent the initial value.
  
     If TAIL is nonzero, it points to a variable holding a list of elements
--- 420,429 ----
*************** process_init_constructor (type, init, el
*** 789,799 ****
  	      else
  		next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE);
  	      next1 = digest_init (TREE_TYPE (type), next1, 0);
  	    }
  	  else if (! zero_init_p (TREE_TYPE (type)))
! 	    next1 = build_forced_zero_init (TREE_TYPE (type));
  	  else
  	    /* The default zero-initialization is fine for us; don't
  	       add anything to the CONSTRUCTOR.  */
  	    break;
  
--- 733,744 ----
  	      else
  		next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE);
  	      next1 = digest_init (TREE_TYPE (type), next1, 0);
  	    }
  	  else if (! zero_init_p (TREE_TYPE (type)))
! 	    next1 = build_zero_init (TREE_TYPE (type),
! 				     /*static_storage_p=*/false);
  	  else
  	    /* The default zero-initialization is fine for us; don't
  	       add anything to the CONSTRUCTOR.  */
  	    break;
  
*************** process_init_constructor (type, init, el
*** 838,848 ****
  	    {
  	      members = tree_cons (field, integer_zero_node, members);
  	      continue;
  	    }
  
! 	  if (TREE_CODE (field) != FIELD_DECL)
  	    continue;
  
  	  if (tail)
  	    {
  	      if (TREE_PURPOSE (tail)
--- 783,793 ----
  	    {
  	      members = tree_cons (field, integer_zero_node, members);
  	      continue;
  	    }
  
! 	  if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
  	    continue;
  
  	  if (tail)
  	    {
  	      if (TREE_PURPOSE (tail)
*************** process_init_constructor (type, init, el
*** 907,917 ****
  	      if (extra_warnings
  	          && (!init || TREE_HAS_CONSTRUCTOR (init)))
  		warning ("missing initializer for member `%D'", field);
  
  	      if (! zero_init_p (TREE_TYPE (field)))
! 		next1 = build_forced_zero_init (TREE_TYPE (field));
  	      else
  		/* The default zero-initialization is fine for us; don't
  		   add anything to the CONSTRUCTOR.  */
  		continue;
  	    }
--- 852,863 ----
  	      if (extra_warnings
  	          && (!init || TREE_HAS_CONSTRUCTOR (init)))
  		warning ("missing initializer for member `%D'", field);
  
  	      if (! zero_init_p (TREE_TYPE (field)))
! 		next1 = build_zero_init (TREE_TYPE (field),
! 					 /*static_storage_p=*/false);
  	      else
  		/* The default zero-initialization is fine for us; don't
  		   add anything to the CONSTRUCTOR.  */
  		continue;
  	    }
*************** process_init_constructor (type, init, el
*** 931,942 ****
      {
        register tree field = TYPE_FIELDS (type);
  
        /* Find the first named field.  ANSI decided in September 1990
  	 that only named fields count here.  */
!       while (field && (DECL_NAME (field) == 0
! 		       || TREE_CODE (field) != FIELD_DECL))
  	field = TREE_CHAIN (field);
  
        /* If this element specifies a field, initialize via that field.  */
        if (TREE_PURPOSE (tail) != NULL_TREE)
  	{
--- 877,887 ----
      {
        register tree field = TYPE_FIELDS (type);
  
        /* Find the first named field.  ANSI decided in September 1990
  	 that only named fields count here.  */
!       while (field && (!DECL_NAME (field) || TREE_CODE (field) != FIELD_DECL))
  	field = TREE_CHAIN (field);
  
        /* If this element specifies a field, initialize via that field.  */
        if (TREE_PURPOSE (tail) != NULL_TREE)
  	{
Index: testsuite/g++.dg/abi/empty7.C
===================================================================
RCS file: testsuite/g++.dg/abi/empty7.C
diff -N testsuite/g++.dg/abi/empty7.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/empty7.C	30 Sep 2002 16:04:56 -0000
***************
*** 0 ****
--- 1,18 ----
+ // { dg-do run { target i?86-*-* } }
+ // { dg-options "-fabi-version=0" }
+ 
+ struct S1 {};
+ struct S2 { virtual void f () {} S1 s1[4]; };
+ struct S3 : virtual public S2 {};
+ struct S4 : virtual public S2 { int i; };
+ struct S5 : public S3, virtual public S4 {};
+ struct S6 { S5 s5; };
+ struct S7 { S1 s1[5]; };
+ struct S8 : public S1, public S6, virtual public S7 { };
+ 
+ S8 s8;
+ 
+ int main () {
+   if ((char *)(S7 *)&s8 - (char *)&s8 != 24)
+     return 1;
+ }
Index: testsuite/g++.dg/init/pm2.C
===================================================================
RCS file: testsuite/g++.dg/init/pm2.C
diff -N testsuite/g++.dg/init/pm2.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/init/pm2.C	30 Sep 2002 16:04:56 -0000
***************
*** 0 ****
--- 1,7 ----
+ struct S {
+   S ();
+   int S::* sp;
+   int i;
+ };
+ 
+ S s[2] = {};


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