OSDN Git Service

* store-layout.c (finish_record_layout): Add free_p parameter.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 30 Sep 2002 16:52:19 +0000 (16:52 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 30 Sep 2002 16:52:19 +0000 (16:52 +0000)
(layout_type): Pass it.
* tree.h (finish_record_layout): Update prototype.

* 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.

* g++.dg/abi/empty7.C: New test.
* g++.dg/init/pm2.C: Likewise.

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

18 files changed:
gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/expr.c
gcc/cp/init.c
gcc/cp/method.c
gcc/cp/pt.c
gcc/cp/search.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/stor-layout.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/empty7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/init/pm2.C [new file with mode: 0644]
gcc/tree.h

index 76793fb..f1a6964 100644 (file)
@@ -1,3 +1,9 @@
+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.
+       
 Mon Sep 30 14:57:18 CEST 2002  Jan Hubicka  <jh@suse.cz>
 
        * i386.h (TARGET_CPP_CPU_BUILTINS): Define __SSE_MATH__.
index 792ce89..1fef98d 100644 (file)
@@ -1,3 +1,62 @@
+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-29  Nathan Sidwell  <nathan@codesourcery.com>
 
        PR c++/7788
index 7532c5d..b97b268 100644 (file)
@@ -137,21 +137,22 @@ 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 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 PARAMS ((tree, splay_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 *));
@@ -171,9 +172,8 @@ 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));
+                                                  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,
@@ -208,7 +208,7 @@ 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 void warn_about_ambiguous_bases PARAMS ((tree));
 static bool type_requires_array_cookie PARAMS ((tree));
 static bool contains_empty_class_p (tree);
 
@@ -3512,6 +3512,7 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
   if (CLASS_TYPE_P (type))
     {
       tree field;
+      tree binfo;
       int i;
 
       /* Record the location of TYPE.  */
@@ -3522,7 +3523,11 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
       /* 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);
+         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) 
@@ -3536,14 +3541,40 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
                                                  BINFO_OFFSET (binfo)),
                                      offsets,
                                      max_offset,
-                                     vbases_p);
+                                     (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)
+       if (TREE_CODE (field) == FIELD_DECL && !DECL_ARTIFICIAL (field))
          {
            tree field_offset;
 
@@ -3571,8 +3602,11 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
       tree index;
 
       /* Step through each of the elements in the array.  */
-      for (index = size_zero_node; 
-          INT_CST_LT (index, TYPE_MAX_VALUE (domain));
+      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),
@@ -3640,22 +3674,34 @@ layout_conflict_p (type, offset, offsets, vbases_p)
 /* 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.  */
+   types already located at those offsets.  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;
+layout_nonempty_base_or_field (record_layout_info rli, 
+                              tree decl, 
+                              tree binfo, 
+                              splay_tree offsets)
 {
+  tree t = rli->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);
+  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
@@ -3683,10 +3729,7 @@ layout_nonempty_base_or_field (rli, decl, binfo, offsets, t)
         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))
+      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
@@ -3709,8 +3752,15 @@ layout_nonempty_base_or_field (rli, decl, binfo, offsets, t)
   /* 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, 
-                            convert (ssizetype, offset), t);
+                            size_diffop (convert (ssizetype, offset),
+                                         convert (ssizetype, 
+                                                  BINFO_OFFSET (binfo))),
+                            t);
 }
 
 /* Layout the empty base BINFO.  EOC indicates the byte currently just
@@ -3768,60 +3818,74 @@ layout_empty_base (binfo, eoc, offsets, t)
   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.  */
+/* 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.  
 
-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;
+   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);
-  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;
+    return next_field;
   
-  if (!integer_zerop (DECL_SIZE (decl)))
+  /* 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.  */
-      *empty_p = 0;
-
+      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, t);
+      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
     {
-      unsigned HOST_WIDE_INT eoc;
+      tree 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);
+      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.  */
@@ -3829,42 +3893,41 @@ build_base_field (rli, binfo, empty_p, offsets, t)
                            BINFO_OFFSET (binfo),
                            offsets, 
                            /*vbases_p=*/0);
-  return atend;
+
+  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.  */
+   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 bool
-build_base_fields (rli, empty_p, offsets, t)
-     record_layout_info rli;
-     int *empty_p;
-     splay_tree offsets;
-     tree t;
+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 rec = rli->t;
-  int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
+  tree t = rli->t;
+  int n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
   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);
+  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 (rec), i);
+      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 (rec))
+      if (base_binfo == CLASSTYPE_PRIMARY_BINFO (t))
        continue;
 
       /* A primary virtual base class is allocated just like any other
@@ -3874,9 +3937,9 @@ build_base_fields (rli, empty_p, offsets, t)
          && !BINFO_PRIMARY_P (base_binfo))
        continue;
 
-      atend |= build_base_field (rli, base_binfo, empty_p, offsets, t);
+      next_field = build_base_field (rli, base_binfo, empty_p,
+                                    offsets, next_field);
     }
-  return atend;
 }
 
 /* Go through the TYPE_METHODS of T issuing any appropriate
@@ -4567,36 +4630,41 @@ dfs_set_offset_for_unshared_vbases (binfo, data)
   return NULL_TREE;
 }
 
-/* Set BINFO_OFFSET for all of the virtual bases for T.  Update
+/* 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 (t, offsets)
-     tree t;
-     splay_tree offsets;
+layout_virtual_bases (record_layout_info rli, splay_tree offsets)
 {
-  tree vbases, dsize;
-  unsigned HOST_WIDE_INT eoc;
+  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);
+      /* 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);
+    }
 
-  /* 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);
+  /* 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
@@ -4614,45 +4682,12 @@ layout_virtual_bases (t, offsets)
 
       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.  */
-         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)));
-           }
+         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
@@ -4663,20 +4698,15 @@ layout_virtual_bases (t, offsets)
             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)))
+             && (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);
 
-         /* 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;
        }
     }
@@ -4687,45 +4717,18 @@ layout_virtual_bases (t, offsets)
      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
+static tree
 end_of_class (t, include_virtuals_p)
      tree t;
      int include_virtuals_p;
 {
-  unsigned HOST_WIDE_INT result = 0;
+  tree result = size_zero_node;
   int i;
 
   for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
@@ -4733,7 +4736,6 @@ end_of_class (t, include_virtuals_p)
       tree base_binfo;
       tree offset;
       tree size;
-      unsigned HOST_WIDE_INT end_of_base;
 
       base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
 
@@ -4752,15 +4754,14 @@ end_of_class (t, include_virtuals_p)
       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;
+      if (INT_CST_LT_UNSIGNED (result, offset))
+       result = offset;
     }
 
   return result;
 }
 
-/* Warn about direct bases of T that are inaccessible because they are
+/* Warn about bases of T that are inaccessible because they are
    ambiguous.  For example:
 
      struct S {};
@@ -4771,19 +4772,35 @@ end_of_class (t, include_virtuals_p)
    subobjects of U.  */
 
 static void
-warn_about_ambiguous_direct_bases (t)
+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)
     {
-      tree basetype = TYPE_BINFO_BASETYPE (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);
+                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.  */
@@ -4796,6 +4813,29 @@ splay_tree_compare_integer_csts (k1, 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.  */
@@ -4811,12 +4851,15 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
   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;
+  /* 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);
@@ -4834,15 +4877,18 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
   /* The vptr is always the first thing in the class.  */
   if (vptr)
     {
-      TYPE_FIELDS (t) = chainon (vptr, TYPE_FIELDS (t));
+      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);
-  if (build_base_fields (rli, empty_p, empty_base_offsets, t))
-    CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+  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))
@@ -4917,7 +4963,7 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
        padding = NULL_TREE;
 
       layout_nonempty_base_or_field (rli, field, NULL_TREE,
-                                    empty_base_offsets, t);
+                                    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
@@ -4957,76 +5003,59 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
          DECL_USER_ALIGN (padding_field) = 0;
          layout_nonempty_base_or_field (rli, padding_field,
                                         NULL_TREE, 
-                                        empty_base_offsets, t);
+                                        empty_base_offsets);
        }
 
       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))
+  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);
+
+  /* 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);
 
-  /* Remember the size and alignment of the class before adding
-     the virtual bases.  */
-  if (*empty_p)
+  /* 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)
     {
-      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);
+      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_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);
+    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
@@ -5037,11 +5066,22 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
      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);
+  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 direct bases that can't be talked about due to
-     ambiguity.  */
-  warn_about_ambiguous_direct_bases (t);
+  /* 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);
@@ -6414,7 +6454,9 @@ contains_empty_class_p (tree type)
        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)))
+       if (TREE_CODE (field) == FIELD_DECL
+           && !DECL_ARTIFICIAL (field)
+           && is_empty_class (TREE_TYPE (field)))
          return true;
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
index 7e40937..3a9c7e7 100644 (file)
@@ -59,6 +59,7 @@ struct diagnostic_context;
       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)
@@ -96,11 +97,10 @@ struct diagnostic_context;
       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
+   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).
@@ -1150,8 +1150,7 @@ struct lang_type_class GTY(())
   tree vfields;
   tree vbases;
   tree tags;
-  tree size;
-  tree size_unit;
+  tree as_base;
   tree pure_virtuals;
   tree friend_classes;
   tree rtti;
@@ -1396,12 +1395,17 @@ struct lang_type GTY(())
 #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) (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)
+#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) \
@@ -1954,6 +1958,11 @@ struct lang_decl GTY(())
    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) \
@@ -3850,7 +3859,6 @@ 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));
@@ -3870,7 +3878,7 @@ 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_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));
@@ -4344,7 +4352,6 @@ 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 *));
index 980a38a..fb6c776 100644 (file)
@@ -67,7 +67,6 @@ 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));
@@ -3460,7 +3459,11 @@ duplicate_decls (newdecl, olddecl)
        newtype = oldtype;
 
       if (TREE_CODE (newdecl) == VAR_DECL)
-       DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
+       {
+         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
@@ -7548,45 +7551,6 @@ grok_reference_init (decl, type, init)
   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.  */
@@ -7773,17 +7737,18 @@ check_initializer (decl, init)
      tree decl;
      tree init;
 {
-  tree type;
-
-  if (TREE_CODE (decl) == FIELD_DECL)
-    return init;
-
-  type = TREE_TYPE (decl);
+  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)
     {
@@ -7823,21 +7788,9 @@ check_initializer (decl, init)
       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;
-    }
+    init = grok_reference_init (decl, type, init);
   else if (init)
     {
-    process_init:
       if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
        {
          if (TREE_CODE (type) == ARRAY_TYPE)
@@ -7861,11 +7814,6 @@ check_initializer (decl, init)
          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))
     ;
@@ -7884,10 +7832,6 @@ check_initializer (decl, init)
        }
 
       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);
@@ -8255,10 +8199,54 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
       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);
+  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
index 3cc6551..e5b0439 100644 (file)
@@ -127,11 +127,3 @@ cxx_expand_expr (exp, target, tmode, modifier)
   /* NOTREACHED */
   return NULL;
 }
-
-int
-extract_init (decl, init)
-     tree decl ATTRIBUTE_UNUSED, init ATTRIBUTE_UNUSED;
-{
-  return 0;
-}
-
index c2110d1..ec74a25 100644 (file)
@@ -156,70 +156,151 @@ initialize_vtbl_ptrs (addr)
            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.  */
+/* 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_forced_zero_init (type)
-     tree type;
+build_zero_init (tree type, bool static_storage_p)
 {
-  tree init = NULL;
+  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 (AGGREGATE_TYPE_P (type) && !TYPE_PTRMEMFUNC_P (type))
+  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)
     {
-      /* 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);
+      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)
-    /*   --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));
-    }
+    abort ();
 
-  init = digest_init (type, init, 0);
+  /* In all cases, the initializer is a constant.  */
+  if (init)
+    TREE_CONSTANT (init) = 1;
 
   return init;
 }
 
-/* [dcl.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.  */
 
-  To default-initialize an object of type T means:
+static tree
+build_default_init (type)
+     tree type;
+{
+  /* [dcl.init]:
 
-  --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);
+    To default-initialize an object of type T means:
 
-  --if T is an array type, each element is default-initialized;
+    --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);
 
-  --otherwise, the storage for the object is zero-initialized.
+    --if T is an array type, each element is default-initialized;
 
-  A program that calls for default-initialization of an entity of refer-
-  ence type is ill-formed.  */
+    --otherwise, the storage for the object is zero-initialized.
 
-static tree
-build_default_init (type)
-     tree type;
-{
+    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))
-    /* 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);
+      
+  /* 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.  */
@@ -335,7 +416,7 @@ build_field_list (t, list, uses_unions_p)
   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)
+      if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
        continue;
       
       /* Keep track of whether or not any fields are unions.  */
@@ -3337,7 +3418,7 @@ push_base_cleanups ()
   for (member = TYPE_FIELDS (current_class_type); member;
        member = TREE_CHAIN (member))
     {
-      if (TREE_CODE (member) != FIELD_DECL)
+      if (TREE_CODE (member) != FIELD_DECL || DECL_ARTIFICIAL (member))
        continue;
       if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
        {
index 0689a7d..6b4b795 100644 (file)
@@ -668,7 +668,7 @@ do_build_assign_ref (fndecl)
          tree comp, init, t;
          tree field = fields;
 
-         if (TREE_CODE (field) != FIELD_DECL)
+         if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
            continue;
 
          if (CP_TYPE_CONST_P (TREE_TYPE (field)))
@@ -824,7 +824,7 @@ synthesize_exception_spec (type, extractor, client)
       tree type = TREE_TYPE (fields);
       tree fn;
       
-      if (TREE_CODE (fields) != FIELD_DECL)
+      if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
         continue;
       while (TREE_CODE (type) == ARRAY_TYPE)
        type = TREE_TYPE (type);
index 53787d6..47421a0 100644 (file)
@@ -6141,7 +6141,10 @@ tsubst_decl (t, args, type, complain)
        /* 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_DEAD_FOR_LOCAL (r) = 0;
+           DECL_INITIALIZED_P (r) = 0;
+         }
 
        if (!local_p)
          {
@@ -9860,9 +9863,10 @@ regenerate_decl_from_template (decl, tmpl)
   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));
+      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)
     {
@@ -10142,7 +10146,10 @@ instantiate_decl (d, defer_ok)
          DECL_EXTERNAL (d) = 1;
          DECL_NOT_REALLY_EXTERN (d) = 1;
        }
-      cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0);
+      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)
     {
index ae3b102..3b06a0a 100644 (file)
@@ -2536,7 +2536,8 @@ dfs_push_decls (binfo, data)
       for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
        if (DECL_NAME (fields) 
            && TREE_CODE (fields) != TYPE_DECL
-           && TREE_CODE (fields) != USING_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)))
@@ -2597,7 +2598,7 @@ dfs_unuse_fields (binfo, data)
 
   for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
     {
-      if (TREE_CODE (fields) != FIELD_DECL)
+      if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
        continue;
 
       TREE_USED (fields) = 0;
index ea2e0e1..588b710 100644 (file)
@@ -1937,6 +1937,8 @@ pod_type_p (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))
@@ -1964,6 +1966,9 @@ zero_init_p (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 d32d81c..ae78dbf 100644 (file)
@@ -1811,7 +1811,7 @@ lookup_anon_field (t, type)
     {
       if (TREE_STATIC (field))
        continue;
-      if (TREE_CODE (field) != FIELD_DECL)
+      if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
        continue;
 
       /* If we find it directly, return the field.  */
index fb55c8b..fa7f705 100644 (file)
@@ -320,12 +320,6 @@ store_init_value (decl, init)
   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)
@@ -337,35 +331,6 @@ store_init_value (decl, init)
          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)
@@ -457,27 +422,6 @@ store_init_value (decl, init)
   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;
-}  
 \f
 /* Digest the parser output INIT as an initializer for type TYPE.
    Return a C expression of type TYPE to represent the initial value.
@@ -791,7 +735,8 @@ process_init_constructor (type, init, elts)
              next1 = digest_init (TREE_TYPE (type), next1, 0);
            }
          else if (! zero_init_p (TREE_TYPE (type)))
-           next1 = build_forced_zero_init (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.  */
@@ -840,7 +785,7 @@ process_init_constructor (type, init, elts)
              continue;
            }
 
-         if (TREE_CODE (field) != FIELD_DECL)
+         if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
            continue;
 
          if (tail)
@@ -909,7 +854,8 @@ process_init_constructor (type, init, elts)
                warning ("missing initializer for member `%D'", field);
 
              if (! zero_init_p (TREE_TYPE (field)))
-               next1 = build_forced_zero_init (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.  */
@@ -933,8 +879,7 @@ process_init_constructor (type, init, elts)
 
       /* 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))
+      while (field && (!DECL_NAME (field) || TREE_CODE (field) != FIELD_DECL))
        field = TREE_CHAIN (field);
 
       /* If this element specifies a field, initialize via that field.  */
index e468a2b..953d58f 100644 (file)
@@ -1484,11 +1484,14 @@ finalize_type_size (type)
 
 /* 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.  */
+   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)
+finish_record_layout (rli, free_p)
      record_layout_info rli;
+     int free_p;
 {
   /* Compute the final size.  */
   finalize_record_size (rli);
@@ -1508,7 +1511,8 @@ finish_record_layout (rli)
     }
 
   /* Clean up.  */
-  free (rli);
+  if (free_p)
+    free (rli);
 }
 \f
 /* Calculate the mode, size, and alignment for TYPE.
@@ -1763,7 +1767,7 @@ layout_type (type)
          (*lang_adjust_rli) (rli);
 
        /* Finish laying out the record.  */
-       finish_record_layout (rli);
+       finish_record_layout (rli, /*free_p=*/true);
       }
       break;
 
index cc3219b..d444eea 100644 (file)
@@ -1,3 +1,8 @@
+2002-09-30  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/abi/empty7.C: New test.
+       * g++.dg/init/pm2.C: Likewise.
+       
 2002-09-29  Nathan Sidwell  <nathan@codesourcery.com>
 
        * g++.dg/rtti/crash1.C: New test.
diff --git a/gcc/testsuite/g++.dg/abi/empty7.C b/gcc/testsuite/g++.dg/abi/empty7.C
new file mode 100644 (file)
index 0000000..4b1ac3b
--- /dev/null
@@ -0,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;
+}
diff --git a/gcc/testsuite/g++.dg/init/pm2.C b/gcc/testsuite/g++.dg/init/pm2.C
new file mode 100644 (file)
index 0000000..35b9b32
--- /dev/null
@@ -0,0 +1,7 @@
+struct S {
+  S ();
+  int S::* sp;
+  int i;
+};
+
+S s[2] = {};
index 1c16c83..1d0941c 100644 (file)
@@ -2434,7 +2434,7 @@ 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));
+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.