OSDN Git Service

* class.c (pushclass): Remove #if 0'd code.
[pf3gnuchains/gcc-fork.git] / gcc / cp / class.c
index 2834154..db4b480 100644 (file)
@@ -89,6 +89,9 @@ typedef struct vtbl_init_data_s
   int ctor_vtbl_p;
 } vtbl_init_data;
 
+/* The type of a function passed to walk_subobject_offsets.  */
+typedef int (*subobject_offset_fn) PARAMS ((tree, tree, splay_tree));
+
 /* The stack itself.  This is an dynamically resized array.  The
    number of elements allocated is CURRENT_CLASS_STACK_SIZE.  */
 static int current_class_stack_size;
@@ -142,8 +145,9 @@ 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 void build_base_field PARAMS ((record_layout_info, tree, int *,
-                                     unsigned int *, varray_type *));
-static varray_type build_base_fields PARAMS ((record_layout_info, int *));
+                                     unsigned int *, splay_tree));
+static void build_base_fields PARAMS ((record_layout_info, int *,
+                                      splay_tree));
 static tree build_vbase_pointer_fields PARAMS ((record_layout_info, int *));
 static tree build_vtbl_or_vbase_field PARAMS ((tree, tree, tree, tree, tree,
                                               int *));
@@ -153,11 +157,11 @@ 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 *, int *, tree *, tree *));
 static void layout_class_type PARAMS ((tree, int *, int *, tree *, tree *));
-static void fixup_pending_inline PARAMS ((struct pending_inline *));
+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));
-static void layout_virtual_bases PARAMS ((tree, varray_type *));
+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 *));
@@ -174,13 +178,9 @@ 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,
-                                                  varray_type));
-static tree dfs_record_base_offsets PARAMS ((tree, void *));
-static void record_base_offsets PARAMS ((tree, varray_type *));
-static tree dfs_search_base_offsets PARAMS ((tree, void *));
-static int layout_conflict_p PARAMS ((tree, varray_type));
+                                                  splay_tree));
 static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
-static void layout_empty_base PARAMS ((tree, tree, varray_type));
+static void layout_empty_base PARAMS ((tree, tree, splay_tree));
 static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
 static void set_vindex PARAMS ((tree, tree, int *));
 static void build_rtti_vtbl_entries PARAMS ((tree, tree, vtbl_init_data *));
@@ -199,6 +199,14 @@ static tree dfs_build_secondary_vptr_vtt_inits PARAMS ((tree, void *));
 static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
 static tree get_matching_base PARAMS ((tree, tree));
 static tree dfs_get_primary_binfo PARAMS ((tree, void*));
+static int record_subobject_offset PARAMS ((tree, tree, splay_tree));
+static int check_subobject_offset PARAMS ((tree, tree, splay_tree));
+static int walk_subobject_offsets PARAMS ((tree, subobject_offset_fn,
+                                          tree, splay_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));
 
 /* Variables shared between class.c and call.c.  */
 
@@ -855,7 +863,8 @@ build_secondary_vtable (binfo, for_type)
   tree new_decl;
   tree offset;
   tree path = binfo;
-  char *buf, *buf2;
+  char *buf;
+  const char *buf2;
   char joiner = '_';
   int i;
 
@@ -1154,8 +1163,6 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p,
     }
 }
 \f
-extern struct obstack *current_obstack;
-
 /* Add method METHOD to class TYPE.  If ERROR_P is true, we are adding
    the method after the class has already been defined because a
    declaration for it was seen.  (Even though that is erroneous, we
@@ -2344,7 +2351,7 @@ duplicate_tag_error (t)
       tree template_info = CLASSTYPE_TEMPLATE_INFO (t);
       int use_template = CLASSTYPE_USE_TEMPLATE (t);
 
-      bzero ((char *) TYPE_LANG_SPECIFIC (t), sizeof (struct lang_type));
+      memset ((char *) TYPE_LANG_SPECIFIC (t), 0, sizeof (struct lang_type));
       BINFO_BASETYPES(binfo) = NULL_TREE;
 
       TYPE_BINFO (t) = binfo;
@@ -2903,56 +2910,24 @@ static void
 check_for_override (decl, ctype)
      tree decl, ctype;
 {
-  tree binfos = BINFO_BASETYPES (TYPE_BINFO (ctype));
-  int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-  int virtualp = DECL_VIRTUAL_P (decl);
-  int found_overriden_fn = 0;
+  if (TREE_CODE (decl) == TEMPLATE_DECL)
+    /* In [temp.mem] we have:
 
-  for (i = 0; i < n_baselinks; i++)
+         A specialization of a member function template does not
+         override a virtual function from a base class.  */
+    return;
+  if ((DECL_DESTRUCTOR_P (decl)
+       || IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)))
+      && look_for_overrides (ctype, decl)
+      && !DECL_STATIC_FUNCTION_P (decl))
     {
-      tree base_binfo = TREE_VEC_ELT (binfos, i);
-      if (TYPE_POLYMORPHIC_P (BINFO_TYPE (base_binfo)))
-       {
-         tree tmp = get_matching_virtual
-           (base_binfo, decl, DECL_DESTRUCTOR_P (decl));
-
-         if (tmp && !found_overriden_fn)
-           {
-             /* If this function overrides some virtual in some base
-                class, then the function itself is also necessarily
-                virtual, even if the user didn't explicitly say so.  */
-             DECL_VIRTUAL_P (decl) = 1;
-
-             /* The TMP we really want is the one from the deepest
-                baseclass on this path, taking care not to
-                duplicate if we have already found it (via another
-                path to its virtual baseclass.  */
-             if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
-               {
-                 cp_error_at ("`static %#D' cannot be declared", decl);
-                 cp_error_at ("  since `virtual %#D' declared in base class",
-                              tmp);
-                 break;
-               }
-             virtualp = 1;
-
-             /* Set DECL_VINDEX to a value that is neither an
-                INTEGER_CST nor the error_mark_node so that
-                add_virtual_function will realize this is an
-                overridden function.  */
-             DECL_VINDEX (decl) 
-               = tree_cons (tmp, NULL_TREE, DECL_VINDEX (decl));
-             
-             /* We now know that DECL overrides something,
-                which is all that is important.  But, we must
-                continue to iterate through all the base-classes
-                in order to allow get_matching_virtual to check for
-                various illegal overrides.  */
-             found_overriden_fn = 1;
-           }
-       }
+      /* Set DECL_VINDEX to a value that is neither an
+        INTEGER_CST nor the error_mark_node so that
+        add_virtual_function will realize this is an
+        overriding function.  */
+      DECL_VINDEX (decl) = decl;
     }
-  if (virtualp)
+  if (DECL_VIRTUAL_P (decl))
     {
       if (DECL_VINDEX (decl) == NULL_TREE)
        DECL_VINDEX (decl) = error_mark_node;
@@ -3562,12 +3537,7 @@ check_field_decls (t, access_decls, empty_p,
          TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
 
          if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
-           {
-             if (DECL_NAME (x))
-               cp_warning_at ("non-static reference `%#D' in class without a constructor", x);
-             else
-               cp_warning_at ("non-static reference in class without a constructor", x);
-           }
+            cp_warning_at ("non-static reference `%#D' in class without a constructor", x);
        }
 
       type = strip_array_types (type);
@@ -3599,12 +3569,7 @@ check_field_decls (t, access_decls, empty_p,
          TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
 
          if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
-           {
-             if (DECL_NAME (x))
-               cp_warning_at ("non-static const member `%#D' in class without a constructor", x);
-             else
-               cp_warning_at ("non-static const member in class without a constructor", x);
-           }
+            cp_warning_at ("non-static const member `%#D' in class without a constructor", x);
        }
       /* A field that is pseudo-const makes the structure likewise.  */
       else if (IS_AGGR_TYPE (type))
@@ -3695,116 +3660,208 @@ build_vtbl_or_vbase_field (name, assembler_name, type, class_type, fcontext,
   return field;
 }
 
-/* Record the type of BINFO in the slot in DATA (which is really a
-   `varray_type *') corresponding to the BINFO_OFFSET.  */
+/* If TYPE is an empty class type, records its OFFSET in the table of
+   OFFSETS.  */
 
-static tree
-dfs_record_base_offsets (binfo, data)
-     tree binfo;
-     void *data;
+static int
+record_subobject_offset (type, offset, offsets)
+     tree type;
+     tree offset;
+     splay_tree offsets;
 {
-  varray_type *v;
-  unsigned HOST_WIDE_INT offset = tree_low_cst (BINFO_OFFSET (binfo), 1);
+  splay_tree_node n;
 
-  v = (varray_type *) data;
-  while (VARRAY_SIZE (*v) <= offset)
-    VARRAY_GROW (*v, 2 * VARRAY_SIZE (*v));
-  VARRAY_TREE (*v, offset) = tree_cons (NULL_TREE,
-                                       BINFO_TYPE (binfo),
-                                       VARRAY_TREE (*v, offset));
+  if (!is_empty_class (type))
+    return 0;
 
-  return NULL_TREE;
+  /* Record the location of this empty object in OFFSETS.  */
+  n = splay_tree_lookup (offsets, (splay_tree_key) offset);
+  if (!n)
+    n = splay_tree_insert (offsets, 
+                          (splay_tree_key) offset,
+                          (splay_tree_value) NULL_TREE);
+  n->value = ((splay_tree_value) 
+             tree_cons (NULL_TREE,
+                        type,
+                        (tree) n->value));
+
+  return 0;
 }
 
-/* Add the offset of BINFO and its bases to BASE_OFFSETS.  */
+/* Returns non-zero if TYPE is an empty class type and there is
+   already an entry in OFFSETS for the same TYPE as the same OFFSET.  */
 
-static void
-record_base_offsets (binfo, base_offsets)
-     tree binfo;
-     varray_type *base_offsets;
+static int
+check_subobject_offset (type, offset, offsets)
+     tree type;
+     tree offset;
+     splay_tree offsets;
 {
-  dfs_walk (binfo,
-           dfs_record_base_offsets,
-           dfs_skip_vbases,
-           base_offsets);
+  splay_tree_node n;
+  tree t;
+
+  if (!is_empty_class (type))
+    return 0;
+
+  /* Record the location of this empty object in OFFSETS.  */
+  n = splay_tree_lookup (offsets, (splay_tree_key) offset);
+  if (!n)
+    return 0;
+
+  for (t = (tree) n->value; t; t = TREE_CHAIN (t))
+    if (same_type_p (TREE_VALUE (t), type))
+      return 1;
+
+  return 0;
 }
 
-/* Returns non-NULL if there is already an entry in DATA (which is
-   really a `varray_type') indicating that an object with the same
-   type of BINFO is already at the BINFO_OFFSET for BINFO.  */
+/* Walk through all the subobjects of TYPE (located at OFFSET).  Call
+   F for every subobject, passing it the type, offset, and table of
+   OFFSETS.  If VBASES_P is non-zero, then even non-virtual primary
+   bases should be traversed; otherwise, they are ignored.  If F
+   returns a non-zero value, the traversal ceases, and that value is
+   returned.  Otherwise, returns zero.  */
 
-static tree
-dfs_search_base_offsets (binfo, data)
-     tree binfo;
-     void *data;
+static int
+walk_subobject_offsets (type, f, offset, offsets, vbases_p)
+     tree type;
+     subobject_offset_fn f;
+     tree offset;
+     splay_tree offsets;
+     int vbases_p;
 {
-  if (is_empty_class (BINFO_TYPE (binfo)))
+  int r = 0;
+
+  if (CLASS_TYPE_P (type))
     {
-      varray_type v = (varray_type) data;
-      /* Find the offset for this BINFO.  */
-      unsigned HOST_WIDE_INT offset = tree_low_cst (BINFO_OFFSET (binfo), 1);
-      tree t;
+      tree field;
+      int i;
 
-      /* If we haven't yet encountered any objects at offsets that
-        big, then there's no conflict.  */
-      if (VARRAY_SIZE (v) <= offset)
-       return NULL_TREE;
-      /* Otherwise, go through the objects already allocated at this
-        offset.  */
-      for (t = VARRAY_TREE (v, offset); t; t = TREE_CHAIN (t))
-       if (same_type_p (TREE_VALUE (t), BINFO_TYPE (binfo)))
-         return binfo;
+      /* 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_MARKED_P (binfo))
+           continue;
+
+         r = walk_subobject_offsets (BINFO_TYPE (binfo),
+                                     f,
+                                     size_binop (PLUS_EXPR,
+                                                 offset,
+                                                 BINFO_OFFSET (binfo)),
+                                     offsets,
+                                     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)
+         {
+           r = walk_subobject_offsets (TREE_TYPE (field),
+                                       f,
+                                       size_binop (PLUS_EXPR,
+                                                   offset,
+                                                   DECL_FIELD_OFFSET (field)),
+                                       offsets,
+                                       /*vbases_p=*/1);
+           if (r)
+             return r;
+         }
+    }
+  else if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      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,
+                                     offsets,
+                                     /*vbases_p=*/1);
+         if (r)
+           return r;
+         offset = size_binop (PLUS_EXPR, offset, 
+                              TYPE_SIZE_UNIT (TREE_TYPE (type)));
+       }
     }
 
-  return NULL_TREE;
+  return 0;
+}
+
+/* Record all of the empty subobjects of TYPE (located at OFFSET) in
+   OFFSETS.  If VBASES_P is non-zero, virtual bases of TYPE are
+   examined.  */
+
+static void
+record_subobject_offsets (type, offset, offsets, vbases_p)
+     tree type;
+     tree offset;
+     splay_tree offsets;
+     int vbases_p;
+{
+  walk_subobject_offsets (type, record_subobject_offset, offset,
+                         offsets, vbases_p);
 }
 
-/* Returns non-zero if there's a conflict between BINFO and a base
-   already mentioned in BASE_OFFSETS if BINFO is placed at its current
-   BINFO_OFFSET.  */
+/* Returns non-zero if any of the empty subobjects of TYPE (located at
+   OFFSET) conflict with entries in OFFSETS.  If VBASES_P is non-zero,
+   virtual bases of TYPE are examined.  */
 
 static int
-layout_conflict_p (binfo, base_offsets)
-     tree binfo;
-     varray_type base_offsets;
+layout_conflict_p (type, offset, offsets, vbases_p)
+     tree type;
+     tree offset;
+     splay_tree offsets;
+     int vbases_p;
 {
-  return dfs_walk (binfo, dfs_search_base_offsets, dfs_skip_vbases,
-                  base_offsets) != NULL_TREE;
+  return walk_subobject_offsets (type, check_subobject_offset, 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, or, if this is a
-   non-static data-member, a dummy BINFO for the type of the data
-   member.  BINFO may be NULL if checks to see if the field overlaps
-   an existing field with the same type are not required.  V maps
-   offsets to types already located at those offsets.  This function
-   determines the position of the DECL.  */
+   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 (rli, decl, binfo, v)
+layout_nonempty_base_or_field (rli, decl, binfo, offsets)
      record_layout_info rli;
      tree decl;
      tree binfo;
-     varray_type v;
+     splay_tree offsets;
 {
+  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)
     {
-      tree offset;
       struct record_layout_info_s old_rli = *rli;
 
       /* Place this field.  */
       place_field (rli, decl);
-      
-      /* Now that we know where it wil be placed, update its
-        BINFO_OFFSET.  */
       offset = byte_position (decl);
-      if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
-       propagate_binfo_offsets (binfo, 
-                                convert (ssizetype, offset));
  
       /* We have to check to see whether or not there is already
         something of the same type at the offset we're about to use.
@@ -3821,40 +3878,46 @@ layout_nonempty_base_or_field (rli, decl, binfo, v)
         empty class, have non-zero size, any overlap can happen only
         with a direct or indirect base-class -- it can't happen with
         a data member.  */
-      if (binfo && flag_new_abi && layout_conflict_p (binfo, v))
+      if (flag_new_abi && layout_conflict_p (TREE_TYPE (decl),
+                                            offset,
+                                            offsets, 
+                                            field_p))
        {
-         /* Undo the propagate_binfo_offsets call.  */
-         offset = size_diffop (size_zero_node, offset);
-         propagate_binfo_offsets (binfo, convert (ssizetype, offset));
-        
          /* 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;
 
-         /* Bump up by the alignment required for the type, without
-            virtual base classes.  */
+         /* Bump up by the alignment required for the type.  */
          rli->bitpos
-           = size_binop (PLUS_EXPR, rli->bitpos,
-                         bitsize_int (CLASSTYPE_ALIGN (BINFO_TYPE (binfo))));
+           = size_binop (PLUS_EXPR, rli->bitpos, 
+                         bitsize_int (binfo 
+                                      ? CLASSTYPE_ALIGN (type)
+                                      : TYPE_ALIGN (type)));
          normalize_rli (rli);
        }
       else
        /* There was no conflict.  We're done laying out this field.  */
        break;
     }
+
+  /* Now that we know where it wil be placed, update its
+     BINFO_OFFSET.  */
+  if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
+    propagate_binfo_offsets (binfo, 
+                            convert (ssizetype, offset));
 }
 
 /* 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; BINFO_OFFSETS gives the
-   offsets of the other bases allocated so far.  */
+   class of the type indicated by BINFO; OFFSETS gives the offsets of
+   the empty bases allocated so far.  */
 
 static void
-layout_empty_base (binfo, eoc, binfo_offsets)
+layout_empty_base (binfo, eoc, offsets)
      tree binfo;
      tree eoc;
-     varray_type binfo_offsets;
+     splay_tree offsets;
 {
   tree alignment;
   tree basetype = BINFO_TYPE (binfo);
@@ -3865,14 +3928,20 @@ layout_empty_base (binfo, eoc, binfo_offsets)
 
   /* This is an empty base class.  We first try to put it at offset
      zero.  */
-  if (layout_conflict_p (binfo, binfo_offsets))
+  if (layout_conflict_p (BINFO_TYPE (binfo),
+                        BINFO_OFFSET (binfo),
+                        offsets, 
+                        /*vbases_p=*/0))
     {
       /* That didn't work.  Now, we move forward from the next
         available spot in the class.  */
       propagate_binfo_offsets (binfo, convert (ssizetype, eoc));
       while (1) 
        {
-         if (!layout_conflict_p (binfo, binfo_offsets))
+         if (!layout_conflict_p (BINFO_TYPE (binfo),
+                                 BINFO_OFFSET (binfo), 
+                                 offsets,
+                                 /*vbases_p=*/0))
            /* We finally found a spot where there's no overlap.  */
            break;
 
@@ -3885,15 +3954,15 @@ layout_empty_base (binfo, eoc, binfo_offsets)
 /* 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.  */
+   class.  OFFSETS gives the location of empty base subobjects.  */
 
 static void
-build_base_field (rli, binfo, empty_p, base_align, v)
+build_base_field (rli, binfo, empty_p, base_align, offsets)
      record_layout_info rli;
      tree binfo;
      int *empty_p;
      unsigned int *base_align;
-     varray_type *v;
+     splay_tree offsets;
 {
   tree basetype = BINFO_TYPE (binfo);
   tree decl;
@@ -3934,7 +4003,7 @@ build_base_field (rli, binfo, empty_p, base_align, v)
       /* 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, *v);
+      layout_nonempty_base_or_field (rli, decl, binfo, offsets);
     }
   else
     {
@@ -3943,8 +4012,8 @@ build_base_field (rli, binfo, empty_p, base_align, v)
       /* 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 (decl)) * DECL_ALIGN (decl);
-      layout_empty_base (binfo, size_int (eoc), *v);
+      eoc = CEIL (eoc, DECL_ALIGN_UNIT (decl)) * DECL_ALIGN_UNIT (decl);
+      layout_empty_base (binfo, size_int (eoc), offsets);
     }
 
   /* Check for inaccessible base classes.  If the same base class
@@ -3955,33 +4024,33 @@ build_base_field (rli, binfo, empty_p, base_align, v)
                basetype, rli->t);
   
   /* Record the offsets of BINFO and its base subobjects.  */
-  record_base_offsets (binfo, v);
+  record_subobject_offsets (BINFO_TYPE (binfo), 
+                           BINFO_OFFSET (binfo),
+                           offsets, 
+                           /*vbases_p=*/0);
 }
 
-/* Layout all of the non-virtual base classes.  Returns a map from
-   offsets to types present at those offsets.  */
+/* Layout all of the non-virtual base classes.  Record empty
+   subobjects in OFFSETS.  */
 
-static varray_type
-build_base_fields (rli, empty_p)
+static void
+build_base_fields (rli, empty_p, offsets)
      record_layout_info rli;
      int *empty_p;
+     splay_tree offsets;
 {
   /* 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;
-  varray_type v;
   unsigned int base_align = 0;
 
-  /* Create the table mapping offsets to empty base classes.  */
-  VARRAY_TREE_INIT (v, 32, "v");
-
   /* Under the new ABI, the primary base class is always allocated
      first.  */
   if (flag_new_abi && CLASSTYPE_HAS_PRIMARY_BASE_P (rec))
     build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec), 
-                     empty_p, &base_align, &v);
+                     empty_p, &base_align, offsets);
 
   /* Now allocate the rest of the bases.  */
   for (i = 0; i < n_baseclasses; ++i)
@@ -4002,10 +4071,8 @@ build_base_fields (rli, empty_p)
          && !BINFO_PRIMARY_MARKED_P (base_binfo))
        continue;
 
-      build_base_field (rli, base_binfo, empty_p, &base_align, &v);
+      build_base_field (rli, base_binfo, empty_p, &base_align, offsets);
     }
-
-  return v;
 }
 
 /* Go through the TYPE_METHODS of T issuing any appropriate
@@ -4207,6 +4274,12 @@ clone_function_decl (fn, update_method_vec_p)
 {
   tree clone;
 
+  /* Avoid inappropriate cloning.  */
+  if (! flag_new_abi
+      || (TREE_CHAIN (fn)
+         && DECL_CLONED_FUNCTION (TREE_CHAIN (fn))))
+    return;
+
   if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn))
     {
       /* For each constructor, we need two variants: an in-charge version
@@ -4448,15 +4521,12 @@ create_vtable_ptr (t, empty_p, vfuns_p,
    complete.  */
 
 static void
-fixup_pending_inline (info)
-     struct pending_inline *info;
+fixup_pending_inline (fn)
+     tree fn;
 {
-  if (info)
+  if (DECL_PENDING_INLINE_INFO (fn))
     {
-      tree args;
-      tree fn = info->fndecl;
-
-      args = DECL_ARGUMENTS (fn);
+      tree args = DECL_ARGUMENTS (fn);
       while (args)
        {
          DECL_CONTEXT (args) = fn;
@@ -4486,13 +4556,13 @@ fixup_inline_methods (type)
 
   /* Do inline member functions.  */
   for (; method; method = TREE_CHAIN (method))
-    fixup_pending_inline (DECL_PENDING_INLINE_INFO (method));
+    fixup_pending_inline (method);
 
   /* Do friends.  */
   for (method = CLASSTYPE_INLINE_FRIENDS (type); 
        method; 
        method = TREE_CHAIN (method))
-    fixup_pending_inline (DECL_PENDING_INLINE_INFO (TREE_VALUE (method)));
+    fixup_pending_inline (TREE_VALUE (method));
   CLASSTYPE_INLINE_FRIENDS (type) = NULL_TREE;
 }
 
@@ -4577,13 +4647,13 @@ dfs_set_offset_for_unshared_vbases (binfo, data)
 }
 
 /* Set BINFO_OFFSET for all of the virtual bases for T.  Update
-   TYPE_ALIGN and TYPE_SIZE for T.  BASE_OFFSETS is a varray mapping
-   offsets to the types at those offsets.  */
+   TYPE_ALIGN and TYPE_SIZE for T.  OFFSETS gives the location of
+   empty subobjects of T.  */
 
 static void
-layout_virtual_bases (t, base_offsets)
+layout_virtual_bases (t, offsets)
      tree t;
-     varray_type *base_offsets;
+     splay_tree offsets;
 {
   tree vbases;
   unsigned HOST_WIDE_INT dsize;
@@ -4653,7 +4723,7 @@ layout_virtual_bases (t, base_offsets)
          if (flag_new_abi && is_empty_class (basetype))
            layout_empty_base (vbase,
                               size_int (CEIL (dsize, BITS_PER_UNIT)),
-                              *base_offsets);
+                              offsets);
          else
            {
              tree offset;
@@ -4673,7 +4743,10 @@ layout_virtual_bases (t, base_offsets)
            }
 
          /* Keep track of the offsets assigned to this virtual base.  */
-         record_base_offsets (vbase, base_offsets);
+         record_subobject_offsets (BINFO_TYPE (vbase), 
+                                   BINFO_OFFSET (vbase),
+                                   offsets,
+                                   /*vbases_p=*/0);
        }
     }
 
@@ -4748,6 +4821,16 @@ end_of_class (t, include_virtuals_p)
   return result;
 }
 
+/* Compare two INTEGER_CSTs K1 and K2.  */
+
+static int
+splay_tree_compare_integer_csts (k1, k2)
+     splay_tree_key k1;
+     splay_tree_key k2;
+{
+  return tree_int_cst_compare ((tree) k1, (tree) k2);
+}
+
 /* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T.  Calculate
    BINFO_OFFSETs for all of the base-classes.  Position the vtable
    pointer.  */
@@ -4765,8 +4848,10 @@ layout_class_type (t, empty_p, vfuns_p,
   tree field;
   tree vptr;
   record_layout_info rli;
-  varray_type v;
   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;
 
   /* Keep track of the first non-static data member.  */
   non_static_data_members = TYPE_FIELDS (t);
@@ -4791,7 +4876,9 @@ layout_class_type (t, empty_p, vfuns_p,
     }
 
   /* Build FIELD_DECLs for all of the non-virtual base-types.  */
-  v = build_base_fields (rli, empty_p);
+  empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts, 
+                                      NULL, NULL);
+  build_base_fields (rli, empty_p, empty_base_offsets);
   /* Add pointers to all of our virtual base-classes.  */
   TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (rli, empty_p),
                             TYPE_FIELDS (t));
@@ -4804,7 +4891,6 @@ layout_class_type (t, empty_p, vfuns_p,
   /* Layout the non-static data members.  */
   for (field = non_static_data_members; field; field = TREE_CHAIN (field))
     {
-      tree binfo;
       tree type;
       tree padding;
 
@@ -4856,10 +4942,8 @@ layout_class_type (t, empty_p, vfuns_p,
       else
        padding = NULL_TREE;
 
-      /* Create a dummy BINFO corresponding to this field.  */
-      binfo = make_binfo (size_zero_node, type, NULL_TREE, NULL_TREE);
-      unshare_base_binfos (binfo);
-      layout_nonempty_base_or_field (rli, field, binfo, v);
+      layout_nonempty_base_or_field (rli, field, NULL_TREE,
+                                    empty_base_offsets);
 
       /* If we needed additional padding after this field, add it
         now.  */
@@ -4874,7 +4958,9 @@ layout_class_type (t, empty_p, vfuns_p,
          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, v);
+         layout_nonempty_base_or_field (rli, padding_field,
+                                        NULL_TREE, 
+                                        empty_base_offsets);
        }
     }
 
@@ -4960,10 +5046,10 @@ layout_class_type (t, empty_p, vfuns_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, &v);
+  layout_virtual_bases (t, empty_base_offsets);
 
   /* Clean up.  */
-  VARRAY_FREE (v);
+  splay_tree_delete (empty_base_offsets);
 }
 
 /* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
@@ -5200,7 +5286,7 @@ finish_struct_1 (t)
   maybe_suppress_debug_info (t);
 
   /* Finish debugging output for this type.  */
-  rest_of_type_compilation (t, toplevel_bindings_p ());
+  rest_of_type_compilation (t, ! LOCAL_CLASS_P (t));
 }
 
 /* When T was built up, the member declarations were added in reverse
@@ -5267,7 +5353,7 @@ finish_struct (t, attributes)
     {
       tree scope = current_scope ();
       if (scope && TREE_CODE (scope) == FUNCTION_DECL)
-       add_tree (build_min (TAG_DEFN, t));
+       add_stmt (build_min (TAG_DEFN, t));
     }
 
   return t;
@@ -5425,6 +5511,10 @@ init_class_processing ()
   access_public_virtual_node = build_int_2 (4 | ak_public, 0);
   access_protected_virtual_node = build_int_2 (4 | ak_protected, 0);
   access_private_virtual_node = build_int_2 (4 | ak_private, 0);
+
+  ridpointers[(int) RID_PUBLIC] = access_public_node;
+  ridpointers[(int) RID_PRIVATE] = access_private_node;
+  ridpointers[(int) RID_PROTECTED] = access_protected_node;
 }
 
 /* Set current scope to NAME. CODE tells us if this is a
@@ -5513,11 +5603,6 @@ pushclass (type, modify)
 
   pushlevel_class ();
 
-#if 0
-  if (CLASSTYPE_TEMPLATE_INFO (type))
-    overload_template_name (type);
-#endif
-
   if (modify)
     {
       if (type != previous_class_type || current_class_depth > 1)
@@ -5643,7 +5728,7 @@ push_nested_class (type, modify)
       || TREE_CODE (type) == NAMESPACE_DECL
       || ! IS_AGGR_TYPE (type)
       || TREE_CODE (type) == TEMPLATE_TYPE_PARM
-      || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
+      || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
     return;
   
   context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
@@ -5863,6 +5948,10 @@ resolve_address_of_overloaded_function (target_type,
        target_fn_type = TREE_TYPE (target_type);
       target_arg_types = TYPE_ARG_TYPES (target_fn_type);
       target_ret_type = TREE_TYPE (target_fn_type);
+
+      /* Never do unification on the 'this' parameter.  */
+      if (TREE_CODE (target_fn_type) == METHOD_TYPE)
+       target_arg_types = TREE_CHAIN (target_arg_types);
          
       for (fns = overload; fns; fns = OVL_CHAIN (fns))
        {
@@ -5885,7 +5974,7 @@ resolve_address_of_overloaded_function (target_type,
          targs = make_tree_vec (DECL_NTPARMS (fn));
          if (fn_type_unification (fn, explicit_targs, targs,
                                   target_arg_types, target_ret_type,
-                                  DEDUCE_EXACT) != 0)
+                                  DEDUCE_EXACT, -1) != 0)
            /* Argument deduction failed.  */
            continue;
 
@@ -5909,8 +5998,7 @@ resolve_address_of_overloaded_function (target_type,
       /* Now, remove all but the most specialized of the matches.  */
       if (matches)
        {
-         tree match = most_specialized_instantiation (matches, 
-                                                      explicit_targs);
+         tree match = most_specialized_instantiation (matches);
 
          if (match != error_mark_node)
            matches = tree_cons (match, NULL_TREE, NULL_TREE);
@@ -5964,13 +6052,20 @@ resolve_address_of_overloaded_function (target_type,
   /* Good, exactly one match.  Now, convert it to the correct type.  */
   fn = TREE_PURPOSE (matches);
 
-  if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
+  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
       && !ptrmem && !flag_ms_extensions)
     {
+      static int explained;
+      
       if (!complain)
         return error_mark_node;
 
       cp_pedwarn ("assuming pointer to member `%D'", fn);
+      if (!explained)
+        {
+          cp_pedwarn ("(a pointer to member can only be formed with `&%E')", fn);
+          explained = 1;
+        }
     }
   mark_used (fn);
 
@@ -6426,8 +6521,8 @@ note_name_declared_in_class (name, decl)
         in its context and when re-evaluated in the completed scope of
         S.  */
       cp_error ("declaration of `%#D'", decl);
-      cp_error_at ("changes meaning of `%s' from `%+#D'", 
-                  IDENTIFIER_POINTER (DECL_NAME (OVL_CURRENT (decl))),
+      cp_error_at ("changes meaning of `%D' from `%+#D'", 
+                  DECL_NAME (OVL_CURRENT (decl)),
                   (tree) n->value);
     }
 }
@@ -6532,7 +6627,7 @@ dump_class_hierarchy_r (t, binfo, indent)
 
   fprintf (stderr, "%*s0x%lx (%s) ", indent, "",
           (unsigned long) binfo,
-          type_as_string (binfo, TS_PLAIN));
+          type_as_string (binfo, TFF_PLAIN_IDENTIFIER));
   fprintf (stderr, HOST_WIDE_INT_PRINT_DEC,
           tree_low_cst (BINFO_OFFSET (binfo), 0));
   if (TREE_VIA_VIRTUAL (binfo))
@@ -7098,7 +7193,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
   vtbl_init_data vid;
 
   /* Initialize VID.  */
-  bzero (&vid, sizeof (vid));
+  memset (&vid, 0, sizeof (vid));
   vid.binfo = binfo;
   vid.derived = t;
   vid.last_init = &vid.inits;
@@ -7118,7 +7213,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
   build_vcall_and_vbase_vtbl_entries (binfo, &vid);
   /* Clean up.  */
   VARRAY_FREE (vid.fns);
-  /* Clear BINFO_VTABLE_PAATH_MARKED; it's set by
+  /* Clear BINFO_VTABLE_PATH_MARKED; it's set by
      build_vbase_offset_vtbl_entries.  */
   for (vbase = CLASSTYPE_VBASECLASSES (t); 
        vbase;