OSDN Git Service

* call.c (joust): Don't warn about "confusing" conversions to the
[pf3gnuchains/gcc-fork.git] / gcc / cp / method.c
index e1ae250..a13082b 100644 (file)
@@ -1,9 +1,9 @@
 /* Handle the hair of processing (but not expanding) inline functions.
    Also manage function and variable name overloading.
-   Copyright (C) 1987, 89, 92-96, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
-   This file is part of GNU CC.
+This file is part of GNU CC.
    
 GNU CC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -31,28 +31,16 @@ Boston, MA 02111-1307, USA.  */
 
 /* Handle method declarations.  */
 #include "config.h"
-#include <stdio.h>
+#include "system.h"
 #include "tree.h"
 #include "cp-tree.h"
 #include "obstack.h"
-#include <ctype.h>
 #include "rtl.h"
 #include "expr.h"
 #include "output.h"
 #include "hard-reg-set.h"
 #include "flags.h"
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-
-#ifdef NEED_DECLARATION_INDEX
-extern char *index ();
-#endif
+#include "toplev.h"
 
 /* TREE_LIST of the current inline functions that need to be
    processed.  */
@@ -69,18 +57,17 @@ static char *scratch_firstobj;
 
 static void icat PROTO((HOST_WIDE_INT));
 static void dicat PROTO((HOST_WIDE_INT, HOST_WIDE_INT));
-static void flush_repeats PROTO((tree));
+static void flush_repeats PROTO((int, tree));
 static void build_overload_identifier PROTO((tree));
 static void build_overload_nested_name PROTO((tree));
 static void build_overload_int PROTO((tree, int));
 static void build_overload_identifier PROTO((tree));
 static void build_qualified_name PROTO((tree));
 static void build_overload_value PROTO((tree, tree, int));
-static void issue_nrepeats PROTO((tree));
+static void issue_nrepeats PROTO((int, tree));
 static char *build_mangled_name PROTO((tree,int,int));
 static void process_modifiers PROTO((tree));
 static void process_overload_item PROTO((tree,int));
-static char *thunk_printable_name PROTO((tree));
 static void do_build_assign_ref PROTO((tree));
 static void do_build_copy_constructor PROTO((tree));
 static tree largest_union_member PROTO((tree));
@@ -89,6 +76,16 @@ static tree build_decl_overload_real PROTO((tree, tree, tree, tree,
 static void build_template_template_parm_names PROTO((tree));
 static void build_template_parm_names PROTO((tree, tree));
 static void build_underscore_int PROTO((int));
+static void start_squangling PROTO((void));
+static void end_squangling PROTO((void));
+static int check_ktype PROTO((tree, int));
+static int issue_ktype PROTO((tree));
+static void build_overload_scope_ref PROTO((tree));
+static void build_mangled_template_parm_index PROTO((char *, tree));
+static int is_back_referenceable_type PROTO((tree));
+static int check_btype PROTO((tree));
+static void build_mangled_name_for_type PROTO((tree));
+static void build_mangled_name_for_type_with_Gcode PROTO((tree, int));
 
 # define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0)
 # define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C)))
@@ -179,7 +176,6 @@ do_inline_function_hair (type, friend_list)
 /* type tables for K and B type compression */
 static tree *btypelist = NULL;
 static tree *ktypelist = NULL;
-static tree lasttype = NULL;
 static int maxbsize = 0;
 static int maxksize = 0;
 
@@ -187,19 +183,14 @@ static int maxksize = 0;
 static int maxbtype = 0;
 static int maxktype = 0;
 
-/* Number of occurrences of last b type seen.  */
-static int nrepeats = 0;
-
 /* Array of types seen so far in top-level call to `build_mangled_name'.
    Allocated and deallocated by caller.  */
 static tree *typevec = NULL;
+static int  typevec_size;
 
 /* Number of types interned by `build_mangled_name' so far.  */
 static int maxtype = 0;
 
-/* Number of occurrences of last type seen.  */
-static int Nrepeats = 0;
-
 /* Nonzero if we should not try folding parameter types.  */
 static int nofold;
 
@@ -212,9 +203,7 @@ start_squangling ()
 {
   if (flag_do_squangling)
     {
-      lasttype = NULL;
       nofold = 0;
-      nrepeats = 0;
       maxbtype = 0;
       maxktype = 0;
       maxbsize = 50;
@@ -229,7 +218,6 @@ end_squangling ()
 {
   if (flag_do_squangling)
     {
-      lasttype = NULL;
       if (ktypelist)
         free (ktypelist);
       if (btypelist)
@@ -311,7 +299,8 @@ dicat (lo, hi)
 }
 
 static __inline void
-flush_repeats (type)
+flush_repeats (nrepeats, type)
+     int nrepeats;
      tree type;
 {
   int tindex = 0;
@@ -319,47 +308,73 @@ flush_repeats (type)
   while (typevec[tindex] != type)
     tindex++;
 
-  if (Nrepeats > 1)
+  if (nrepeats > 1)
     {
       OB_PUTC ('N');
-      icat (Nrepeats);
-      if (Nrepeats > 9)
+      icat (nrepeats);
+      if (nrepeats > 9)
        OB_PUTC ('_');
     }
   else
     OB_PUTC ('T');
-  Nrepeats = 0;
   icat (tindex);
   if (tindex > 9)
     OB_PUTC ('_');
 }
 
+/* Returns nonzero iff this is a type to which we will want to make
+   back-references (using the `B' code).  */
 
-/* issue squangling type repeating */
-static void
-issue_nrepeats (lasttype)
-     tree lasttype;
+int
+is_back_referenceable_type (type)
+     tree type;
 {
-  if (nrepeats == 1)
+  if (btypelist == NULL)
+    /* We're not generating any back-references.  */
+    return 0;
+
+  switch (TREE_CODE (type)) 
     {
-      switch (TREE_CODE (lasttype))
-        {
-          case INTEGER_TYPE:
-          case REAL_TYPE:
-          case VOID_TYPE:
-          case BOOLEAN_TYPE:
-            process_overload_item (lasttype, FALSE);
-            nrepeats = 0;
-            return;
-        }
+    case INTEGER_TYPE:
+    case REAL_TYPE:
+    case VOID_TYPE:
+    case BOOLEAN_TYPE:
+      /* These types have single-character manglings, so there's no
+        point in generating back-references.  */
+      return 0;         
+
+    case TEMPLATE_TYPE_PARM:
+      /* It would be a bit complex to demangle signatures correctly if
+        we generated back-references to these, and the manglings of
+        type parameters are short.  */
+      return 0;
+
+    default:
+      return 1;
     }
-  OB_PUTC ('n');
-  icat (nrepeats);
-  if (nrepeats > 9)
-    OB_PUTC ('_');
-  nrepeats = 0;
 }
 
+/* Issue the squangling code indicating NREPEATS repetitions of TYPE,
+   which was the last parameter type output.  */
+
+static void
+issue_nrepeats (nrepeats, type)
+     int nrepeats;
+     tree type;
+{
+  if (nrepeats == 1 && !is_back_referenceable_type (type))
+    /* For types whose manglings are short, don't bother using the
+       repetition code if there's only one repetition, since the
+       repetition code will be about as long as the ordinary mangling.  */ 
+    build_mangled_name_for_type (type);
+  else
+    {
+      OB_PUTC ('n');
+      icat (nrepeats);
+      if (nrepeats > 9)
+       OB_PUTC ('_');
+    }
+}
 
 /* Check to see if a tree node has been entered into the Kcode typelist    */
 /* if not, add it. Return -1 if it isn't found, otherwise return the index */
@@ -388,7 +403,7 @@ check_ktype (node, add)
       if (maxksize <= maxktype)
         {
           maxksize = maxksize* 3 / 2;
-          ktypelist = (tree *)xrealloc (sizeof (tree) * maxksize);
+          ktypelist = (tree *)xrealloc (ktypelist, sizeof (tree) * maxksize);
         }
       ktypelist[maxktype++] = localnode;
     }
@@ -412,43 +427,41 @@ issue_ktype (decl)
     }
   return FALSE;
 }
+  
+/* Build a representation for DECL, which may be an entity not at
+   global scope.  If so, a marker indicating that the name is
+   qualified has already been output, but the qualifying context has
+   not.  */
 
 static void
 build_overload_nested_name (decl)
      tree decl;
 {
+  tree context;
 
   if (ktypelist && issue_ktype (decl))
       return;
 
-   if (DECL_CONTEXT (decl))
-    {
-      tree context = DECL_CONTEXT (decl);
+  if (decl == global_namespace)
+    return;
 
-      /* try to issue a K type, and if we can't continue the normal path */
-      if (!(ktypelist && issue_ktype (context)))
-        {
-          /* For a template type parameter, we want to output an 'Xn'
-             rather than 'T' or some such. */
-          if (TREE_CODE (context) == TEMPLATE_TYPE_PARM
-              || TREE_CODE (context) == TEMPLATE_TEMPLATE_PARM)
-            build_mangled_name (context, 0, 0);
-          else
-            {
-              if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
-                context = TYPE_NAME (context);
-              build_overload_nested_name (context);
-            }
-        }
+  context = CP_DECL_CONTEXT (decl);
+
+  /* try to issue a K type, and if we can't continue the normal path */
+  if (!(ktypelist && issue_ktype (context)))
+  {
+    /* For a template type parameter, we want to output an 'Xn'
+       rather than 'T' or some such. */
+    if (TREE_CODE (context) == TEMPLATE_TYPE_PARM
+        || TREE_CODE (context) == TEMPLATE_TEMPLATE_PARM)
+      build_mangled_name_for_type (context);
+    else
+    {
+      if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
+        context = TYPE_NAME (context);
+      build_overload_nested_name (context);
     }
-  else if (decl == global_namespace)
-    return;
-  else if (DECL_NAMESPACE (decl))
-    build_overload_nested_name (DECL_NAMESPACE (decl));
-  else
-    /* XXX the above does not work for non-namespaces */
-    if (current_namespace && TREE_CODE (decl) != NAMESPACE_DECL)
-      build_overload_nested_name (current_namespace);
+  }
 
   if (TREE_CODE (decl) == FUNCTION_DECL)
     {
@@ -470,6 +483,9 @@ build_overload_nested_name (decl)
     build_overload_identifier (decl);
 }
 
+/* Output the decimal representation of I.  If I > 9, the decimal
+   representation is preceeded and followed by an underscore.  */
+
 static void
 build_underscore_int (i)
      int i;
@@ -481,6 +497,16 @@ build_underscore_int (i)
     OB_PUTC ('_');
 }
 
+static void
+build_overload_scope_ref (value)
+     tree value;
+{
+  OB_PUTC2 ('Q', '2');
+  numeric_output_need_bar = 0;
+  build_mangled_name_for_type (TREE_OPERAND (value, 0));
+  build_overload_identifier (TREE_OPERAND (value, 1));
+}
+
 /* Encoding for an INTEGER_CST value.  */
 
 static void
@@ -489,13 +515,77 @@ build_overload_int (value, in_template)
      int in_template;
 {
   if (in_template && TREE_CODE (value) != INTEGER_CST)
-    /* We don't ever want this output, but it's inconvenient not to
-       be able to build the string.  This should cause assembler
-       errors we'll notice.  */
     {
-      static int n;
-      sprintf (digit_buffer, " *%d", n++);
-      OB_PUTCP (digit_buffer);
+      if (TREE_CODE (value) == SCOPE_REF)
+       {
+         build_overload_scope_ref (value);
+         return;
+       }
+
+      OB_PUTC ('E');
+      numeric_output_need_bar = 0;
+
+      if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (value))))
+       {
+         int i;
+         int operands = tree_code_length[(int) TREE_CODE (value)];
+         tree id;
+         char* name;
+
+         id = ansi_opname [(int) TREE_CODE (value)];
+         my_friendly_assert (id != NULL_TREE, 0);
+         name = IDENTIFIER_POINTER (id);
+         if (name[0] != '_' || name[1] != '_')
+           /* On some erroneous inputs, we can get here with VALUE a
+              LOOKUP_EXPR.  In that case, the NAME will be the
+              identifier for "<invalid operator>".  We must survive
+              this routine in order to issue a sensible error
+              message, so we fall through to the case below.  */
+           goto bad_value;
+
+         for (i = 0; i < operands; ++i)
+           {
+             tree operand;
+             enum tree_code tc;
+
+             /* We just outputted either the `E' or the name of the
+                operator.  */
+             numeric_output_need_bar = 0;
+
+             if (i != 0)
+               /* Skip the leading underscores.  */
+               OB_PUTCP (name + 2);
+
+             operand = TREE_OPERAND (value, i);
+             tc = TREE_CODE (operand);
+
+             if (TREE_CODE_CLASS (tc) == 't')
+               /* We can get here with sizeof, e.g.:
+                    
+                  template <class T> void f(A<sizeof(T)>);  */
+               build_mangled_name_for_type (operand);
+             else if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (tc)))
+               build_overload_int (operand, in_template);
+             else
+               build_overload_value (TREE_TYPE (operand),
+                                     operand,
+                                     in_template);
+           }
+       }
+      else
+       {
+         /* We don't ever want this output, but it's
+            inconvenient not to be able to build the string.
+            This should cause assembler errors we'll notice.  */
+           
+         static int n;
+       bad_value:
+         sprintf (digit_buffer, " *%d", n++);
+         OB_PUTCP (digit_buffer);
+       }
+
+      OB_PUTC ('W');
+      numeric_output_need_bar = 0;
       return;
     }
 
@@ -507,12 +597,14 @@ build_overload_int (value, in_template)
        {
          /* need to print a DImode value in decimal */
          dicat (TREE_INT_CST_LOW (value), TREE_INT_CST_HIGH (value));
+         numeric_output_need_bar = 1;
          return;
        }
       /* else fall through to print in smaller mode */
     }
   /* Wordsize or smaller */
   icat (TREE_INT_CST_LOW (value));
+  numeric_output_need_bar = 1;
 }
 
 
@@ -541,8 +633,11 @@ build_overload_value (type, value, in_template)
   while (TREE_CODE (value) == NON_LVALUE_EXPR
         || TREE_CODE (value) == NOP_EXPR)
     value = TREE_OPERAND (value, 0);
-  my_friendly_assert (TREE_CODE (type) == PARM_DECL, 242);
-  type = TREE_TYPE (type);
+
+  if (TREE_CODE (type) == PARM_DECL)
+    type = TREE_TYPE (type);
+
+  my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (type)) == 't', 0);
 
   if (numeric_output_need_bar)
     {
@@ -579,7 +674,6 @@ build_overload_value (type, value, in_template)
     case BOOLEAN_TYPE:
       {
        build_overload_int (value, in_template);
-       numeric_output_need_bar = 1;
        return;
       }
     case REAL_TYPE:
@@ -682,7 +776,6 @@ build_overload_value (type, value, in_template)
                    {
                      OB_PUTC ('i');
                      build_overload_int (a3, in_template);
-                     numeric_output_need_bar = 1;
                      return;
                    }
                }
@@ -693,7 +786,6 @@ build_overload_value (type, value, in_template)
       if (TREE_CODE (value) == INTEGER_CST)
        {
          build_overload_int (value, in_template);
-         numeric_output_need_bar = 1;
          return;
        }
       else if (TREE_CODE (value) == TEMPLATE_PARM_INDEX)
@@ -717,13 +809,7 @@ build_overload_value (type, value, in_template)
          return;
        }
       else if (TREE_CODE (value) == SCOPE_REF)
-       {
-         OB_PUTC2 ('Q', '1');
-         numeric_output_need_bar = 0;
-         build_mangled_name (TREE_OPERAND (value, 0), 0, 0);
-         build_overload_identifier (TREE_OPERAND (value, 1));
-         return;
-       }
+       build_overload_scope_ref (value);
       else
        my_friendly_abort (71);
       break; /* not really needed */
@@ -763,10 +849,8 @@ build_template_template_parm_names (parmlist)
          build_template_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (parm));
        }
       else
-       {
-         /* It's a PARM_DECL.  */
-         build_mangled_name (TREE_TYPE (parm), 0, 0);
-       }
+       /* It's a PARM_DECL.  */
+       build_mangled_name_for_type (TREE_TYPE (parm));
     }
 }
 
@@ -791,14 +875,14 @@ build_template_parm_names (parmlist, arglist)
        {
          /* This parameter is a type.  */
          OB_PUTC ('Z');
-         build_mangled_name (arg, 0, 0);
+         build_mangled_name_for_type (arg);
        }
       else if (TREE_CODE (parm) == TEMPLATE_DECL)
        {
          /* This parameter is a template. */
          if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
            /* Output parameter declaration, argument index and level */
-           build_mangled_name (arg, 0, 0);
+           build_mangled_name_for_type (arg);
          else
            {
              /* A TEMPLATE_DECL node, output the parameter declaration 
@@ -814,12 +898,14 @@ build_template_parm_names (parmlist, arglist)
        {
          parm = tsubst (parm, arglist, NULL_TREE);
          /* It's a PARM_DECL.  */
-         build_mangled_name (TREE_TYPE (parm), 0, 0);
+         build_mangled_name_for_type (TREE_TYPE (parm));
          build_overload_value (parm, arg, uses_template_parms (arglist));
        }
     }
  }
 
+/* Output the representation for NAME, which is either a TYPE_DECL or
+   an IDENTIFIER.  */
 
 static void
 build_overload_identifier (name)
@@ -833,9 +919,10 @@ build_overload_identifier (name)
                                       (TREE_TYPE (name))))
              == FUNCTION_DECL)))
     {
+      /* NAME is the TYPE_DECL for a template specialization.  */
       tree template, parmlist, arglist, tname;
       template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name));
-      arglist = TREE_VALUE (template);
+      arglist = innermost_args (TREE_VALUE (template), 0);
       template = TREE_PURPOSE (template);
       tname = DECL_NAME (template);
       parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
@@ -875,7 +962,10 @@ build_qualified_name (decl)
   if (TREE_CODE (decl) == TYPE_DECL
       && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) && !flag_do_squangling)
     {
-      OB_PUTID (DECL_ASSEMBLER_NAME (decl));
+      tree id = DECL_ASSEMBLER_NAME (decl);
+      OB_PUTID (id);
+      if (ISDIGIT (IDENTIFIER_POINTER (id) [IDENTIFIER_LENGTH (id) - 1]))
+       numeric_output_need_bar = 1;
       return;
     }
 
@@ -883,8 +973,8 @@ build_qualified_name (decl)
   /* if we can't find a Ktype, do it the hard way */
   if (check_ktype (context, FALSE) == -1)
     {
-      /* count type scopes */
-      while (DECL_CONTEXT (context))
+      /* count type and namespace scopes */
+      while (DECL_CONTEXT (context) && DECL_CONTEXT (context) != global_namespace)
        {
          i += 1;
          context = DECL_CONTEXT (context);
@@ -893,40 +983,43 @@ build_qualified_name (decl)
          if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
            context = TYPE_NAME (context);
        }
-      /* now count namespace scopes */
-      if (TREE_CODE (decl) == NAMESPACE_DECL)
-       {
-         i = 0; /* we have nothing done, yet: reset */
-         context = decl;
-       }
-      else
-       /* decl must be a type, which we have to scope with the
-          namespace */
-       {
-         /* XXX MvL somehow, types have no lang_decl, so no namespace */
-         context = current_namespace;
-       }    
-    }
-
-  while (context != global_namespace)
-    {
-      i += 1;
-      context = DECL_NAMESPACE (context);
     }
 
   if (i > 1)
     {
       OB_PUTC ('Q');
-      if (i > 9)
-       OB_PUTC ('_');
-      icat (i);
-      if (i > 9)
-       OB_PUTC ('_');
+      build_underscore_int (i);
       numeric_output_need_bar = 0;
     }
   build_overload_nested_name (decl);
 }
 
+/* Output the mangled representation for TYPE.  If EXTRA_GCODE is
+   non-zero, mangled names for structure/union types are intentionally
+   mangled differently from the method described in the ARM.  */
+
+void 
+build_mangled_name_for_type_with_Gcode (type, extra_Gcode)
+     tree type;
+     int extra_Gcode;
+{
+  if (TYPE_PTRMEMFUNC_P (type))
+    type = TYPE_PTRMEMFUNC_FN_TYPE (type);
+  type = CANONICAL_TYPE_VARIANT (type);
+  process_modifiers (type);
+  process_overload_item (type, extra_Gcode);
+}
+
+/* Like build_mangled_name_for_type_with_Gcode, but never outputs the
+   `G'.  */
+
+void
+build_mangled_name_for_type (type)
+     tree type;
+{
+  build_mangled_name_for_type_with_Gcode (type, 0);
+}
+
 /* Given a list of parameters in PARMTYPES, create an unambiguous
    overload string. Should distinguish any type that C (or C++) can
    distinguish. I.e., pointers to functions are treated correctly.
@@ -951,103 +1044,116 @@ build_overload_name (parmtypes, begin, end)
   return ret ;
 }
 
+/* Output the mangled representation for PARMTYPES.  If PARMTYPES is a
+   TREE_LIST, then it is a list of parameter types.  Otherwise,
+   PARMTYPES must be a single type.  */
+
 static char *
 build_mangled_name (parmtypes, begin, end)
      tree parmtypes;
      int begin, end;
 {
-  tree parmtype;
-
   if (begin) 
     OB_INIT ();
-  numeric_output_need_bar = 0;
 
-  if (TREE_CODE (parmtypes) != TREE_LIST)  /* just one item */
+  if (TREE_CODE (parmtypes) != TREE_LIST)  
+    /* There is only one type.  */
+    build_mangled_name_for_type (parmtypes);
+  else  
     {
-      if (TYPE_PTRMEMFUNC_P (parmtypes))
-        parmtypes = TYPE_PTRMEMFUNC_FN_TYPE (parmtypes);
-      process_modifiers (parmtypes);
-      process_overload_item (parmtypes, FALSE);
-    }
-  else  {
-    for ( ; parmtypes!=NULL; parmtypes = TREE_CHAIN (parmtypes))
-      {
-        parmtype = TREE_VALUE (parmtypes);
-        if (flag_do_squangling)       /* squangling style repeats */
-          {
-            if (parmtype == lasttype) 
-              {
-                nrepeats++;
-                continue;
-              }
-            else 
-              if (nrepeats != 0) 
-                {
-                  issue_nrepeats (lasttype);
-                }
-            lasttype = parmtype;
-          }
-        else 
-          if (!nofold && typevec)
-            {
-              /* Every argument gets counted.  */
-              typevec[maxtype++] = parmtype;
+      /* There are several types in a parameter list.  */
+      int nrepeats = 0;
+      int old_style_repeats = !flag_do_squangling && !nofold && typevec;
+      tree last_type = NULL_TREE;
 
-              if (TREE_USED (parmtype) && parmtype == typevec[maxtype-2])
-                {
-                  Nrepeats++;
-                  continue;
-                }
+      for (; parmtypes && parmtypes != void_list_node;
+          parmtypes = TREE_CHAIN (parmtypes))
+       {
+         tree parmtype = CANONICAL_TYPE_VARIANT (TREE_VALUE (parmtypes));
 
-              if (Nrepeats)
-                flush_repeats (typevec[maxtype-2]);
+         if (old_style_repeats)
+           {
+             /* Every argument gets counted.  */
+             my_friendly_assert (maxtype < typevec_size, 387);
+             typevec[maxtype++] = parmtype;
+           }
 
-              if (TREE_USED (parmtype))
-                {
+         if (parmtype == last_type)
+           {
+             if (flag_do_squangling 
+                 || (old_style_repeats && TREE_USED (parmtype)
+                     && !TYPE_FOR_JAVA (parmtype)))
+               {
+                 /* The next type is the same as this one.  Keep
+                    track of the repetition, and output the repeat
+                    count later.  */
+                 nrepeats++;
+                 continue;
+               }
+           }
+         else if (nrepeats != 0)
+           {
+             /* Indicate how many times the previous parameter was
+                repeated.  */
+             if (old_style_repeats)
+               flush_repeats (nrepeats, last_type);
+             else
+               issue_nrepeats (nrepeats, last_type);
+             nrepeats = 0;
+           }
+         
+         last_type = parmtype;
+
+         if (old_style_repeats)
+           {
+             if (nrepeats)
+               {
+                 flush_repeats (nrepeats, last_type);
+                 nrepeats = 0;
+               }
+
+             if (TREE_USED (parmtype))
+               {
 #if 0
-                  /* We can turn this on at some point when we want
-                     improved symbol mangling.  */
-                  Nrepeats++;
+                 /* We can turn this on at some point when we want
+                    improved symbol mangling.  */
+                 nrepeats++;
 #else
-                  /* This is bug compatible with 2.7.x  */
-                  flush_repeats (parmtype);
+                 /* This is bug compatible with 2.7.x  */
+                 flush_repeats (nrepeats, parmtype);
 #endif
-                  continue;
-                }
-
-              /* Only cache types which take more than one character.  */
-              if (parmtype != TYPE_MAIN_VARIANT (parmtype)
-                  || (TREE_CODE (parmtype) != INTEGER_TYPE
-                      && TREE_CODE (parmtype) != REAL_TYPE))
-                TREE_USED (parmtype) = 1;
-            }
-        if (TYPE_PTRMEMFUNC_P (parmtype))
-          parmtype = TYPE_PTRMEMFUNC_FN_TYPE (parmtype);
-        process_modifiers (parmtype);
-        if (TREE_CODE(parmtype)==VOID_TYPE) 
-         {
-#if 0
-             extern tree void_list_node;
+                 nrepeats = 0;
+                 continue;
+               }
+             
+             /* Only cache types which take more than one character.  */
+             if ((parmtype != TYPE_MAIN_VARIANT (parmtype)
+                  || (TREE_CODE (parmtype) != INTEGER_TYPE
+                      && TREE_CODE (parmtype) != REAL_TYPE))
+                 && ! TYPE_FOR_JAVA (parmtype))
+               TREE_USED (parmtype) = 1;
+           }
+
+         /* Output the PARMTYPE.  */
+         build_mangled_name_for_type_with_Gcode (parmtype, 1);
+       }
+
+      /* Output the repeat count for the last parameter, if
+        necessary.  */
+      if (nrepeats != 0)
+       {
+         if (old_style_repeats)
+           flush_repeats (nrepeats, last_type);
+         else
+           issue_nrepeats (nrepeats, last_type);
+         nrepeats = 0;
+       }
+
+      if (!parmtypes)
+       /* The parameter list ends in an ellipsis.  */
+       OB_PUTC ('e');
+    }
 
-             /* See if anybody is wasting memory.  */
-             my_friendly_assert (parmtypes == void_list_node, 247);
-#endif
-             /* This is the end of a parameter list.  */
-             if (end) 
-                OB_FINISH ();
-             return (char *)obstack_base (&scratch_obstack);
-         }
-        process_overload_item (parmtype, TRUE);
-      }
-      if (flag_do_squangling && nrepeats != 0)
-        issue_nrepeats (lasttype);
-      else 
-        if (Nrepeats && typevec)
-          flush_repeats (typevec[maxtype-1]);
-
-      /* To get here, parms must end with `...'.  */
-      OB_PUTC ('e');
-  }
   if (end) 
     OB_FINISH ();
   return (char *)obstack_base (&scratch_obstack);
@@ -1058,57 +1164,57 @@ void
 process_modifiers (parmtype) 
      tree parmtype;
 {
-
-
   if (TREE_READONLY (parmtype))
     OB_PUTC ('C');
-  if (TREE_CODE (parmtype) == INTEGER_TYPE && 
-             TYPE_MAIN_VARIANT (parmtype) == 
-                            unsigned_type (TYPE_MAIN_VARIANT (parmtype)))
+  if (TREE_CODE (parmtype) == INTEGER_TYPE
+      && (TYPE_MAIN_VARIANT (parmtype)
+         == unsigned_type (TYPE_MAIN_VARIANT (parmtype)))
+      && ! TYPE_FOR_JAVA (parmtype))
     OB_PUTC ('U');
   if (TYPE_VOLATILE (parmtype))
     OB_PUTC ('V');
 }
 
-/* Check to see if a tree node has been entered into the Bcode typelist 
-   if not, add it. Otherwise emit the code and return TRUE */
-static int 
-check_btype (node) 
-     tree node;
+/* Check to see if TYPE has been entered into the Bcode typelist.  If
+   so, return 1 and emit a backreference to TYPE.  Otherwise, add TYPE
+   to the list of back-referenceable types and return 0.  */
+
+int 
+check_btype (type) 
+     tree type;
 {
   int x;
 
   if (btypelist == NULL)
     return 0;
 
-  switch (TREE_CODE (node)) 
-    {
-    case INTEGER_TYPE:
-    case REAL_TYPE:
-    case VOID_TYPE:
-    case BOOLEAN_TYPE:
-      return 0;         /* don't compress single char basic types */
-    }
+  if (!is_back_referenceable_type (type))
+    return 0;
+
+  /* We assume that our caller has put out any necessary
+     qualifiers.  */
+  type = TYPE_MAIN_VARIANT (type);
 
-  node = TYPE_MAIN_VARIANT (node);
   for (x = 0; x < maxbtype; x++) 
-    {
-      if (node == btypelist[x]) 
-        {
-          OB_PUTC ('B');
-          icat (x);
-          if (x > 9)
-            OB_PUTC ('_');
-          return 1 ;
-        }
-    }
-  /* didn't find it, so add it here */
+    if (type == btypelist[x]) 
+      {
+       OB_PUTC ('B');
+       icat (x);
+       if (x > 9)
+         OB_PUTC ('_');
+       return 1 ;
+      }
+
   if (maxbsize <= maxbtype) 
     {
+      /* Enlarge the table.  */
       maxbsize = maxbsize * 3 / 2;
-      btypelist = (tree *)xrealloc (sizeof (tree) * maxbsize); 
+      btypelist = (tree *)xrealloc (btypelist, sizeof (tree) * maxbsize); 
     }
-  btypelist[maxbtype++] = node;
+  
+  /* Register the TYPE.  */
+  btypelist[maxbtype++] = type;
+
   return 0;
 }
 
@@ -1118,6 +1224,7 @@ process_overload_item (parmtype, extra_Gcode)
   tree parmtype;
   int extra_Gcode;
 {
+  numeric_output_need_bar = 0;
 
   /* These tree types are considered modifiers for B code squangling , */
   /* and therefore should not get entries in the Btypelist             */
@@ -1154,82 +1261,65 @@ process_overload_item (parmtype, extra_Gcode)
     case POINTER_TYPE:
       OB_PUTC ('P');
     more:
-      build_mangled_name (TREE_TYPE (parmtype), 0, 0);
+      build_mangled_name_for_type (TREE_TYPE (parmtype));
       return;
       break;
+
+    default:
+      break;
     }
   
-  /* check if type is already in the typelist. If not, add it now */
-
-  if (flag_do_squangling && btypelist != NULL) {
-    if (check_btype (parmtype))    /* emits the code if it finds it */
-      return;
-  }
+  if (flag_do_squangling && check_btype (parmtype)) 
+    /* If PARMTYPE is already in the list of back-referenceable types,
+       then check_btype will output the appropriate reference, and
+       there's nothing more to do.  */
+    return;
 
   switch (TREE_CODE (parmtype))
     {
     case OFFSET_TYPE:
       OB_PUTC ('O');
-      build_mangled_name (TYPE_OFFSET_BASETYPE (parmtype), 0, 0);
+      build_mangled_name_for_type (TYPE_OFFSET_BASETYPE (parmtype));
       OB_PUTC ('_');
-      build_mangled_name (TREE_TYPE (parmtype), 0, 0);
+      build_mangled_name_for_type (TREE_TYPE (parmtype));
       break;
 
     case FUNCTION_TYPE:
     case METHOD_TYPE:
       {
-        tree firstarg = TYPE_ARG_TYPES (parmtype);
-        /* Otherwise have to implement reentrant typevecs,
-           unmark and remark types, etc.  */
-        int old_nofold = nofold;
-        if (!flag_do_squangling) {
-          nofold = 1;
-          if (Nrepeats)
-            flush_repeats (typevec[maxtype-1]);
-        }
-        else 
-          if (nrepeats != 0)
-            issue_nrepeats (lasttype);
+        tree parms = TYPE_ARG_TYPES (parmtype);
 
-        /* @@ It may be possible to pass a function type in
-           which is not preceded by a 'P'.  */
-        if (TREE_CODE (parmtype) == FUNCTION_TYPE)
-          {
-            OB_PUTC ('F');
-            if (firstarg == NULL_TREE)
-              OB_PUTC ('e');
-            else if (firstarg == void_list_node)
-              OB_PUTC ('v');
-            else
-              build_mangled_name (firstarg, 0, 0);
-          }
-        else
-          {
-            int constp = TYPE_READONLY (TREE_TYPE (TREE_VALUE (firstarg)));
-            int volatilep = TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (firstarg)));
+       /* Rather than implementing a reentrant TYPEVEC, we turn off
+          repeat codes here, unless we're squangling.  Squangling
+          doesn't make use of the TYPEVEC, so there's no reentrancy
+          problem.  */
+       int old_nofold = nofold;
+       if (!flag_do_squangling)
+         nofold = 1;
+
+       if (TREE_CODE (parmtype) == METHOD_TYPE)
+         {
+           /* Mark this as a method.  */
             OB_PUTC ('M');
-            firstarg = TREE_CHAIN (firstarg);
-
-            build_mangled_name (TYPE_METHOD_BASETYPE (parmtype), 0, 0);
-            if (constp)
-              OB_PUTC ('C');
-            if (volatilep)
-              OB_PUTC ('V');
-
-            /* For cfront 2.0 compatibility.  */
-            OB_PUTC ('F');
-
-            if (firstarg == NULL_TREE)
-              OB_PUTC ('e');
-            else if (firstarg == void_list_node)
-              OB_PUTC ('v');
-            else
-              build_mangled_name (firstarg, 0, 0);
-          }
+           /* Output the class of which this method is a member.  */
+            build_mangled_name_for_type (TYPE_METHOD_BASETYPE (parmtype));
+           /* Output any qualifiers for the `this' parameter.  */
+           process_modifiers (TREE_TYPE (TREE_VALUE (parms)));
+         }
 
-        /* Separate args from return type.  */
+       /* Output the parameter types.  */
+       OB_PUTC ('F');
+       if (parms == NULL_TREE)
+         OB_PUTC ('e');
+       else if (parms == void_list_node)
+         OB_PUTC ('v');
+       else
+         build_mangled_name (parms, 0, 0);
+
+        /* Output the return type.  */
         OB_PUTC ('_');
-        build_mangled_name (TREE_TYPE (parmtype), 0, 0);
+        build_mangled_name_for_type (TREE_TYPE (parmtype));
+
         nofold = old_nofold;
         break;
       }
@@ -1237,13 +1327,15 @@ process_overload_item (parmtype, extra_Gcode)
     case INTEGER_TYPE:
       parmtype = TYPE_MAIN_VARIANT (parmtype);
       if (parmtype == integer_type_node
-          || parmtype == unsigned_type_node)
+          || parmtype == unsigned_type_node
+         || parmtype == java_int_type_node)
         OB_PUTC ('i');
       else if (parmtype == long_integer_type_node
                || parmtype == long_unsigned_type_node)
         OB_PUTC ('l');
       else if (parmtype == short_integer_type_node
-               || parmtype == short_unsigned_type_node)
+               || parmtype == short_unsigned_type_node
+              || parmtype == java_short_type_node)
         OB_PUTC ('s');
       else if (parmtype == signed_char_type_node)
         {
@@ -1251,12 +1343,15 @@ process_overload_item (parmtype, extra_Gcode)
           OB_PUTC ('c');
         }
       else if (parmtype == char_type_node
-               || parmtype == unsigned_char_type_node)
+               || parmtype == unsigned_char_type_node
+              || parmtype == java_byte_type_node)
         OB_PUTC ('c');
-      else if (parmtype == wchar_type_node)
+      else if (parmtype == wchar_type_node
+              || parmtype == java_char_type_node)
         OB_PUTC ('w');
       else if (parmtype == long_long_integer_type_node
-          || parmtype == long_long_unsigned_type_node)
+              || parmtype == long_long_unsigned_type_node
+              || parmtype == java_long_type_node)
         OB_PUTC ('x');
 #if 0
       /* it would seem there is no way to enter these in source code,
@@ -1265,6 +1360,8 @@ process_overload_item (parmtype, extra_Gcode)
           || parmtype == long_long_long_unsigned_type_node)
         OB_PUTC ('q');
 #endif
+      else if (parmtype == java_boolean_type_node)
+       OB_PUTC ('b');
       else
         my_friendly_abort (73);
       break;
@@ -1277,16 +1374,18 @@ process_overload_item (parmtype, extra_Gcode)
       parmtype = TYPE_MAIN_VARIANT (parmtype);
       if (parmtype == long_double_type_node)
         OB_PUTC ('r');
-      else if (parmtype == double_type_node)
+      else if (parmtype == double_type_node
+              || parmtype == java_double_type_node)
         OB_PUTC ('d');
-      else if (parmtype == float_type_node)
+      else if (parmtype == float_type_node
+              || parmtype == java_float_type_node)
         OB_PUTC ('f');
       else my_friendly_abort (74);
       break;
 
     case COMPLEX_TYPE:
       OB_PUTC ('J');
-      build_mangled_name (TREE_TYPE (parmtype), 0, 0);
+      build_mangled_name_for_type (TREE_TYPE (parmtype));
       break;
 
     case VOID_TYPE:
@@ -1428,41 +1527,20 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs,
      and figure out its name without any extra encoding.  */
 
   OB_PUTC2 ('_', '_');
-  if (for_method)
-    {
-#if 0
-      /* We can get away without doing this.  */
-      OB_PUTC ('M');
-#endif
-      if (tparms != NULL_TREE)
-       OB_PUTC ('H');
-      {
-       tree this_type = TREE_VALUE (parms);
-
-       if (TREE_CODE (this_type) == RECORD_TYPE)  /* a signature pointer */
-         parms = temp_tree_cons (NULL_TREE, SIGNATURE_TYPE (this_type),
-                                 TREE_CHAIN (parms));
-       else
-         parms = temp_tree_cons (NULL_TREE, TREE_TYPE (this_type),
-                                 TREE_CHAIN (parms));
-      }
-    }
-  else if (tparms)
-    OB_PUTC ('H');
-  /* XXX this works only if we call this in the same namespace
-     as the declaration. Unfortunately, we don't have the _DECL,
-     only its name */
-  else if (current_namespace == global_namespace)
-    OB_PUTC ('F');
 
   if (tparms)
     {
+      OB_PUTC ('H');
       build_template_parm_names (tparms, targs);
       OB_PUTC ('_');
     }
-
-  /* qualify with namespace */
-  if (!for_method && current_namespace != global_namespace)
+  else if (!for_method && current_namespace == global_namespace)
+    /* XXX this works only if we call this in the same namespace
+       as the declaration. Unfortunately, we don't have the _DECL,
+       only its name */
+    OB_PUTC ('F');
+  else if (!for_method)
+    /* qualify with namespace */
     build_qualified_name (current_namespace);
 
   if (parms == NULL_TREE)
@@ -1474,18 +1552,36 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs,
       if (!flag_do_squangling)    /* Allocate typevec array. */
         {
           maxtype = 0;
-          Nrepeats = 0;
-          typevec = (tree *)alloca (list_length (parms) * sizeof (tree));
+         typevec_size = list_length (parms);
+         if (!for_method && current_namespace != global_namespace)
+           /* the namespace of a global function needs one slot */
+           typevec_size++;
+          typevec = (tree *)alloca (typevec_size * sizeof (tree));
         }
       nofold = 0;
+
       if (for_method)
        {
-         build_mangled_name (TREE_VALUE (parms), 0, 0);
+         tree this_type = TREE_VALUE (parms);
 
-          if (!flag_do_squangling) {
-            typevec[maxtype++] = TREE_VALUE (parms);
-            TREE_USED (TREE_VALUE (parms)) = 1;
-          }
+         if (TREE_CODE (this_type) == RECORD_TYPE)  /* a signature pointer */
+           this_type = SIGNATURE_TYPE (this_type);
+         else
+           this_type = TREE_TYPE (this_type);
+
+         build_mangled_name_for_type (this_type);
+
+          if (!flag_do_squangling) 
+           {
+             my_friendly_assert (maxtype < typevec_size, 387);
+             typevec[maxtype++] = this_type;
+             TREE_USED (this_type) = 1;
+
+             /* By setting up PARMS in this way, the loop below will
+                automatically clear TREE_USED on THIS_TYPE.  */
+             parms = temp_tree_cons (NULL_TREE, this_type,
+                                     TREE_CHAIN (parms));
+           }
 
          if (TREE_CHAIN (parms))
            build_mangled_name (TREE_CHAIN (parms), 0, 0);
@@ -1498,7 +1594,10 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs,
             will count as type */
          if (current_namespace != global_namespace
              && !flag_do_squangling)
-           typevec[maxtype++] = current_namespace;
+           {
+             my_friendly_assert (maxtype < typevec_size, 387);
+             typevec[maxtype++] = current_namespace;
+           }
          build_mangled_name (parms, 0, 0);
        }
 
@@ -1508,7 +1607,11 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs,
           typevec = NULL;
           while (t)
             {
-              TREE_USED (TREE_VALUE (t)) = 0;
+              tree temp = TREE_VALUE (t);
+              TREE_USED (temp) = 0;
+              /* clear out the type variant in case we used it */
+              temp = CANONICAL_TYPE_VARIANT (temp);
+              TREE_USED (temp) = 0;
               t = TREE_CHAIN (t);
             }
         }
@@ -1518,7 +1621,7 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs,
     {
       /* Add the return type. */
       OB_PUTC ('_');
-      build_mangled_name (ret_type, 0, 0);
+      build_mangled_name_for_type (ret_type);
     }
 
   OB_FINISH ();
@@ -1554,17 +1657,31 @@ build_decl_overload (dname, parms, for_method)
 /* Like build_decl_overload, but for template functions. */
 
 tree
-build_template_decl_overload (dname, parms, ret_type, tparms, targs,
+build_template_decl_overload (decl, parms, ret_type, tparms, targs,
                              for_method) 
-     tree dname;
+     tree decl;
      tree parms;
      tree ret_type;
      tree tparms;
      tree targs;
      int for_method;
 {
-  return build_decl_overload_real (dname, parms, ret_type, tparms, targs,
-                                  for_method); 
+  tree res, saved_ctx;
+
+  /* If the template is in a namespace, we need to put that into the
+     mangled name. Unfortunately, build_decl_overload_real does not
+     get the decl to mangle, so it relies on the current
+     namespace. Therefore, we set that here temporarily. */
+
+  my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 980702);
+  saved_ctx = current_namespace;
+  current_namespace = CP_DECL_CONTEXT (decl);  
+
+  res = build_decl_overload_real (DECL_NAME (decl), parms, ret_type,
+                                 tparms, targs, for_method); 
+
+  current_namespace = saved_ctx;
+  return res;
 }
 
 
@@ -1616,6 +1733,16 @@ get_id_2 (name, name2)
   OB_FINISH ();
   return get_identifier (obstack_base (&scratch_obstack));
 }
+
+/* Returns a DECL_ASSEMBLER_NAME for the destructor of type TYPE.  */
+
+tree
+build_destructor_name (type)
+     tree type;
+{
+  return build_overload_with_type (get_identifier (DESTRUCTOR_DECL_PREFIX),
+                                  type);
+}
 \f
 /* Given a tree_code CODE, and some arguments (at least one),
    attempt to use an overloaded operator on the arguments.
@@ -1687,6 +1814,9 @@ hack_identifier (value, name)
 
              fndecl = TREE_VALUE (fields);
              my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 251);
+             /* I could not trigger this code. MvL */
+             my_friendly_abort (980325);
+#ifdef DEAD
              if (DECL_CHAIN (fndecl) == NULL_TREE)
                {
                  warning ("methods cannot be converted to function pointers");
@@ -1698,6 +1828,7 @@ hack_identifier (value, name)
                         IDENTIFIER_POINTER (name));
                  return error_mark_node;
                }
+#endif
            }
        }
       if (flag_labels_ok && IDENTIFIER_LABEL_VALUE (name))
@@ -1738,6 +1869,9 @@ hack_identifier (value, name)
        }
 #endif
     }
+  else if (TREE_CODE (value) == OVERLOAD)
+    /* not really overloaded function */
+    mark_used (OVL_FUNCTION (value));
   else if (TREE_CODE (value) == TREE_LIST)
     {
       /* Ambiguous reference to base members, possibly other cases?.  */
@@ -1748,6 +1882,16 @@ hack_identifier (value, name)
          t = TREE_CHAIN (t);
        }
     }
+  else if (TREE_CODE (value) == NAMESPACE_DECL)
+    {
+      cp_error ("use of namespace `%D' as expression", value);
+      return error_mark_node;
+    }
+  else if (DECL_CLASS_TEMPLATE_P (value))
+    {
+      cp_error ("use of class template `%T' as expression", value);
+      return error_mark_node;
+    }
   else
     mark_used (value);
 
@@ -1813,40 +1957,41 @@ hack_identifier (value, name)
 }
 
 \f
-static char *
-thunk_printable_name (decl)
-     tree decl;
-{
-  return "<thunk function>";
-}
-
 tree
 make_thunk (function, delta)
      tree function;
      int delta;
 {
-  char *buffer;
   tree thunk_id;
   tree thunk;
-  char *func_name;
   tree func_decl;
+
   if (TREE_CODE (function) != ADDR_EXPR)
     abort ();
   func_decl = TREE_OPERAND (function, 0);
   if (TREE_CODE (func_decl) != FUNCTION_DECL)
     abort ();
-  func_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (func_decl));
-  buffer = (char *)alloca (strlen (func_name) + 32);
-  if (delta<=0)
-    sprintf (buffer, "__thunk_%d_%s", -delta, func_name);
+
+  OB_INIT ();
+  OB_PUTS ("__thunk_");
+  if (delta > 0)
+    {
+      OB_PUTC ('n');
+      icat (delta);
+    }
   else
-    sprintf (buffer, "__thunk_n%d_%s", delta, func_name);
-  thunk_id = get_identifier (buffer);
+    icat (-delta);
+  OB_PUTC ('_');
+  OB_PUTID (DECL_ASSEMBLER_NAME (func_decl));
+  OB_FINISH ();
+  thunk_id = get_identifier (obstack_base (&scratch_obstack));
+
   thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id);
   if (thunk && TREE_CODE (thunk) != THUNK_DECL)
     {
       cp_error ("implementation-reserved name `%D' used", thunk_id);
-      IDENTIFIER_GLOBAL_VALUE (thunk_id) = thunk = NULL_TREE;
+      thunk = NULL_TREE;
+      SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk);
     }
   if (thunk == NULL_TREE)
     {
@@ -1899,6 +2044,7 @@ emit_thunk (thunk_fndecl)
       = build_decl (RESULT_DECL, 0, integer_type_node);
     fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
     init_function_start (thunk_fndecl, input_filename, lineno);
+    current_function_is_thunk = 1;
     assemble_start_function (thunk_fndecl, fnname);
     ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
     assemble_end_function (thunk_fndecl, fnname);
@@ -1997,7 +2143,11 @@ do_build_copy_constructor (fndecl)
     parm = TREE_CHAIN (parm);
   parm = convert_from_reference (parm);
 
-  if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
+  if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)
+      && is_empty_class (current_class_type))
+    /* Don't copy the padding byte; it might not have been allocated
+       if *this is a base subobject.  */;
+  else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
     {
       t = build (INIT_EXPR, void_type_node, current_class_ref, parm);
       TREE_SIDE_EFFECTS (t) = 1;
@@ -2067,8 +2217,7 @@ do_build_copy_constructor (fndecl)
                continue;
            }
          else if ((t = TREE_TYPE (field)) != NULL_TREE
-                  && TREE_CODE (t) == UNION_TYPE
-                  && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
+                  && ANON_UNION_TYPE_P (t)
                   && TYPE_FIELDS (t) != NULL_TREE)
            {
              do
@@ -2077,8 +2226,7 @@ do_build_copy_constructor (fndecl)
                  field = largest_union_member (t);
                }
              while ((t = TREE_TYPE (field)) != NULL_TREE
-                    && TREE_CODE (t) == UNION_TYPE
-                    && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
+                    && ANON_UNION_TYPE_P (t)
                     && TYPE_FIELDS (t) != NULL_TREE);
            }
          else
@@ -2109,7 +2257,11 @@ do_build_assign_ref (fndecl)
 
   parm = convert_from_reference (parm);
 
-  if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type))
+  if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)
+      && is_empty_class (current_class_type))
+    /* Don't copy the padding byte; it might not have been allocated
+       if *this is a base subobject.  */;
+  else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type))
     {
       tree t = build (MODIFY_EXPR, void_type_node, current_class_ref, parm);
       TREE_SIDE_EFFECTS (t) = 1;
@@ -2173,8 +2325,7 @@ do_build_assign_ref (fndecl)
                continue;
            }
          else if ((t = TREE_TYPE (field)) != NULL_TREE
-                  && TREE_CODE (t) == UNION_TYPE
-                  && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
+                  && ANON_UNION_TYPE_P (t)
                   && TYPE_FIELDS (t) != NULL_TREE)
            {
              do
@@ -2184,8 +2335,7 @@ do_build_assign_ref (fndecl)
                  field = largest_union_member (t);
                }
              while ((t = TREE_TYPE (field)) != NULL_TREE
-                    && TREE_CODE (t) == UNION_TYPE
-                    && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
+                    && ANON_UNION_TYPE_P (t)
                     && TYPE_FIELDS (t) != NULL_TREE);
            }
          else