* class.c (check_field_decls): Split out from ...
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 15 Dec 1999 00:36:57 +0000 (00:36 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 15 Dec 1999 00:36:57 +0000 (00:36 +0000)
(finish_struct_1): ... here.  Use it.  Tidy.

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

gcc/cp/ChangeLog
gcc/cp/class.c

index 31b963e..3de530b 100644 (file)
@@ -1,5 +1,8 @@
 1999-12-14  Mark Mitchell  <mark@codesourcery.com>
 
+       * class.c (check_field_decls): Split out from ...
+       (finish_struct_1): ... here.  Use it.  Tidy.
+
        * cp-tree.h (remap_save_expr): Add walk_subtrees parameter.
        * optimize.c (copy_body_r): Pass it.
        * tree.c (remap_save_expr): Clear walk_subtrees for an
index 60132b5..9406152 100644 (file)
@@ -123,6 +123,8 @@ static int count_fields PROTO((tree));
 static int add_fields_to_vec PROTO((tree, tree, int));
 static void check_bitfield_decl PROTO((tree));
 static void check_field_decl PROTO((tree, tree, int *, int *, int *, int *));
+static tree* check_field_decls PROTO((tree, tree *, int *, int *, int *, 
+                                     int *));
 
 /* Variables shared between class.c and call.c.  */
 
@@ -3339,202 +3341,94 @@ check_field_decl (field, t, cant_have_const_ctor,
                             : TYPE_ALIGN (TREE_TYPE (field))));
 };
 
-/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
-   (or C++ class declaration).
-
-   For C++, we must handle the building of derived classes.
-   Also, C++ allows static class members.  The way that this is
-   handled is to keep the field name where it is (as the DECL_NAME
-   of the field), and place the overloaded decl in the DECL_FIELD_BITPOS
-   of the field.  layout_record and layout_union will know about this.
-
-   More C++ hair: inline functions have text in their
-   DECL_PENDING_INLINE_INFO nodes which must somehow be parsed into
-   meaningful tree structure.  After the struct has been laid out, set
-   things up so that this can happen.
-
-   And still more: virtual functions.  In the case of single inheritance,
-   when a new virtual function is seen which redefines a virtual function
-   from the base class, the new virtual function is placed into
-   the virtual function table at exactly the same address that
-   it had in the base class.  When this is extended to multiple
-   inheritance, the same thing happens, except that multiple virtual
-   function tables must be maintained.  The first virtual function
-   table is treated in exactly the same way as in the case of single
-   inheritance.  Additional virtual function tables have different
-   DELTAs, which tell how to adjust `this' to point to the right thing.
-
-   ATTRIBUTES is the set of decl attributes to be applied, if any.  */
-
-void
-finish_struct_1 (t)
-     tree t;
-{
-  tree fields = TYPE_FIELDS (t);
-  tree x, last_x, method_vec;
-  int has_virtual;
-  int max_has_virtual;
-  tree pending_virtuals = NULL_TREE;
-  tree pending_hard_virtuals = NULL_TREE;
-  tree abstract_virtuals = NULL_TREE;
-  tree vfield;
-  tree vfields;
-  tree virtual_dtor;
-  int cant_have_default_ctor;
-  int cant_have_const_ctor;
-  int no_const_asn_ref;
-  int has_mutable = 0;
-  int n_fields = 0;
-  int non_pod_class = 0;
-
-  /* The index of the first base class which has virtual
-     functions.  Only applied to non-virtual baseclasses.  */
-  int first_vfn_base_index;
+/* Check the data members (both static and non-static), class-scoped
+   typedefs, etc., appearing in the declaration of T.  Issue
+   appropriate diagnostics.  Sets ACCESS_DECLS to a list (in
+   declaration order) of access declarations; each TREE_VALUE in this
+   list is a USING_DECL.
 
-  int n_baseclasses;
-  int any_default_members = 0;
-  int const_sans_init = 0;
-  int ref_sans_init = 0;
-  tree access_decls = NULL_TREE;
-  int aggregate = 1;
-  int empty = 1;
-  int has_pointers = 0;
-  tree inline_friends;
-
-  if (TYPE_SIZE (t))
-    {
-      if (IS_AGGR_TYPE (t))
-       cp_error ("redefinition of `%#T'", t);
-      else
-       my_friendly_abort (172);
-      popclass ();
-      return;
-    }
+   In addition, set the following flags:
 
-  GNU_xref_decl (current_function_decl, t);
+     EMPTY_P
+       The class is empty, i.e., contains no non-static data members.
 
-  /* If this type was previously laid out as a forward reference,
-     make sure we lay it out again.  */
+     CANT_HAVE_DEFAULT_CTOR_P
+       This class cannot have an implicitly generated default
+       constructor.
 
-  TYPE_SIZE (t) = NULL_TREE;
-  CLASSTYPE_GOT_SEMICOLON (t) = 0;
+     CANT_HAVE_CONST_CTOR_P
+       This class cannot have an implicitly generated copy constructor
+       taking a const reference.
 
-  /* Install struct as DECL_FIELD_CONTEXT of each field decl.
-     Also process specified field sizes.
-     Set DECL_FIELD_SIZE to the specified size, or 0 if none specified.
-     The specified size is found in the DECL_INITIAL.
-     Store 0 there, except for ": 0" fields (so we can find them
-     and delete them, below).  */
+     CANT_HAVE_CONST_ASN_REF
+       This class cannot have an implicitly generated assignment
+       operator taking a const reference.
 
-  if (TYPE_BINFO_BASETYPES (t))
-    n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t));
-  else
-    n_baseclasses = 0;
+   All of these flags should be initialized before calling this
+   function.
 
-  if (n_baseclasses > 0)
-    {
-      struct base_info base_info;
+   Returns a pointer to the end of the TYPE_FIELDs chain; additional
+   fields can be added by adding to this chain.  */
 
-      first_vfn_base_index = finish_base_struct (t, &base_info);
-      /* Remember where we got our vfield from.  */
-      CLASSTYPE_VFIELD_PARENT (t) = first_vfn_base_index;
-      has_virtual = base_info.has_virtual;
-      max_has_virtual = base_info.max_has_virtual;
-      vfield = base_info.vfield;
-      vfields = base_info.vfields;
-      CLASSTYPE_RTTI (t) = base_info.rtti;
-      cant_have_default_ctor = base_info.cant_have_default_ctor;
-      cant_have_const_ctor = base_info.cant_have_const_ctor;
-      no_const_asn_ref = base_info.no_const_asn_ref;
-      aggregate = 0;
-    }
-  else
-    {
-      first_vfn_base_index = -1;
-      has_virtual = 0;
-      max_has_virtual = has_virtual;
-      vfield = NULL_TREE;
-      vfields = NULL_TREE;
-      CLASSTYPE_RTTI (t) = NULL_TREE;
-      cant_have_default_ctor = 0;
-      cant_have_const_ctor = 0;
-      no_const_asn_ref = 0;
-    }
-
-  /* The three of these are approximations which may later be
-     modified.  Needed at this point to make add_virtual_function
-     and modify_vtable_entries work.  */
-  CLASSTYPE_VFIELDS (t) = vfields;
-  TYPE_VFIELD (t) = vfield;
+static tree*
+check_field_decls (t, access_decls, empty_p, 
+                  cant_have_default_ctor_p, cant_have_const_ctor_p,
+                  no_const_asn_ref_p)
+     tree t;
+     tree *access_decls;
+     int *empty_p;
+     int *cant_have_default_ctor_p;
+     int *cant_have_const_ctor_p;
+     int *no_const_asn_ref_p;
+{
+  tree *field;
+  tree *next;
+  int has_pointers;
+  int any_default_members;
+
+  /* Assume there are no access declarations.  */
+  *access_decls = NULL_TREE;
+  /* Assume this class has no pointer members.  */
+  has_pointers = 0;
+  /* Assume none of the members of this class have default
+     initializations.  */
+  any_default_members = 0;
+
+  for (field = &TYPE_FIELDS (t); *field; field = next)
+    {
+      tree x = *field;
+      tree type = TREE_TYPE (x);
 
-  for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
-    {
       GNU_xref_member (current_class_name, x);
 
-      /* If this was an evil function, don't keep it in class.  */
-      if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
-       continue;
-
-      /* Do both of these, even though they're in the same union;
-        if the insn `r' member and the size `i' member are
-        different sizes, as on the alpha, the larger of the two
-        will end up with garbage in it.  */
-      DECL_SAVED_INSNS (x) = 0;
-      DECL_FIELD_SIZE (x) = 0;
-
-      check_for_override (x, t);
-      if (DECL_ABSTRACT_VIRTUAL_P (x) && ! DECL_VINDEX (x))
-       cp_error_at ("initializer specified for non-virtual method `%D'", x);
-
-      /* The name of the field is the original field name
-        Save this in auxiliary field for later overloading.  */
-      if (DECL_VINDEX (x))
-       {
-         add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
-                               &has_virtual, x, t);
-         if (DECL_ABSTRACT_VIRTUAL_P (x))
-           abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals);
-#if 0
-         /* XXX Why did I comment this out?  (jason) */
-         else
-           TREE_USED (x) = 1;
-#endif
-       }
-    }
-
-  if (n_baseclasses)
-    fields = chainon (build_vbase_pointer_fields (t), fields);
-
-  last_x = NULL_TREE;
-  for (x = fields; x; x = TREE_CHAIN (x))
-    {
-      tree type = TREE_TYPE (x);
-      GNU_xref_member (current_class_name, x);
+      next = &TREE_CHAIN (x);
 
       if (TREE_CODE (x) == FIELD_DECL)
        {
          DECL_PACKED (x) |= TYPE_PACKED (t);
 
          if (DECL_C_BIT_FIELD (x) && integer_zerop (DECL_INITIAL (x)))
-           /* A zero-width bitfield doesn't do the trick.  */;
+           /* We don't treat zero-width bitfields as making a class
+              non-empty.  */
+           ;
          else
-           empty = 0;
+           *empty_p = 0;
        }
 
       if (TREE_CODE (x) == USING_DECL)
        {
-         /* Save access declarations for later.  */
-         if (last_x)
-           TREE_CHAIN (last_x) = TREE_CHAIN (x);
-         else
-           fields = TREE_CHAIN (x);
-         
-         access_decls = tree_cons (NULL_TREE, x, access_decls);
+         /* Prune the access declaration from the list of fields.  */
+         *field = TREE_CHAIN (x);
+
+         /* Save the access declarations for our caller.  */
+         *access_decls = tree_cons (NULL_TREE, x, *access_decls);
+
+         /* Since we've reset *FIELD there's no reason to skip to the
+            next field.  */
+         next = field;
          continue;
        }
 
-      last_x = x;
-
       if (TREE_CODE (x) == TYPE_DECL
          || TREE_CODE (x) == TEMPLATE_DECL)
        continue;
@@ -3570,11 +3464,6 @@ finish_struct_1 (t)
          TREE_TYPE (x) = type;
        }
 
-#if 0
-      if (DECL_NAME (x) == constructor_name (t))
-       cant_have_default_ctor = 1;
-#endif
-
       if (type == error_mark_node)
        continue;
          
@@ -3599,22 +3488,21 @@ finish_struct_1 (t)
       /* Now it can only be a FIELD_DECL.  */
 
       if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
-       aggregate = 0;
+       CLASSTYPE_NON_AGGREGATE (t) = 1;
 
       /* If this is of reference type, check if it needs an init.
         Also do a little ANSI jig if necessary.  */
       if (TREE_CODE (type) == REFERENCE_TYPE)
        {
-          non_pod_class = 1;
-          
+         CLASSTYPE_NON_POD_P (t) = 1;
          if (DECL_INITIAL (x) == NULL_TREE)
-           ref_sans_init = 1;
+           CLASSTYPE_REF_FIELDS_NEED_INIT (t) = 1;
 
          /* ARM $12.6.2: [A member initializer list] (or, for an
             aggregate, initialization by a brace-enclosed list) is the
             only way to initialize nonstatic const and reference
             members.  */
-         cant_have_default_ctor = 1;
+         *cant_have_default_ctor_p = 1;
          TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
 
          if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
@@ -3632,26 +3520,26 @@ finish_struct_1 (t)
        has_pointers = 1;
 
       if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (type))
-        has_mutable = 1;
+       CLASSTYPE_HAS_MUTABLE (t) = 1;
 
       if (! pod_type_p (type)
          /* For some reason, pointers to members are POD types themselves,
             but are not allowed in POD structs.  Silly.  */
          || TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
-        non_pod_class = 1;
+       CLASSTYPE_NON_POD_P (t) = 1;
 
       /* If any field is const, the structure type is pseudo-const.  */
       if (CP_TYPE_CONST_P (type))
        {
          C_TYPE_FIELDS_READONLY (t) = 1;
          if (DECL_INITIAL (x) == NULL_TREE)
-           const_sans_init = 1;
+           CLASSTYPE_READONLY_FIELDS_NEED_INIT (t) = 1;
 
          /* ARM $12.6.2: [A member initializer list] (or, for an
             aggregate, initialization by a brace-enclosed list) is the
             only way to initialize nonstatic const and reference
             members.  */
-         cant_have_default_ctor = 1;
+         *cant_have_default_ctor_p = 1;
          TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
 
          if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
@@ -3662,17 +3550,12 @@ finish_struct_1 (t)
                cp_warning_at ("non-static const member in class without a constructor", x);
            }
        }
-      else
+      /* A field that is pseudo-const makes the structure likewise.  */
+      else if (IS_AGGR_TYPE (type))
        {
-         /* A field that is pseudo-const makes the structure
-            likewise.  */
-         if (IS_AGGR_TYPE (type))
-           {
-             if (C_TYPE_FIELDS_READONLY (type))
-               C_TYPE_FIELDS_READONLY (t) = 1;
-             if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (type))
-               const_sans_init = 1;
-           }
+         C_TYPE_FIELDS_READONLY (t) |= C_TYPE_FIELDS_READONLY (type);
+         CLASSTYPE_READONLY_FIELDS_NEED_INIT (t) 
+           |= CLASSTYPE_READONLY_FIELDS_NEED_INIT (type);
        }
 
       /* We set DECL_C_BIT_FIELD in grokbitfield.
@@ -3681,21 +3564,12 @@ finish_struct_1 (t)
        check_bitfield_decl (x);
       else
        check_field_decl (x, t,
-                         &cant_have_const_ctor,
-                         &cant_have_default_ctor
-                         &no_const_asn_ref,
+                         cant_have_const_ctor_p,
+                         cant_have_default_ctor_p
+                         no_const_asn_ref_p,
                          &any_default_members);
     }
 
-  /* If this type has any constant members which did not come
-     with their own initialization, mark that fact here.  It is
-     not an error here, since such types can be saved either by their
-     constructors, or by fortuitous initialization.  */
-  CLASSTYPE_READONLY_FIELDS_NEED_INIT (t) = const_sans_init;
-  CLASSTYPE_REF_FIELDS_NEED_INIT (t) = ref_sans_init;
-  CLASSTYPE_ABSTRACT_VIRTUALS (t) = abstract_virtuals;
-  CLASSTYPE_HAS_MUTABLE (t) = has_mutable;
-
   /* Effective C++ rule 11.  */
   if (has_pointers && warn_ecpp && TYPE_HAS_CONSTRUCTOR (t)
       && ! (TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
@@ -3711,20 +3585,205 @@ finish_struct_1 (t)
       else if (! TYPE_HAS_ASSIGN_REF (t))
        cp_warning ("  but does not override `operator=(const %T&)'", t);
     }
+
+  /* We've built up the list of access declarations in reverse order.
+     Fix that now.  */
+  *access_decls = nreverse (*access_decls);
+
+  /* Return the last field.  */
+  return field;
+}
+
+/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
+   (or C++ class declaration).
+
+   For C++, we must handle the building of derived classes.
+   Also, C++ allows static class members.  The way that this is
+   handled is to keep the field name where it is (as the DECL_NAME
+   of the field), and place the overloaded decl in the DECL_FIELD_BITPOS
+   of the field.  layout_record and layout_union will know about this.
+
+   More C++ hair: inline functions have text in their
+   DECL_PENDING_INLINE_INFO nodes which must somehow be parsed into
+   meaningful tree structure.  After the struct has been laid out, set
+   things up so that this can happen.
+
+   And still more: virtual functions.  In the case of single inheritance,
+   when a new virtual function is seen which redefines a virtual function
+   from the base class, the new virtual function is placed into
+   the virtual function table at exactly the same address that
+   it had in the base class.  When this is extended to multiple
+   inheritance, the same thing happens, except that multiple virtual
+   function tables must be maintained.  The first virtual function
+   table is treated in exactly the same way as in the case of single
+   inheritance.  Additional virtual function tables have different
+   DELTAs, which tell how to adjust `this' to point to the right thing.
+
+   ATTRIBUTES is the set of decl attributes to be applied, if any.  */
+
+void
+finish_struct_1 (t)
+     tree t;
+{
+  tree fields;
+  tree x, method_vec;
+  tree *next_field;
+  int has_virtual;
+  int max_has_virtual;
+  tree pending_virtuals = NULL_TREE;
+  tree pending_hard_virtuals = NULL_TREE;
+  tree abstract_virtuals = NULL_TREE;
+  tree vfield;
+  tree vfields;
+  tree virtual_dtor;
+  int cant_have_default_ctor;
+  int cant_have_const_ctor;
+  int no_const_asn_ref;
+  int n_fields = 0;
+
+  /* The index of the first base class which has virtual
+     functions.  Only applied to non-virtual baseclasses.  */
+  int first_vfn_base_index;
+
+  int n_baseclasses;
+  int const_sans_init = 0;
+  tree access_decls;
+  int aggregate = 1;
+  int empty = 1;
+  tree inline_friends;
+
+  if (TYPE_SIZE (t))
+    {
+      if (IS_AGGR_TYPE (t))
+       cp_error ("redefinition of `%#T'", t);
+      else
+       my_friendly_abort (172);
+      popclass ();
+      return;
+    }
+
+  GNU_xref_decl (current_function_decl, t);
+
+  /* If this type was previously laid out as a forward reference,
+     make sure we lay it out again.  */
+
+  TYPE_SIZE (t) = NULL_TREE;
+  CLASSTYPE_GOT_SEMICOLON (t) = 0;
+
+  /* Install struct as DECL_FIELD_CONTEXT of each field decl.
+     Also process specified field sizes.
+     Set DECL_FIELD_SIZE to the specified size, or 0 if none specified.
+     The specified size is found in the DECL_INITIAL.
+     Store 0 there, except for ": 0" fields (so we can find them
+     and delete them, below).  */
+
+  if (TYPE_BINFO_BASETYPES (t))
+    n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t));
+  else
+    n_baseclasses = 0;
+
+  if (n_baseclasses > 0)
+    {
+      struct base_info base_info;
+
+      first_vfn_base_index = finish_base_struct (t, &base_info);
+      /* Remember where we got our vfield from.  */
+      CLASSTYPE_VFIELD_PARENT (t) = first_vfn_base_index;
+      has_virtual = base_info.has_virtual;
+      max_has_virtual = base_info.max_has_virtual;
+      vfield = base_info.vfield;
+      vfields = base_info.vfields;
+      CLASSTYPE_RTTI (t) = base_info.rtti;
+      cant_have_default_ctor = base_info.cant_have_default_ctor;
+      cant_have_const_ctor = base_info.cant_have_const_ctor;
+      no_const_asn_ref = base_info.no_const_asn_ref;
+      aggregate = 0;
+    }
+  else
+    {
+      first_vfn_base_index = -1;
+      has_virtual = 0;
+      max_has_virtual = has_virtual;
+      vfield = NULL_TREE;
+      vfields = NULL_TREE;
+      CLASSTYPE_RTTI (t) = NULL_TREE;
+      cant_have_default_ctor = 0;
+      cant_have_const_ctor = 0;
+      no_const_asn_ref = 0;
+    }
+
+  /* The three of these are approximations which may later be
+     modified.  Needed at this point to make add_virtual_function
+     and modify_vtable_entries work.  */
+  CLASSTYPE_VFIELDS (t) = vfields;
+  TYPE_VFIELD (t) = vfield;
+
+  for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
+    {
+      GNU_xref_member (current_class_name, x);
+
+      /* If this was an evil function, don't keep it in class.  */
+      if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
+       continue;
+
+      /* Do both of these, even though they're in the same union;
+        if the insn `r' member and the size `i' member are
+        different sizes, as on the alpha, the larger of the two
+        will end up with garbage in it.  */
+      DECL_SAVED_INSNS (x) = 0;
+      DECL_FIELD_SIZE (x) = 0;
+
+      check_for_override (x, t);
+      if (DECL_ABSTRACT_VIRTUAL_P (x) && ! DECL_VINDEX (x))
+       cp_error_at ("initializer specified for non-virtual method `%D'", x);
+
+      /* The name of the field is the original field name
+        Save this in auxiliary field for later overloading.  */
+      if (DECL_VINDEX (x))
+       {
+         add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
+                               &has_virtual, x, t);
+         if (DECL_ABSTRACT_VIRTUAL_P (x))
+           abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals);
+#if 0
+         /* XXX Why did I comment this out?  (jason) */
+         else
+           TREE_USED (x) = 1;
+#endif
+       }
+    }
+
+  if (n_baseclasses)
+    TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (t),
+                              TYPE_FIELDS (t));
+
+  /* Check all the data member declarations for legality.  */
+  next_field = check_field_decls (t, &access_decls, &empty,
+                                 &cant_have_default_ctor,
+                                 &cant_have_const_ctor,
+                                 &no_const_asn_ref);
+  fields = TYPE_FIELDS (t);
+
+  /* If this type has any constant members which did not come
+     with their own initialization, mark that fact here.  It is
+     not an error here, since such types can be saved either by their
+     constructors, or by fortuitous initialization.  */
+  CLASSTYPE_READONLY_FIELDS_NEED_INIT (t) = const_sans_init;
+  CLASSTYPE_ABSTRACT_VIRTUALS (t) = abstract_virtuals;
   
   /* Do some bookkeeping that will guide the generation of implicitly
      declared member functions.  */
   TYPE_HAS_COMPLEX_INIT_REF (t)
     |= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t)
-       || has_virtual || any_default_members);
+       || has_virtual);
   TYPE_NEEDS_CONSTRUCTING (t)
     |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t)
-       || has_virtual || any_default_members);
+       || has_virtual);
   CLASSTYPE_NON_AGGREGATE (t)
       = ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t);
   CLASSTYPE_NON_POD_P (t)
-      = non_pod_class || CLASSTYPE_NON_AGGREGATE (t)
-        || TYPE_HAS_DESTRUCTOR (t) || TYPE_HAS_ASSIGN_REF (t);
+    |= (CLASSTYPE_NON_AGGREGATE (t) || TYPE_HAS_DESTRUCTOR (t) 
+       || TYPE_HAS_ASSIGN_REF (t));
   TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t);
   TYPE_HAS_COMPLEX_ASSIGN_REF (t)
     |= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t);
@@ -3754,9 +3813,12 @@ finish_struct_1 (t)
       TYPE_HAS_DESTRUCTOR (t) = 0;
     }
 
-  for (access_decls = nreverse (access_decls); access_decls;
-       access_decls = TREE_CHAIN (access_decls))
-    handle_using_decl (TREE_VALUE (access_decls), t, method_vec, fields); 
+  /* Process the access-declarations.  */
+  while (access_decls)
+    {
+      handle_using_decl (TREE_VALUE (access_decls), t, method_vec, fields); 
+      access_decls = TREE_CHAIN (access_decls);
+    }
 
   if (vfield == NULL_TREE && has_virtual)
     {
@@ -3794,23 +3856,7 @@ finish_struct_1 (t)
       DECL_SAVED_INSNS (vfield) = 0;
       DECL_FIELD_SIZE (vfield) = 0;
       DECL_ALIGN (vfield) = TYPE_ALIGN (ptr_type_node);
-#if 0
-      /* This is more efficient, but breaks binary compatibility, turn
-        it on sometime when we don't care.  If we turn it on, we also
-        have to enable the code in dfs_init_vbase_pointers.  */
-      /* vfield is always first entry in structure.  */
-      TREE_CHAIN (vfield) = fields;
-      fields = vfield;
-#else
-      if (last_x)
-       {
-         my_friendly_assert (TREE_CHAIN (last_x) == NULL_TREE, 175);
-         TREE_CHAIN (last_x) = vfield;
-         last_x = vfield;
-       }
-      else
-       fields = vfield;
-#endif
+      *next_field = vfield;
       empty = 0;
       vfields = chainon (vfields, build_tree_list (NULL_TREE, t));
     }
@@ -3829,10 +3875,10 @@ finish_struct_1 (t)
 
   if (n_baseclasses)
     {
-      last_x = build_base_fields (t);
+      TYPE_FIELDS (t) = chainon (build_base_fields (t), TYPE_FIELDS (t));
 
       /* If all our bases are empty, we can be empty too.  */
-      for (x = last_x; empty && x; x = TREE_CHAIN (x))
+      for (x = TYPE_FIELDS (t); empty && x != fields; x = TREE_CHAIN (x))
        if (DECL_SIZE (x) != integer_zero_node)
          empty = 0;
     }
@@ -3855,9 +3901,6 @@ finish_struct_1 (t)
       TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1;
     }
 
-  if (n_baseclasses)
-    TYPE_FIELDS (t) = chainon (last_x, TYPE_FIELDS (t));
-
   layout_type (t);
 
   /* Remember the size and alignment of the class before adding
@@ -4180,8 +4223,6 @@ finish_struct_1 (t)
 
   /* Finish debugging output for this type.  */
   rest_of_type_compilation (t, toplevel_bindings_p ());
-
-  return;
 }
 
 /* When T was built up, the member declarations were added in reverse