OSDN Git Service

* error.c (dump_expr): Add 0x to printed hex numbers to make
[pf3gnuchains/gcc-fork.git] / gcc / cp / error.c
index ae6b511..f836ecc 100644 (file)
 /* Call-backs for C++ error reporting.
    This code is non-reentrant.
-   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002
    Free Software Foundation, Inc.
-   This file is part of GNU CC.
+   This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
+along with GCC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "tree.h"
 #include "cp-tree.h"
-#include "obstack.h"
+#include "real.h"
 #include "toplev.h"
-
-typedef const char *cp_printer ();
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-/* Obstack where we build text strings for overloading, etc.  */
-static struct obstack scratch_obstack;
-static char *scratch_firstobj;
-
-# define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0)
-# define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C)))
-# define OB_PUTC2(C1,C2)       \
-  (obstack_1grow (&scratch_obstack, (C1)), obstack_1grow (&scratch_obstack, (C2)))
-# define OB_PUTS(S) (obstack_grow (&scratch_obstack, (S), sizeof (S) - 1))
-# define OB_PUTID(ID)  \
-  (obstack_grow (&scratch_obstack, IDENTIFIER_POINTER (ID),    \
-                IDENTIFIER_LENGTH (ID)))
-# define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S)))
-# define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0'))
-# define OB_PUTI(CST) do { sprintf (digit_buffer, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)(CST)); \
-                          OB_PUTCP (digit_buffer); } while (0)
-
-# define OB_END_TEMPLATE_ID()                                              \
-  (((obstack_next_free (&scratch_obstack) != obstack_base (&scratch_obstack) \
-    && obstack_next_free (&scratch_obstack)[-1] == '>')                            \
-   ? OB_PUTC (' ') : (void)0), OB_PUTC ('>'))
-
-# define NEXT_CODE(t) (TREE_CODE (TREE_TYPE (t)))
+#include "flags.h"
+#include "diagnostic.h"
+#include "langhooks-def.h"
 
 enum pad { none, before, after };
 
-static const char *args_to_string              PARAMS ((tree, int));
-static const char *assop_to_string             PARAMS ((enum tree_code, int));
-static const char *code_to_string              PARAMS ((enum tree_code, int));
-static const char *cv_to_string                        PARAMS ((tree, int));
-static const char *decl_to_string              PARAMS ((tree, int));
-static const char *expr_to_string              PARAMS ((tree, int));
-static const char *fndecl_to_string            PARAMS ((tree, int));
-static const char *language_to_string          PARAMS ((enum languages, int));
-static const char *op_to_string                        PARAMS ((enum tree_code, int));
-static const char *parm_to_string              PARAMS ((int, int));
-static const char *type_to_string              PARAMS ((tree, int));
-
-static void dump_type PARAMS ((tree, enum tree_string_flags));
-static void dump_simple_decl PARAMS ((tree, tree, enum tree_string_flags));
-static void dump_decl PARAMS ((tree, enum tree_string_flags));
-static void dump_template_decl PARAMS ((tree, enum tree_string_flags));
-static void dump_function_decl PARAMS ((tree, enum tree_string_flags));
-static void dump_expr PARAMS ((tree, enum tree_string_flags));
-static void dump_unary_op PARAMS ((const char *, tree, enum tree_string_flags));
-static void dump_binary_op PARAMS ((const char *, tree, enum tree_string_flags));
-static void dump_aggr_type PARAMS ((tree, enum tree_string_flags));
-static enum pad dump_type_prefix PARAMS ((tree, enum tree_string_flags));
-static void dump_type_suffix PARAMS ((tree, enum tree_string_flags));
-static void dump_function_name PARAMS ((tree, enum tree_string_flags));
-static void dump_expr_list PARAMS ((tree, enum tree_string_flags));
-static void dump_global_iord PARAMS ((tree));
-static enum pad dump_qualifiers PARAMS ((tree, enum pad));
-static void dump_char PARAMS ((int));
-static void dump_parameters PARAMS ((tree, enum tree_string_flags));
-static void dump_exception_spec PARAMS ((tree, enum tree_string_flags));
-static const char *aggr_variety PARAMS ((tree));
-static tree ident_fndecl PARAMS ((tree));
-static void dump_template_argument PARAMS ((tree, enum tree_string_flags));
-static void dump_template_argument_list PARAMS ((tree, enum tree_string_flags));
-static void dump_template_parameter PARAMS ((tree, enum tree_string_flags));
-static void dump_template_bindings PARAMS ((tree, tree));
-static void dump_scope PARAMS ((tree, enum tree_string_flags));
-static void dump_template_parms PARAMS ((tree, int, enum tree_string_flags));
-
-#define A args_to_string
-#define C code_to_string
-#define D decl_to_string
-#define E expr_to_string
-#define F fndecl_to_string
-#define L language_to_string
-#define O op_to_string
-#define P parm_to_string
-#define Q assop_to_string
-#define T type_to_string
-#define V cv_to_string
-
-#define o (cp_printer *) 0
-cp_printer * cp_printers[256] =
-{
-/*0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F */
-  o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x00 */
-  o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x10 */
-  o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x20 */
-  o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x30 */
-  o, A, o, C, D, E, F, o, o, o, o, o, L, o, o, O, /* 0x40 */
-  P, Q, o, o, T, o, V, o, o, o, o, o, o, o, o, o, /* 0x50 */
-  o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x60 */
-  o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x70 */
-};
-#undef C
-#undef D
-#undef E
-#undef F
-#undef L
-#undef O
-#undef P
-#undef Q
-#undef T
-#undef V
-#undef o
+#define sorry_for_unsupported_tree(T)                                      \
+   sorry ("`%s' not supported by %s", tree_code_name[(int) TREE_CODE (T)], \
+             __FUNCTION__)
+
+#define print_scope_operator(BUFFER)  output_add_string ((BUFFER), "::")
+#define print_left_paren(BUFFER)      output_add_character ((BUFFER), '(')
+#define print_right_paren(BUFFER)     output_add_character ((BUFFER), ')')
+#define print_left_bracket(BUFFER)    output_add_character ((BUFFER), '[')
+#define print_right_bracket(BUFFER)   output_add_character ((BUFFER), ']')
+#define print_template_argument_list_start(BUFFER) \
+   print_non_consecutive_character ((BUFFER), '<')
+#define print_template_argument_list_end(BUFFER)  \
+   print_non_consecutive_character ((BUFFER), '>')
+#define print_tree_identifier(BUFFER, TID) \
+   output_add_string ((BUFFER), IDENTIFIER_POINTER (TID))
+#define print_identifier(BUFFER, ID) output_add_string ((BUFFER), (ID))
+#define separate_with_comma(BUFFER) output_add_string ((BUFFER), ", ")
+
+/* The global buffer where we dump everything.  It is there only for
+   transitional purpose.  It is expected, in the near future, to be
+   completely removed.  */
+static output_buffer scratch_buffer_rec;
+static output_buffer *scratch_buffer = &scratch_buffer_rec;
+
+# define NEXT_CODE(T) (TREE_CODE (TREE_TYPE (T)))
+
+#define reinit_global_formatting_buffer() \
+   output_clear_message_text (scratch_buffer)
+
+static const char *args_to_string (tree, int);
+static const char *assop_to_string (enum tree_code, int);
+static const char *code_to_string (enum tree_code, int);
+static const char *cv_to_string (tree, int);
+static const char *decl_to_string (tree, int);
+static const char *expr_to_string (tree, int);
+static const char *fndecl_to_string (tree, int);
+static const char *op_to_string        (enum tree_code, int);
+static const char *parm_to_string (int, int);
+static const char *type_to_string (tree, int);
+
+static void dump_type (tree, int);
+static void dump_typename (tree, int);
+static void dump_simple_decl (tree, tree, int);
+static void dump_decl (tree, int);
+static void dump_template_decl (tree, int);
+static void dump_function_decl (tree, int);
+static void dump_expr (tree, int);
+static void dump_unary_op (const char *, tree, int);
+static void dump_binary_op (const char *, tree, int);
+static void dump_aggr_type (tree, int);
+static enum pad dump_type_prefix (tree, int);
+static void dump_type_suffix (tree, int);
+static void dump_function_name (tree, int);
+static void dump_expr_list (tree, int);
+static void dump_global_iord (tree);
+static enum pad dump_qualifiers (tree, enum pad);
+static void dump_char (int);
+static void dump_parameters (tree, int);
+static void dump_exception_spec (tree, int);
+static const char *class_key_or_enum (tree);
+static void dump_template_argument (tree, int);
+static void dump_template_argument_list (tree, int);
+static void dump_template_parameter (tree, int);
+static void dump_template_bindings (tree, tree);
+static void dump_scope (tree, int);
+static void dump_template_parms (tree, int, int);
+
+static const char *function_category (tree);
+static void maybe_print_instantiation_context (diagnostic_context *);
+static void print_instantiation_full_context (diagnostic_context *);
+static void print_instantiation_partial_context (diagnostic_context *,
+                                                 tree, const char *, int);
+static void cp_diagnostic_starter (diagnostic_context *, diagnostic_info *);
+static void cp_diagnostic_finalizer (diagnostic_context *, diagnostic_info *);
+static void cp_print_error_function (diagnostic_context *, diagnostic_info *);
+
+static bool cp_printer (output_buffer *, text_info *);
+static void print_non_consecutive_character (output_buffer *, int);
+static void print_integer (output_buffer *, HOST_WIDE_INT);
+static tree locate_error (const char *, va_list);
 
 void
-init_error ()
+init_error (void)
 {
-  gcc_obstack_init (&scratch_obstack);
-  scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0);
+  diagnostic_starter (global_dc) = cp_diagnostic_starter;
+  diagnostic_finalizer (global_dc) = cp_diagnostic_finalizer;
+  diagnostic_format_decoder (global_dc) = cp_printer;
+
+  init_output_buffer (scratch_buffer, /* prefix */NULL, /* line-width */0);
 }
 
 /* Dump a scope, if deemed necessary.  */
 
 static void
-dump_scope (scope, flags)
-     tree scope;
-     enum tree_string_flags flags;
+dump_scope (tree scope, int flags)
 {
+  int f = ~TFF_RETURN_TYPE & (flags & (TFF_SCOPE | TFF_CHASE_TYPEDEF));
+
   if (scope == NULL_TREE)
     return;
-  
+
   if (TREE_CODE (scope) == NAMESPACE_DECL)
     {
       if (scope != global_namespace)
         {
-          dump_decl (scope, (flags & (TS_PEDANTIC_NAME | TS_FUNC_SCOPE | TS_CHASE_TYPEDEFS))
-                             | TS_FUNC_NORETURN | TS_DECL_TYPE);
-          OB_PUTS ("::");
+          dump_decl (scope, f);
+          print_scope_operator (scratch_buffer);
         }
-      else if (flags & TS_PEDANTIC_NAME)
-        OB_PUTS ("::");
     }
   else if (AGGREGATE_TYPE_P (scope))
     {
-      dump_type (scope, (flags & (TS_PEDANTIC_NAME | TS_FUNC_SCOPE | TS_CHASE_TYPEDEFS))
-                           | TS_FUNC_NORETURN | TS_DECL_TYPE);
-      OB_PUTS ("::");
+      dump_type (scope, f);
+      print_scope_operator (scratch_buffer);
     }
-  else if ((flags & (TS_PEDANTIC_NAME | TS_FUNC_SCOPE))
-            && TREE_CODE (scope) == FUNCTION_DECL)
+  else if ((flags & TFF_SCOPE) && TREE_CODE (scope) == FUNCTION_DECL)
     {
-      dump_function_decl (scope, (flags & (TS_PEDANTIC_NAME | TS_FUNC_SCOPE | TS_CHASE_TYPEDEFS))
-                           | TS_FUNC_NORETURN | TS_DECL_TYPE);
-      OB_PUTS ("::");
+      dump_function_decl (scope, f);
+      print_scope_operator (scratch_buffer);
     }
 }
 
@@ -180,9 +158,7 @@ dump_scope (scope, flags)
    indication of whether we dumped something.  */
 
 static enum pad
-dump_qualifiers (t, p)
-     tree t;
-     enum pad p;
+dump_qualifiers (tree t, enum pad p)
 {
   static const int masks[] =
     {TYPE_QUAL_CONST, TYPE_QUAL_VOLATILE, TYPE_QUAL_RESTRICT};
@@ -191,19 +167,19 @@ dump_qualifiers (t, p)
   int ix;
   int quals = TYPE_QUALS (t);
   int do_after = p == after;
-  
+
   if (quals)
     {
       for (ix = 0; ix != 3; ix++)
         if (masks[ix] & quals)
           {
             if (p == before)
-              OB_PUTC (' ');
+              output_add_space (scratch_buffer);
             p = before;
-            OB_PUTCP (names[ix]);
+            print_identifier (scratch_buffer, names[ix]);
           }
       if (do_after)
-        OB_PUTC (' ');
+        output_add_space (scratch_buffer);
     }
   else
     p = none;
@@ -217,24 +193,19 @@ static char digit_buffer[128];
 /* Dump the template ARGument under control of FLAGS.  */
 
 static void
-dump_template_argument (arg, flags)
-     tree arg;
-     enum tree_string_flags flags;
+dump_template_argument (tree arg, int flags)
 {
-  if (TREE_CODE_CLASS (TREE_CODE (arg)) == 't'
-      || TREE_CODE (arg) == TEMPLATE_DECL)
-    dump_type (arg, flags & ~TS_AGGR_TAGS);
+  if (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL)
+    dump_type (arg, flags & ~TFF_CLASS_KEY_OR_ENUM);
   else
-    dump_expr (arg, (flags | TS_EXPR_PARENS) & ~TS_AGGR_TAGS);
+    dump_expr (arg, (flags | TFF_EXPR_IN_PARENS) & ~TFF_CLASS_KEY_OR_ENUM);
 }
 
 /* Dump a template-argument-list ARGS (always a TREE_VEC) under control
    of FLAGS.  */
 
 static void
-dump_template_argument_list (args, flags)
-     tree args;
-     enum tree_string_flags flags;
+dump_template_argument_list (tree args, int flags)
 {
   int n = TREE_VEC_LENGTH (args);
   int need_comma = 0;
@@ -243,7 +214,7 @@ dump_template_argument_list (args, flags)
   for (i = 0; i< n; ++i)
     {
       if (need_comma)
-        OB_PUTS (", ");
+        separate_with_comma (scratch_buffer);
       dump_template_argument (TREE_VEC_ELT (args, i), flags);
       need_comma = 1;
     }
@@ -252,39 +223,37 @@ dump_template_argument_list (args, flags)
 /* Dump a template parameter PARM (a TREE_LIST) under control of FLAGS.  */
 
 static void
-dump_template_parameter (parm, flags)
-     tree parm;
-     enum tree_string_flags flags;
+dump_template_parameter (tree parm, int flags)
 {
   tree p = TREE_VALUE (parm);
   tree a = TREE_PURPOSE (parm);
 
   if (TREE_CODE (p) == TYPE_DECL)
     {
-      if (flags & TS_DECL_TYPE)
+      if (flags & TFF_DECL_SPECIFIERS)
         {
-          OB_PUTS ("class");
+          print_identifier (scratch_buffer, "class");
           if (DECL_NAME (p))
             {
-              OB_PUTC (' ');
-              OB_PUTID (DECL_NAME (p));
+              output_add_space (scratch_buffer);
+              print_tree_identifier (scratch_buffer, DECL_NAME (p));
             }
         }
       else if (DECL_NAME (p))
-        OB_PUTID (DECL_NAME (p));
+        print_tree_identifier (scratch_buffer, DECL_NAME (p));
       else
-        OB_PUTS ("{template default argument error}");
+        print_identifier (scratch_buffer, "{template default argument error}");
     }
   else
-    dump_decl (p, flags | TS_DECL_TYPE);
+    dump_decl (p, flags | TFF_DECL_SPECIFIERS);
 
-  if ((flags & TS_PARM_DEFAULTS) && a != NULL_TREE)
+  if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && a != NULL_TREE)
     {
-      OB_PUTS (" = ");
-      if (TREE_CODE (a) == TYPE_DECL || TREE_CODE (a) == TEMPLATE_DECL)
-        dump_type (a, flags & ~TS_CHASE_TYPEDEFS);
+      output_add_string (scratch_buffer, " = ");
+      if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL)
+        dump_type (a, flags & ~TFF_CHASE_TYPEDEF);
       else
-        dump_expr (a, flags | TS_EXPR_PARENS);
+        dump_expr (a, flags | TFF_EXPR_IN_PARENS);
     }
 }
 
@@ -293,8 +262,7 @@ dump_template_parameter (parm, flags)
    TREE_VEC.  */
 
 static void
-dump_template_bindings (parms, args)
-     tree parms, args;
+dump_template_bindings (tree parms, tree args)
 {
   int need_comma = 0;
 
@@ -307,17 +275,25 @@ dump_template_bindings (parms, args)
 
       for (i = 0; i < TREE_VEC_LENGTH (p); ++i)
        {
-         tree arg = TMPL_ARG (args, lvl, arg_idx);
+         tree arg = NULL_TREE;
+
+         /* Don't crash if we had an invalid argument list.  */
+         if (TMPL_ARGS_DEPTH (args) >= lvl)
+           {
+             tree lvl_args = TMPL_ARGS_LEVEL (args, lvl);
+             if (NUM_TMPL_ARGS (lvl_args) > arg_idx)
+               arg = TREE_VEC_ELT (lvl_args, arg_idx);
+           }
 
          if (need_comma)
-           OB_PUTS (", ");
-         dump_template_parameter (TREE_VEC_ELT (p, i), TS_PLAIN);
-         OB_PUTS (" = ");
+           separate_with_comma (scratch_buffer);
+         dump_template_parameter (TREE_VEC_ELT (p, i), TFF_PLAIN_IDENTIFIER);
+         output_add_string (scratch_buffer, " = ");
          if (arg)
-           dump_template_argument (arg, TS_PLAIN);
+           dump_template_argument (arg, TFF_PLAIN_IDENTIFIER);
          else
-           OB_PUTS ("{missing}");
-          
+           print_identifier (scratch_buffer, "<missing>");
+
          ++arg_idx;
          need_comma = 1;
        }
@@ -326,24 +302,22 @@ dump_template_bindings (parms, args)
     }
 }
 
-/* Dump into the obstack a human-readable equivalent of TYPE.  FLAGS
-   controls the format.  */
+/* Dump a human-readable equivalent of TYPE.  FLAGS controls the
+   format.  */
 
 static void
-dump_type (t, flags)
-     tree t;
-     enum tree_string_flags flags;
+dump_type (tree t, int flags)
 {
   if (t == NULL_TREE)
     return;
-  
+
   if (TYPE_PTRMEMFUNC_P (t))
     goto offset_type;
 
   switch (TREE_CODE (t))
     {
     case UNKNOWN_TYPE:
-      OB_PUTS ("{unknown type}");
+      print_identifier (scratch_buffer, "<unknown type>");
       break;
 
     case TREE_LIST:
@@ -352,7 +326,7 @@ dump_type (t, flags)
       break;
 
     case IDENTIFIER_NODE:
-      OB_PUTID (t);
+      print_tree_identifier (scratch_buffer, t);
       break;
 
     case TREE_VEC:
@@ -366,29 +340,41 @@ dump_type (t, flags)
       break;
 
     case TYPE_DECL:
-      if (flags & TS_CHASE_TYPEDEFS)
+      if (flags & TFF_CHASE_TYPEDEF)
         {
           dump_type (DECL_ORIGINAL_TYPE (t)
                      ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t), flags);
           break;
         }
       /* else fallthrough */
-    
+
     case TEMPLATE_DECL:
     case NAMESPACE_DECL:
-      dump_decl (t, flags & ~TS_DECL_TYPE);
+      dump_decl (t, flags & ~TFF_DECL_SPECIFIERS);
       break;
-    
+
     case COMPLEX_TYPE:
-      OB_PUTS ("complex ");
+      output_add_string (scratch_buffer, "__complex__ ");
       dump_type (TREE_TYPE (t), flags);
       break;
 
+    case VECTOR_TYPE:
+      output_add_string (scratch_buffer, "vector ");
+      {
+       /* The subtype of a VECTOR_TYPE is something like intQI_type_node,
+          which has no name and is not very useful for diagnostics.  So
+          look up the equivalent C type and print its name.  */
+       tree elt = TREE_TYPE (t);
+       elt = c_common_type_for_mode (TYPE_MODE (elt), TREE_UNSIGNED (elt));
+       dump_type (elt, flags);
+      }
+      break;
+
     case INTEGER_TYPE:
       if (!TREE_UNSIGNED (TYPE_MAIN_VARIANT (t)) && TREE_UNSIGNED (t))
-       OB_PUTS ("unsigned ");
+       output_add_string (scratch_buffer, "unsigned ");
       else if (TREE_UNSIGNED (TYPE_MAIN_VARIANT (t)) && !TREE_UNSIGNED (t))
-       OB_PUTS ("signed ");
+       output_add_string (scratch_buffer, "signed ");
 
       /* fall through.  */
     case REAL_TYPE:
@@ -397,42 +383,43 @@ dump_type (t, flags)
       {
        tree type;
        dump_qualifiers (t, after);
-       type = flags & TS_CHASE_TYPEDEFS ? TYPE_MAIN_VARIANT (t) : t;
+       type = flags & TFF_CHASE_TYPEDEF ? TYPE_MAIN_VARIANT (t) : t;
        if (TYPE_NAME (type) && TYPE_IDENTIFIER (type))
-         OB_PUTID (TYPE_IDENTIFIER (type));
+         print_tree_identifier (scratch_buffer, TYPE_IDENTIFIER (type));
        else
          /* Types like intQI_type_node and friends have no names.
             These don't come up in user error messages, but it's nice
             to be able to print them from the debugger.  */
-         OB_PUTS ("{anonymous}");
+         print_identifier (scratch_buffer, "<anonymous>");
       }
       break;
 
     case TEMPLATE_TEMPLATE_PARM:
-      if (!TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t))
-       {
-         /* For parameters inside template signature. */
-         if (TYPE_IDENTIFIER (t))
-           OB_PUTID (TYPE_IDENTIFIER (t));
-         else
-           OB_PUTS ("{anonymous template template parameter}");
-       }
+      /* For parameters inside template signature.  */
+      if (TYPE_IDENTIFIER (t))
+       print_tree_identifier (scratch_buffer, TYPE_IDENTIFIER (t));
       else
-       {
-         tree args = TYPE_TI_ARGS (t);
-         OB_PUTID (TYPE_IDENTIFIER (t));
-         OB_PUTC ('<');
-          dump_template_argument_list (args, flags);
-         OB_END_TEMPLATE_ID ();
-       }
+       print_identifier
+          (scratch_buffer, "<anonymous template template parameter>");
+      break;
+
+    case BOUND_TEMPLATE_TEMPLATE_PARM:
+      {
+       tree args = TYPE_TI_ARGS (t);
+       print_tree_identifier (scratch_buffer, TYPE_IDENTIFIER (t));
+       print_template_argument_list_start (scratch_buffer);
+        dump_template_argument_list (args, flags);
+       print_template_argument_list_end (scratch_buffer);
+      }
       break;
 
     case TEMPLATE_TYPE_PARM:
       dump_qualifiers (t, after);
       if (TYPE_IDENTIFIER (t))
-       OB_PUTID (TYPE_IDENTIFIER (t));
+       print_tree_identifier (scratch_buffer, TYPE_IDENTIFIER (t));
       else
-       OB_PUTS ("{anonymous template type parameter}");
+       print_identifier
+          (scratch_buffer, "<anonymous template type parameter>");
       break;
 
       /* This is not always necessary for pointers and such, but doing this
@@ -450,34 +437,54 @@ dump_type (t, flags)
       break;
     }
     case TYPENAME_TYPE:
-      OB_PUTS ("typename ");
+      dump_qualifiers (t, after);
+      output_add_string (scratch_buffer, "typename ");
+      dump_typename (t, flags);
+      break;
+
+    case UNBOUND_CLASS_TEMPLATE:
       dump_type (TYPE_CONTEXT (t), flags);
-      OB_PUTS ("::");
-      dump_decl (TYPENAME_TYPE_FULLNAME (t), flags);
+      print_scope_operator (scratch_buffer);
+      print_identifier (scratch_buffer, "template ");
+      dump_type (DECL_NAME (TYPE_NAME (t)), flags);
       break;
 
     case TYPEOF_TYPE:
-      OB_PUTS ("__typeof (");
-      dump_expr (TYPE_FIELDS (t), flags & ~TS_EXPR_PARENS);
-      OB_PUTC (')');
+      output_add_string (scratch_buffer, "__typeof (");
+      dump_expr (TYPE_FIELDS (t), flags & ~TFF_EXPR_IN_PARENS);
+      print_right_paren (scratch_buffer);
       break;
 
     default:
-      sorry ("`%s' not supported by dump_type",
-            tree_code_name[(int) TREE_CODE (t)]);
-      /* Fall through to error. */
+      sorry_for_unsupported_tree (t);
+      /* Fall through to error.  */
 
     case ERROR_MARK:
-      OB_PUTS ("{type error}");
+      print_identifier (scratch_buffer, "<type error>");
       break;
     }
 }
 
+/* Dump a TYPENAME_TYPE. We need to notice when the context is itself
+   a TYPENAME_TYPE.  */
+
+static void
+dump_typename (tree t, int flags)
+{
+  tree ctx = TYPE_CONTEXT (t);
+
+  if (TREE_CODE (ctx) == TYPENAME_TYPE)
+    dump_typename (ctx, flags);
+  else
+    dump_type (ctx, flags & ~TFF_CLASS_KEY_OR_ENUM);
+  print_scope_operator (scratch_buffer);
+  dump_decl (TYPENAME_TYPE_FULLNAME (t), flags);
+}
+
 /* Return the name of the supplied aggregate, or enumeral type.  */
 
 static const char *
-aggr_variety (t)
-     tree t;
+class_key_or_enum (tree t)
 {
   if (TREE_CODE (t) == ENUMERAL_TYPE)
     return "enum";
@@ -493,24 +500,22 @@ aggr_variety (t)
    in the form `class foo'.  */
 
 static void
-dump_aggr_type (t, flags)
-     tree t;
-     enum tree_string_flags flags;
+dump_aggr_type (tree t, int flags)
 {
   tree name;
-  const char *variety = aggr_variety (t);
+  const char *variety = class_key_or_enum (t);
   int typdef = 0;
   int tmplate = 0;
 
   dump_qualifiers (t, after);
 
-  if (flags & TS_AGGR_TAGS)
+  if (flags & TFF_CLASS_KEY_OR_ENUM)
     {
-      OB_PUTCP (variety);
-      OB_PUTC (' ');
+      print_identifier (scratch_buffer, variety);
+      output_add_space (scratch_buffer);
     }
-  
-  if (flags & TS_CHASE_TYPEDEFS)
+
+  if (flags & TFF_CHASE_TYPEDEF)
     t = TYPE_MAIN_VARIANT (t);
 
   name = TYPE_NAME (t);
@@ -524,13 +529,13 @@ dump_aggr_type (t, flags)
                     || TREE_CODE (CLASSTYPE_TI_TEMPLATE (t)) != TEMPLATE_DECL
                     || DECL_TEMPLATE_SPECIALIZATION (CLASSTYPE_TI_TEMPLATE (t))
                     || PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)));
-      dump_scope (CP_DECL_CONTEXT (name), flags | TS_FUNC_SCOPE);
+      dump_scope (CP_DECL_CONTEXT (name), flags | TFF_SCOPE);
       if (tmplate)
         {
           /* Because the template names are mangled, we have to locate
              the most general template, and use that name.  */
           tree tpl = CLASSTYPE_TI_TEMPLATE (t);
-          
+
           while (DECL_TEMPLATE_INFO (tpl))
             tpl = DECL_TI_TEMPLATE (tpl);
           name = tpl;
@@ -540,20 +545,17 @@ dump_aggr_type (t, flags)
 
   if (name == 0 || ANON_AGGRNAME_P (name))
     {
-      OB_PUTS ("{anonymous");
-      if (!(flags & TS_AGGR_TAGS))
-       {
-         OB_PUTC (' ');
-         OB_PUTCP (variety);
-       }
-      OB_PUTC ('}');
+      if (flags & TFF_CLASS_KEY_OR_ENUM)
+        print_identifier (scratch_buffer, "<anonymous>");
+      else
+        output_printf (scratch_buffer, "<anonymous %s>", variety);
     }
   else
-    OB_PUTID (name);
+    print_tree_identifier (scratch_buffer, name);
   if (tmplate)
     dump_template_parms (TYPE_TEMPLATE_INFO (t),
                          !CLASSTYPE_USE_TEMPLATE (t),
-                         flags & ~TS_TEMPLATE_PREFIX);
+                         flags & ~TFF_TEMPLATE_HEADER);
 }
 
 /* Dump into the obstack the initial part of the output for a given type.
@@ -565,42 +567,42 @@ dump_aggr_type (t, flags)
    deal with prefix and suffix.
 
    Arrays must also do this for DECL nodes, like int a[], and for things like
-   int *[]&.  
-   
+   int *[]&.
+
    Return indicates how you should pad an object name after this. I.e. you
    want to pad non-*, non-& cores, but not pad * or & types.  */
 
 static enum pad
-dump_type_prefix (t, flags)
-     tree t;
-     enum tree_string_flags flags;
+dump_type_prefix (tree t, int flags)
 {
   enum pad padding = before;
-  
+
   if (TYPE_PTRMEMFUNC_P (t))
     {
       t = TYPE_PTRMEMFUNC_FN_TYPE (t);
       goto offset_type;
     }
-  
+
   switch (TREE_CODE (t))
     {
     case POINTER_TYPE:
     case REFERENCE_TYPE:
       {
        tree sub = TREE_TYPE (t);
-       
+
        padding = dump_type_prefix (sub, flags);
        /* A tree for a member pointer looks like pointer to offset,
           so let the OFFSET_TYPE case handle it.  */
        if (!TYPE_PTRMEM_P (t))
          {
-           if (padding != none)
-             OB_PUTC (' ');
            if (TREE_CODE (sub) == ARRAY_TYPE)
-             OB_PUTC ('(');
-            OB_PUTC ("&*"[TREE_CODE (t) == POINTER_TYPE]);
-           padding = dump_qualifiers (t, none);
+              {
+                output_add_space (scratch_buffer);
+                print_left_paren (scratch_buffer);
+              }
+            output_add_character
+              (scratch_buffer, "&*"[TREE_CODE (t) == POINTER_TYPE]);
+           padding = dump_qualifiers (t, before);
          }
       }
       break;
@@ -611,11 +613,11 @@ dump_type_prefix (t, flags)
       if (TREE_CODE (t) == OFFSET_TYPE)        /* pmfs deal with this in d_t_p */
        {
          if (padding != none)
-           OB_PUTC (' ');
+           output_add_space (scratch_buffer);
          dump_type (TYPE_OFFSET_BASETYPE (t), flags);
-         OB_PUTS ("::");
+         print_scope_operator (scratch_buffer);
        }
-      OB_PUTC ('*');
+      output_add_character (scratch_buffer, '*');
       padding = dump_qualifiers (t, none);
       break;
 
@@ -624,19 +626,19 @@ dump_type_prefix (t, flags)
     case FUNCTION_TYPE:
       padding = dump_type_prefix (TREE_TYPE (t), flags);
       if (padding != none)
-        OB_PUTC (' ');
-      OB_PUTC ('(');
+        output_add_space (scratch_buffer);
+      print_left_paren (scratch_buffer);
       padding = none;
       break;
 
     case METHOD_TYPE:
       padding = dump_type_prefix (TREE_TYPE (t), flags);
       if (padding != none)
-        OB_PUTC (' ');
-      OB_PUTC ('(');
+        output_add_space (scratch_buffer);
+      print_left_paren (scratch_buffer);
       padding = none;
       dump_aggr_type (TYPE_METHOD_BASETYPE (t), flags);
-      OB_PUTS ("::");
+      print_scope_operator (scratch_buffer);
       break;
 
     case ARRAY_TYPE:
@@ -651,6 +653,7 @@ dump_type_prefix (t, flags)
     case RECORD_TYPE:
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
+    case BOUND_TEMPLATE_TEMPLATE_PARM:
     case TREE_LIST:
     case TYPE_DECL:
     case TREE_VEC:
@@ -659,16 +662,17 @@ dump_type_prefix (t, flags)
     case VOID_TYPE:
     case TYPENAME_TYPE:
     case COMPLEX_TYPE:
+    case VECTOR_TYPE:
+    case TYPEOF_TYPE:
       dump_type (t, flags);
       padding = before;
       break;
-      
-    default:
-      sorry ("`%s' not supported by dump_type_prefix",
-            tree_code_name[(int) TREE_CODE (t)]);
 
+    default:
+      sorry_for_unsupported_tree (t);
+      /* fall through.  */
     case ERROR_MARK:
-      OB_PUTS ("{typeprefixerror}");
+      print_identifier (scratch_buffer, "<typeprefixerror>");
       break;
     }
   return padding;
@@ -678,9 +682,7 @@ dump_type_prefix (t, flags)
    which appears after the identifier (or function parms).  */
 
 static void
-dump_type_suffix (t, flags)
-     tree t;
-     enum tree_string_flags flags;
+dump_type_suffix (tree t, int flags)
 {
   if (TYPE_PTRMEMFUNC_P (t))
     t = TYPE_PTRMEMFUNC_FN_TYPE (t);
@@ -691,7 +693,7 @@ dump_type_suffix (t, flags)
     case REFERENCE_TYPE:
     case OFFSET_TYPE:
       if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
-       OB_PUTC (')');
+       print_right_paren (scratch_buffer);
       dump_type_suffix (TREE_TYPE (t), flags);
       break;
 
@@ -700,42 +702,44 @@ dump_type_suffix (t, flags)
     case METHOD_TYPE:
       {
        tree arg;
-       OB_PUTC (')');
+        print_right_paren (scratch_buffer);
        arg = TYPE_ARG_TYPES (t);
        if (TREE_CODE (t) == METHOD_TYPE)
          arg = TREE_CHAIN (arg);
 
        /* Function pointers don't have default args.  Not in standard C++,
           anyway; they may in g++, but we'll just pretend otherwise.  */
-       dump_parameters (arg, flags & ~TS_PARM_DEFAULTS);
+       dump_parameters (arg, flags & ~TFF_FUNCTION_DEFAULT_ARGUMENTS);
 
        if (TREE_CODE (t) == METHOD_TYPE)
          dump_qualifiers
            (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), before);
-       dump_type_suffix (TREE_TYPE (t), flags);
        dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags);
+       dump_type_suffix (TREE_TYPE (t), flags);
        break;
       }
 
     case ARRAY_TYPE:
-      OB_PUTC ('[');
+      print_left_bracket (scratch_buffer);
       if (TYPE_DOMAIN (t))
        {
-         if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == INTEGER_CST)
-           OB_PUTI (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) + 1);
+         if (host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0))
+           print_integer
+              (scratch_buffer,
+               tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0) + 1);
          else if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == MINUS_EXPR)
            dump_expr (TREE_OPERAND (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0),
-                      flags & ~TS_EXPR_PARENS);
+                      flags & ~TFF_EXPR_IN_PARENS);
          else
-           dump_expr (fold (build_binary_op
+           dump_expr (fold (cp_build_binary_op
                             (PLUS_EXPR, TYPE_MAX_VALUE (TYPE_DOMAIN (t)),
                              integer_one_node)),
-                      flags & ~TS_EXPR_PARENS);
+                      flags & ~TFF_EXPR_IN_PARENS);
        }
-      OB_PUTC (']');
+      print_right_bracket (scratch_buffer);
       dump_type_suffix (TREE_TYPE (t), flags);
       break;
-      
+
     case ENUMERAL_TYPE:
     case IDENTIFIER_NODE:
     case INTEGER_TYPE:
@@ -744,6 +748,7 @@ dump_type_suffix (t, flags)
     case RECORD_TYPE:
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
+    case BOUND_TEMPLATE_TEMPLATE_PARM:
     case TREE_LIST:
     case TYPE_DECL:
     case TREE_VEC:
@@ -752,12 +757,12 @@ dump_type_suffix (t, flags)
     case VOID_TYPE:
     case TYPENAME_TYPE:
     case COMPLEX_TYPE:
+    case VECTOR_TYPE:
+    case TYPEOF_TYPE:
       break;
 
     default:
-      sorry ("`%s' not supported by dump_type_suffix",
-            tree_code_name[(int) TREE_CODE (t)]);
-
+      sorry_for_unsupported_tree (t);
     case ERROR_MARK:
       /* Don't mark it here, we should have already done in
          dump_type_prefix.  */
@@ -765,87 +770,43 @@ dump_type_suffix (t, flags)
     }
 }
 
-/* Return a function declaration which corresponds to the IDENTIFIER_NODE
-   argument.  */
-
-static tree
-ident_fndecl (t)
-     tree t;
-{
-  tree n = lookup_name (t, 0);
-
-  if (n == NULL_TREE)
-    return NULL_TREE;
-
-  if (TREE_CODE (n) == FUNCTION_DECL)
-    return n;
-  else if (TREE_CODE (n) == TREE_LIST
-          && TREE_CODE (TREE_VALUE (n)) == FUNCTION_DECL)
-    return TREE_VALUE (n);
-
-  my_friendly_abort (66);
-  return NULL_TREE;
-}
-
-#ifndef NO_DOLLAR_IN_LABEL
-#  define GLOBAL_THING "_GLOBAL_$"
-#else
-#  ifndef NO_DOT_IN_LABEL
-#    define GLOBAL_THING "_GLOBAL_."
-#  else
-#    define GLOBAL_THING "_GLOBAL__"
-#  endif
-#endif
-
-#define GLOBAL_IORD_P(NODE) \
-  ! strncmp (IDENTIFIER_POINTER(NODE), GLOBAL_THING, sizeof (GLOBAL_THING) - 1)
-
 static void
-dump_global_iord (t)
-     tree t;
+dump_global_iord (tree t)
 {
-  const char *name = IDENTIFIER_POINTER (t);
+  const char *p = NULL;
 
-  OB_PUTS ("(static ");
-  if (name [sizeof (GLOBAL_THING) - 1] == 'I')
-    OB_PUTS ("initializers");
-  else if (name [sizeof (GLOBAL_THING) - 1] == 'D')
-    OB_PUTS ("destructors");
+  if (DECL_GLOBAL_CTOR_P (t))
+    p = "initializers";
+  else if (DECL_GLOBAL_DTOR_P (t))
+    p = "destructors";
   else
-    my_friendly_abort (352);
-  
-  OB_PUTS (" for ");
-  OB_PUTCP (input_filename);
-  OB_PUTC (')');
+    abort ();
+
+  output_printf (scratch_buffer, "(static %s for %s)", p, input_filename);
 }
 
 static void
-dump_simple_decl (t, type, flags)
-     tree t;
-     tree type;
-     enum tree_string_flags flags;
+dump_simple_decl (tree t, tree type, int flags)
 {
-  if (flags & TS_DECL_TYPE)
+  if (flags & TFF_DECL_SPECIFIERS)
     {
       if (dump_type_prefix (type, flags) != none)
-        OB_PUTC (' ');
+        output_add_space (scratch_buffer);
     }
   if (!DECL_INITIAL (t) || TREE_CODE (DECL_INITIAL (t)) != TEMPLATE_PARM_INDEX)
     dump_scope (CP_DECL_CONTEXT (t), flags);
   if (DECL_NAME (t))
     dump_decl (DECL_NAME (t), flags);
   else
-    OB_PUTS ("{anonymous}");
-  if (flags & TS_DECL_TYPE)
+    print_identifier (scratch_buffer, "<anonymous>");
+  if (flags & TFF_DECL_SPECIFIERS)
     dump_type_suffix (type, flags);
 }
 
 /* Dump a human readable string for the decl T under control of FLAGS.  */
 
 static void
-dump_decl (t, flags)
-     tree t;
-     enum tree_string_flags flags;
+dump_decl (tree t, int flags)
 {
   if (t == NULL_TREE)
     return;
@@ -857,33 +818,28 @@ dump_decl (t, flags)
        /* Don't say 'typedef class A' */
         if (DECL_ARTIFICIAL (t))
          {
-           if ((flags & TS_DECL_TYPE)
+           if ((flags & TFF_DECL_SPECIFIERS)
                && TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
-             /* Say `class T' not just `T'. */
-             OB_PUTS ("class ");
+             /* Say `class T' not just `T'.  */
+             output_add_string (scratch_buffer, "class ");
 
            dump_type (TREE_TYPE (t), flags);
            break;
          }
       }
-      if (flags & TS_DECORATE)
-       OB_PUTS ("typedef ");
-      dump_simple_decl (t, DECL_ORIGINAL_TYPE (t) 
+      if (flags & TFF_DECL_SPECIFIERS)
+       output_add_string (scratch_buffer, "typedef ");
+      dump_simple_decl (t, DECL_ORIGINAL_TYPE (t)
                        ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t),
                        flags);
       break;
-      
+
     case VAR_DECL:
       if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t)))
        {
-         OB_PUTS ("vtable for ");
-         if (TYPE_P (DECL_CONTEXT (t)))
-           dump_type (DECL_CONTEXT (t), flags);
-         else
-           /* This case can arise with -fno-vtable-thunks.  See
-              expand_upcast_fixups.  It's not clear what to print
-              here.  */
-           OB_PUTS ("{unknown type}");
+         output_add_string (scratch_buffer, "vtable for ");
+         my_friendly_assert (TYPE_P (DECL_CONTEXT (t)), 20010720);
+         dump_type (DECL_CONTEXT (t), flags);
          break;
        }
       /* else fall through */
@@ -893,29 +849,29 @@ dump_decl (t, flags)
       break;
 
     case RESULT_DECL:
-      OB_PUTS ("{return} ");
+      output_add_string (scratch_buffer, "<return value> ");
       dump_simple_decl (t, TREE_TYPE (t), flags);
       break;
 
     case NAMESPACE_DECL:
       dump_scope (CP_DECL_CONTEXT (t), flags);
       if (DECL_NAME (t) == anonymous_namespace_name)
-       OB_PUTS ("{unnamed}");
+       print_identifier (scratch_buffer, "<unnamed>");
       else
-       OB_PUTID (DECL_NAME (t));
+       print_tree_identifier (scratch_buffer, DECL_NAME (t));
       break;
 
     case SCOPE_REF:
-      dump_decl (TREE_OPERAND (t, 0), flags & ~TS_DECL_TYPE);
-      OB_PUTS ("::");
+      dump_decl (TREE_OPERAND (t, 0), flags & ~TFF_DECL_SPECIFIERS);
+      print_scope_operator (scratch_buffer); 
       dump_decl (TREE_OPERAND (t, 1), flags);
-      break;      
+      break;
 
     case ARRAY_REF:
       dump_decl (TREE_OPERAND (t, 0), flags);
-      OB_PUTC ('[');
+      print_left_bracket (scratch_buffer);
       dump_decl (TREE_OPERAND (t, 1), flags);
-      OB_PUTC (']');
+      print_right_bracket (scratch_buffer);
       break;
 
       /* So that we can do dump_decl on an aggr type.  */
@@ -926,60 +882,57 @@ dump_decl (t, flags)
       break;
 
     case TYPE_EXPR:
-      my_friendly_abort (69);
+      abort ();
       break;
 
       /* These special cases are duplicated here so that other functions
-        can feed identifiers to cp_error and get them demangled properly.  */
+        can feed identifiers to error and get them demangled properly.  */
     case IDENTIFIER_NODE:
-      { tree f;
-       if (DESTRUCTOR_NAME_P (t)
-           && (f = ident_fndecl (t))
-           && DECL_LANGUAGE (f) == lang_cplusplus)
-         {
-           OB_PUTC ('~');
-           dump_decl (DECL_NAME (f), flags);
-         }
-       else if (IDENTIFIER_TYPENAME_P (t))
-         {
-           OB_PUTS ("operator ");
-           /* Not exactly IDENTIFIER_TYPE_VALUE.  */
-           dump_type (TREE_TYPE (t), flags);
-           break;
-         }
-       else if (IDENTIFIER_OPNAME_P (t))
-         {
-           const char *name_string = operator_name_string (t);
-           OB_PUTS ("operator");
-           if (ISALPHA (name_string[0]))
-             OB_PUTC (' ');
-           OB_PUTCP (name_string);
-         }
-       else
-         OB_PUTID (t);
-      }
+      if (IDENTIFIER_TYPENAME_P (t))
+       {
+         output_add_string (scratch_buffer, "operator ");
+         /* Not exactly IDENTIFIER_TYPE_VALUE.  */
+         dump_type (TREE_TYPE (t), flags);
+         break;
+       }
+      else
+       print_tree_identifier (scratch_buffer, t);
       break;
 
     case OVERLOAD:
+      if (OVL_CHAIN (t))
+       {
+         t = OVL_CURRENT (t);
+         if (DECL_CLASS_SCOPE_P (t))
+           {
+             dump_type (DECL_CONTEXT (t), flags);
+             output_add_string (scratch_buffer, "::");
+           }
+         else if (DECL_CONTEXT (t))
+           {
+             dump_decl (DECL_CONTEXT (t), flags);
+             output_add_string (scratch_buffer, "::");
+           }
+         dump_decl (DECL_NAME (t), flags);
+         break;
+       }
+      
+      /* If there's only one function, just treat it like an ordinary
+        FUNCTION_DECL.  */
       t = OVL_CURRENT (t);
       /* Fall through.  */
 
     case FUNCTION_DECL:
-      if (GLOBAL_IORD_P (DECL_ASSEMBLER_NAME (t)))
-       dump_global_iord (DECL_ASSEMBLER_NAME (t));
+      if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t))
+       dump_global_iord (t);
       else if (! DECL_LANG_SPECIFIC (t))
-       OB_PUTS ("{internal}");
-      else if (flags & TS_PEDANTIC_NAME)
-        dump_function_decl (t, flags | TS_FUNC_NORETURN | TS_DECL_TYPE);
+       print_identifier (scratch_buffer, "<internal>");
       else
         dump_function_decl (t, flags);
       break;
 
     case TEMPLATE_DECL:
-      if (flags & TS_PEDANTIC_NAME)
-        dump_template_decl (t, flags | TS_FUNC_NORETURN | TS_DECL_TYPE);
-      else
-        dump_template_decl (t, flags);
+      dump_template_decl (t, flags);
       break;
 
     case TEMPLATE_ID_EXPR:
@@ -989,14 +942,14 @@ dump_decl (t, flags)
        if (is_overloaded_fn (name))
          name = DECL_NAME (get_first_fn (name));
        dump_decl (name, flags);
-       OB_PUTC ('<');
+       print_template_argument_list_start (scratch_buffer);
        for (args = TREE_OPERAND (t, 1); args; args = TREE_CHAIN (args))
          {
            dump_template_argument (TREE_VALUE (args), flags);
            if (TREE_CHAIN (args))
-             OB_PUTS (", ");
+             separate_with_comma (scratch_buffer);
          }
-       OB_END_TEMPLATE_ID ();
+       print_template_argument_list_end (scratch_buffer);
       }
       break;
 
@@ -1005,7 +958,7 @@ dump_decl (t, flags)
       break;
 
     case LABEL_DECL:
-      OB_PUTID (DECL_NAME (t));
+      print_tree_identifier (scratch_buffer, DECL_NAME (t));
       break;
 
     case CONST_DECL:
@@ -1016,25 +969,28 @@ dump_decl (t, flags)
       else if (DECL_NAME (t))
        dump_decl (DECL_NAME (t), flags);
       else if (DECL_INITIAL (t))
-       dump_expr (DECL_INITIAL (t), flags | TS_EXPR_PARENS);
+       dump_expr (DECL_INITIAL (t), flags | TFF_EXPR_IN_PARENS);
       else
-       OB_PUTS ("enumerator");
+       print_identifier (scratch_buffer, "<enumerator>");
       break;
 
     case USING_DECL:
-      OB_PUTS ("using ");
+      output_add_string (scratch_buffer, "using ");
       dump_type (DECL_INITIAL (t), flags);
-      OB_PUTS ("::");
-      OB_PUTID (DECL_NAME (t));
+      print_scope_operator (scratch_buffer);
+      print_tree_identifier (scratch_buffer, DECL_NAME (t));
+      break;
+
+    case BASELINK:
+      dump_decl (BASELINK_FUNCTIONS (t), flags);
       break;
 
     default:
-      sorry ("`%s' not supported by dump_decl",
-            tree_code_name[(int) TREE_CODE (t)]);
+      sorry_for_unsupported_tree (t);
       /* Fallthrough to error.  */
 
     case ERROR_MARK:
-      OB_PUTS ("{declaration error}");
+      print_identifier (scratch_buffer, "<declaration error>");
       break;
     }
 }
@@ -1043,77 +999,80 @@ dump_decl (t, flags)
    'template <...> leaders plus the 'class X' or 'void fn(...)' part.  */
 
 static void
-dump_template_decl (t, flags)
-     tree t;
-     enum tree_string_flags flags;
+dump_template_decl (tree t, int flags)
 {
   tree orig_parms = DECL_TEMPLATE_PARMS (t);
   tree parms;
-  int i; 
-  
-  if (flags & TS_TEMPLATE_PREFIX)
+  int i;
+
+  if (flags & TFF_TEMPLATE_HEADER)
     {
-      for (parms = orig_parms = nreverse (orig_parms); 
+      for (parms = orig_parms = nreverse (orig_parms);
            parms;
            parms = TREE_CHAIN (parms))
         {
          tree inner_parms = INNERMOST_TEMPLATE_PARMS (parms);
           int len = TREE_VEC_LENGTH (inner_parms);
-          
-          OB_PUTS ("template <");
+
+          output_add_string (scratch_buffer, "template<");
+
+         /* If we've shown the template prefix, we'd better show the
+            parameters' and decl's type too.  */
+           flags |= TFF_DECL_SPECIFIERS;
+
           for (i = 0; i < len; i++)
             {
               if (i)
-                OB_PUTS (", ");
+                separate_with_comma (scratch_buffer);
               dump_template_parameter (TREE_VEC_ELT (inner_parms, i), flags);
             }
-          OB_END_TEMPLATE_ID ();
-          OB_PUTC (' ');
+          print_template_argument_list_end (scratch_buffer);
+          output_add_space (scratch_buffer);
         }
       nreverse(orig_parms);
-      /* If we've shown the template<args> prefix, we'd better show the
-        decl's type too.  */
-      flags |= TS_DECL_TYPE;
+
+      if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
+       /* Say `template<arg> class TT' not just `template<arg> TT'.  */
+       output_add_string (scratch_buffer, "class ");
     }
+
   if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
     dump_type (TREE_TYPE (t),
-               ((flags & ~TS_AGGR_TAGS) | TS_TEMPLATE_PLAIN
-                | (flags & TS_DECL_TYPE ? TS_AGGR_TAGS : 0)));
+               ((flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
+                | (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0)));
   else if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL)
-    dump_decl (DECL_TEMPLATE_RESULT (t), flags | TS_TEMPLATE_PLAIN);
+    dump_decl (DECL_TEMPLATE_RESULT (t), flags | TFF_TEMPLATE_NAME);
   else if (TREE_TYPE (t) == NULL_TREE)
-    my_friendly_abort (353);
+    abort ();
   else
     switch (NEXT_CODE (t))
     {
       case METHOD_TYPE:
       case FUNCTION_TYPE:
-        dump_function_decl (t, flags | TS_TEMPLATE_PLAIN);
+        dump_function_decl (t, flags | TFF_TEMPLATE_NAME);
         break;
       default:
-        /* This case can occur with some illegal code.  */
+        /* This case can occur with some invalid code.  */
         dump_type (TREE_TYPE (t),
-                   (flags & ~TS_AGGR_TAGS) | TS_TEMPLATE_PLAIN
-                   | (flags & TS_DECL_TYPE ? TS_AGGR_TAGS : 0));
+                   (flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
+                   | (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0));
     }
 }
 
 /* Pretty print a function decl. There are several ways we want to print a
-   function declaration. The TS_FUNC bits in FLAGS tells us how to behave.
-   As cp_error can only apply the '#' flag once to give 0 and 1 for V, there
-   is %D which doesn't print the throw specs, and %F which does. */
+   function declaration. The TFF_ bits in FLAGS tells us how to behave.
+   As error can only apply the '#' flag once to give 0 and 1 for V, there
+   is %D which doesn't print the throw specs, and %F which does.  */
 
 static void
-dump_function_decl (t, flags)
-     tree t;
-     enum tree_string_flags flags;
+dump_function_decl (tree t, int flags)
 {
   tree fntype;
   tree parmtypes;
   tree cname = NULL_TREE;
   tree template_args = NULL_TREE;
   tree template_parms = NULL_TREE;
-  int show_return = !(flags & TS_FUNC_NORETURN) && (flags & TS_DECL_TYPE);
+  int show_return = flags & TFF_RETURN_TYPE || flags & TFF_DECL_SPECIFIERS;
 
   if (TREE_CODE (t) == TEMPLATE_DECL)
     t = DECL_TEMPLATE_RESULT (t);
@@ -1121,14 +1080,19 @@ dump_function_decl (t, flags)
   /* Pretty print template instantiations only.  */
   if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t))
     {
+      tree tmpl;
+
       template_args = DECL_TI_ARGS (t);
-      t = most_general_template (t);
-      if (TREE_CODE (t) == TEMPLATE_DECL)
-       template_parms = DECL_TEMPLATE_PARMS (t);
+      tmpl = most_general_template (t);
+      if (tmpl && TREE_CODE (tmpl) == TEMPLATE_DECL)
+       {
+         template_parms = DECL_TEMPLATE_PARMS (tmpl);
+         t = tmpl;
+       }
     }
 
   fntype = TREE_TYPE (t);
-  parmtypes = TYPE_ARG_TYPES (fntype);
+  parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);
 
   if (DECL_CLASS_SCOPE_P (t))
     cname = DECL_CONTEXT (t);
@@ -1136,110 +1100,100 @@ dump_function_decl (t, flags)
   else if (TREE_CODE (fntype) == METHOD_TYPE)
     cname = TREE_TYPE (TREE_VALUE (parmtypes));
 
-  if (!(flags & TS_DECORATE))
+  if (!(flags & TFF_DECL_SPECIFIERS))
     /* OK */;
   else if (DECL_STATIC_FUNCTION_P (t))
-    OB_PUTS ("static ");
-  else if (TYPE_POLYMORPHIC_P (t))
-    OB_PUTS ("virtual ");
-  
+    print_identifier (scratch_buffer, "static ");
+  else if (DECL_VIRTUAL_P (t))
+    print_identifier (scratch_buffer, "virtual ");
+
   /* Print the return type?  */
   if (show_return)
     show_return = !DECL_CONV_FN_P (t)  && !DECL_CONSTRUCTOR_P (t)
                   && !DECL_DESTRUCTOR_P (t);
   if (show_return)
     {
-      if (dump_type_prefix (TREE_TYPE (fntype), flags) != none)
-        OB_PUTC (' ');
+      dump_type_prefix (TREE_TYPE (fntype), flags);
+      output_add_space (scratch_buffer);
     }
 
   /* Print the function name.  */
   if (cname)
     {
       dump_type (cname, flags);
-      OB_PUTS ("::");
+      print_scope_operator (scratch_buffer);
     }
   else
     dump_scope (CP_DECL_CONTEXT (t), flags);
 
   dump_function_name (t, flags);
-  
-  if (!(flags & TS_DECL_TYPE))
-    return;
-  if (TREE_CODE (fntype) == METHOD_TYPE && parmtypes)
-    /* Skip "this" parameter.  */
-    parmtypes = TREE_CHAIN (parmtypes);
-    
-  if (DECL_DESTRUCTOR_P (t) || DECL_CONSTRUCTOR_FOR_VBASE_P (t))
-    /* Skip past "in_charge" identifier.  */
-    parmtypes = TREE_CHAIN (parmtypes);
-  
-  dump_parameters (parmtypes, flags);
-  
-  if (show_return)
-    dump_type_suffix (TREE_TYPE (fntype), flags);
 
-  if (TREE_CODE (fntype) == METHOD_TYPE)
-    dump_qualifiers (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))),
-                    before);
-  
-  if (flags & TS_FUNC_THROW)
-    dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), flags);
+  if (1)
+    {
+      dump_parameters (parmtypes, flags);
+
+      if (TREE_CODE (fntype) == METHOD_TYPE)
+       dump_qualifiers (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))),
+                        before);
+
+      if (flags & TFF_EXCEPTION_SPECIFICATION)
+       dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), flags);
+
+      if (show_return)
+       dump_type_suffix (TREE_TYPE (fntype), flags);
+    }
 
   /* If T is a template instantiation, dump the parameter binding.  */
   if (template_parms != NULL_TREE && template_args != NULL_TREE)
     {
-      OB_PUTS (" [with ");
+      output_add_string (scratch_buffer, " [with ");
       dump_template_bindings (template_parms, template_args);
-      OB_PUTC (']');
+      print_right_bracket (scratch_buffer);
     }
 }
 
 /* Print a parameter list. If this is for a member function, the
    member object ptr (and any other hidden args) should have
-   already been removed. */
+   already been removed.  */
 
 static void
-dump_parameters (parmtypes, flags)
-     tree parmtypes;
-     enum tree_string_flags flags;
+dump_parameters (tree parmtypes, int flags)
 {
   int first;
-  OB_PUTS (" (");
+
+  print_left_paren (scratch_buffer);
 
   for (first = 1; parmtypes != void_list_node;
        parmtypes = TREE_CHAIN (parmtypes))
     {
       if (!first)
-        OB_PUTS (", ");
+        separate_with_comma (scratch_buffer);
       first = 0;
       if (!parmtypes)
         {
-          OB_PUTS ("...");
+          print_identifier (scratch_buffer, "...");
           break;
         }
       dump_type (TREE_VALUE (parmtypes), flags);
-      
-      if ((flags & TS_PARM_DEFAULTS) && TREE_PURPOSE (parmtypes))
+
+      if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && TREE_PURPOSE (parmtypes))
         {
-          OB_PUTS (" = ");
-          dump_expr (TREE_PURPOSE (parmtypes), flags | TS_EXPR_PARENS);
+          output_add_string (scratch_buffer, " = ");
+          dump_expr (TREE_PURPOSE (parmtypes), flags | TFF_EXPR_IN_PARENS);
         }
     }
 
-  OB_PUTC (')');
+  print_right_paren (scratch_buffer);
 }
 
-/* Print an exception specification. T is the exception specification. */
+/* Print an exception specification. T is the exception specification.  */
 
 static void
-dump_exception_spec (t, flags)
-     tree t;
-     enum tree_string_flags flags;
+dump_exception_spec (tree t, int flags)
 {
   if (t)
     {
-      OB_PUTS (" throw (");
+      output_add_string (scratch_buffer, " throw (");
       if (TREE_VALUE (t) != NULL_TREE)
         while (1)
           {
@@ -1247,9 +1201,9 @@ dump_exception_spec (t, flags)
             t = TREE_CHAIN (t);
             if (!t)
               break;
-            OB_PUTS (", ");
+            separate_with_comma (scratch_buffer);
           }
-      OB_PUTC (')');
+      print_right_paren (scratch_buffer);
     }
 }
 
@@ -1257,16 +1211,22 @@ dump_exception_spec (t, flags)
    and destructors properly.  */
 
 static void
-dump_function_name (t, flags)
-     tree t;
-     enum tree_string_flags flags;
+dump_function_name (tree t, int flags)
 {
   tree name = DECL_NAME (t);
 
+  if (TREE_CODE (t) == TEMPLATE_DECL)
+    t = DECL_TEMPLATE_RESULT (t);
+
+  /* Don't let the user see __comp_ctor et al.  */
+  if (DECL_CONSTRUCTOR_P (t)
+      || DECL_DESTRUCTOR_P (t))
+    name = constructor_name (DECL_CONTEXT (t));
+
   if (DECL_DESTRUCTOR_P (t))
     {
-      OB_PUTC ('~');
-      dump_decl (name, TS_PLAIN);
+      output_add_character (scratch_buffer, '~');
+      dump_decl (name, TFF_PLAIN_IDENTIFIER);
     }
   else if (DECL_CONV_FN_P (t))
     {
@@ -1276,23 +1236,17 @@ dump_function_name (t, flags)
         declarations, both will have the same name, yet
         the types will be different, hence the TREE_TYPE field
         of the first name will be clobbered by the second.  */
-      OB_PUTS ("operator ");
+      output_add_string (scratch_buffer, "operator ");
       dump_type (TREE_TYPE (TREE_TYPE (t)), flags);
     }
   else if (IDENTIFIER_OPNAME_P (name))
-    {
-      const char *name_string = operator_name_string (name);
-      OB_PUTS ("operator");
-      if (ISALPHA (name_string[0]))
-       OB_PUTC (' ');
-      OB_PUTCP (name_string);
-    }
+    print_tree_identifier (scratch_buffer, name);
   else
     dump_decl (name, flags);
 
   if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
       && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t)
-      && (DECL_TEMPLATE_SPECIALIZATION (t) 
+      && (DECL_TEMPLATE_SPECIALIZATION (t)
          || TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL
          || DECL_TEMPLATE_SPECIALIZATION (DECL_TI_TEMPLATE (t))
          || PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t))))
@@ -1306,17 +1260,14 @@ dump_function_name (t, flags)
    decoration.  */
 
 static void
-dump_template_parms (info, primary, flags)
-     tree info;
-     int primary;
-     enum tree_string_flags flags;
+dump_template_parms (tree info, int primary, int flags)
 {
   tree args = info ? TI_ARGS (info) : NULL_TREE;
-  
-  if (primary && flags & TS_TEMPLATE_PLAIN)
+
+  if (primary && flags & TFF_TEMPLATE_NAME)
     return;
-  flags &= ~(TS_AGGR_TAGS | TS_TEMPLATE_PLAIN);
-  OB_PUTC ('<');
+  flags &= ~(TFF_CLASS_KEY_OR_ENUM | TFF_TEMPLATE_NAME);
+  print_template_argument_list_start (scratch_buffer);
 
   /* Be careful only to print things when we have them, so as not
         to crash producing error messages.  */
@@ -1325,13 +1276,13 @@ dump_template_parms (info, primary, flags)
       int len = 0;
       int ix = 0;
       int need_comma = 0;
-      
+
       if (TREE_CODE (args) == TREE_VEC)
         {
           if (TREE_VEC_LENGTH (args) > 0
-             && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
-           args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
-          
+             && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+           args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
+
           len = TREE_VEC_LENGTH (args);
         }
       else if (TREE_CODE (args) == TREE_LIST)
@@ -1350,10 +1301,10 @@ dump_template_parms (info, primary, flags)
               args = TREE_CHAIN (args);
             }
           if (need_comma)
-            OB_PUTS (", ");
-              
+            separate_with_comma (scratch_buffer);
+          
           if (!arg)
-            OB_PUTS ("{template parameter error}");
+            print_identifier (scratch_buffer, "<template parameter error>");
           else
             dump_template_argument (arg, flags);
           need_comma = 1;
@@ -1364,66 +1315,65 @@ dump_template_parms (info, primary, flags)
       tree tpl = TI_TEMPLATE (info);
       tree parms = DECL_TEMPLATE_PARMS (tpl);
       int len, ix;
-      
+
       parms = TREE_CODE (parms) == TREE_LIST ? TREE_VALUE (parms) : NULL_TREE;
       len = parms ? TREE_VEC_LENGTH (parms) : 0;
-      
+
       for (ix = 0; ix != len; ix++)
         {
           tree parm = TREE_VALUE (TREE_VEC_ELT (parms, ix));
 
           if (ix)
-            OB_PUTS (", ");
-          
-          dump_decl (parm, flags & ~TS_DECL_TYPE);
+            separate_with_comma (scratch_buffer);
+
+          dump_decl (parm, flags & ~TFF_DECL_SPECIFIERS);
         }
     }
-  OB_END_TEMPLATE_ID ();
+  print_template_argument_list_end (scratch_buffer);
 }
 
 static void
-dump_char (c)
-     int c;
+dump_char (int c)
 {
   switch (c)
     {
     case TARGET_NEWLINE:
-      OB_PUTS ("\\n");
+      output_add_string (scratch_buffer, "\\n");
       break;
     case TARGET_TAB:
-      OB_PUTS ("\\t");
+      output_add_string (scratch_buffer, "\\t");
       break;
     case TARGET_VT:
-      OB_PUTS ("\\v");
+      output_add_string (scratch_buffer, "\\v");
       break;
     case TARGET_BS:
-      OB_PUTS ("\\b");
+      output_add_string (scratch_buffer, "\\b");
       break;
     case TARGET_CR:
-      OB_PUTS ("\\r");
+      output_add_string (scratch_buffer, "\\r");
       break;
     case TARGET_FF:
-      OB_PUTS ("\\f");
+      output_add_string (scratch_buffer, "\\f");
       break;
     case TARGET_BELL:
-      OB_PUTS ("\\a");
+      output_add_string (scratch_buffer, "\\a");
       break;
     case '\\':
-      OB_PUTS ("\\\\");
+      output_add_string (scratch_buffer, "\\\\");
       break;
     case '\'':
-      OB_PUTS ("\\'");
+      output_add_string (scratch_buffer, "\\'");
       break;
     case '\"':
-      OB_PUTS ("\\\"");
+      output_add_string (scratch_buffer, "\\\"");
       break;
     default:
       if (ISPRINT (c))
-       OB_PUTC (c);
+       output_add_character (scratch_buffer, c);
       else
        {
          sprintf (digit_buffer, "\\%03o", (int) c);
-         OB_PUTCP (digit_buffer);
+         output_add_string (scratch_buffer, digit_buffer);
        }
     }
 }
@@ -1431,26 +1381,25 @@ dump_char (c)
 /* Print out a list of initializers (subr of dump_expr) */
 
 static void
-dump_expr_list (l, flags)
-     tree l;
-     enum tree_string_flags flags;
+dump_expr_list (tree l, int flags)
 {
   while (l)
     {
-      dump_expr (TREE_VALUE (l), flags | TS_EXPR_PARENS);
+      dump_expr (TREE_VALUE (l), flags | TFF_EXPR_IN_PARENS);
       l = TREE_CHAIN (l);
       if (l)
-       OB_PUTS (", ");
+       separate_with_comma (scratch_buffer);
     }
 }
 
-/* Print out an expression E under control of FLAGS. */
+/* Print out an expression E under control of FLAGS.  */
 
 static void
-dump_expr (t, flags)
-     tree t;
-     enum tree_string_flags flags;
+dump_expr (tree t, int flags)
 {
+  if (t == 0)
+    return;
+  
   switch (TREE_CODE (t))
     {
     case VAR_DECL:
@@ -1461,7 +1410,8 @@ dump_expr (t, flags)
     case TEMPLATE_DECL:
     case NAMESPACE_DECL:
     case OVERLOAD:
-      dump_decl (t, flags & ~TS_DECL_TYPE);
+    case IDENTIFIER_NODE:
+      dump_decl (t, flags & ~TFF_DECL_SPECIFIERS);
       break;
 
     case INTEGER_CST:
@@ -1472,70 +1422,84 @@ dump_expr (t, flags)
        /* If it's an enum, output its tag, rather than its value.  */
        if (TREE_CODE (type) == ENUMERAL_TYPE)
          {
-           const char *p = enum_name_string (t, type);
-           OB_PUTCP (p);
+           tree values = TYPE_VALUES (type);
+
+           for (; values;
+                values = TREE_CHAIN (values))
+             if (tree_int_cst_equal (TREE_VALUE (values), t))
+               break;
+
+           if (values)
+             print_tree_identifier (scratch_buffer, TREE_PURPOSE (values));
+           else
+             {
+                /* Value must have been cast.  */
+                print_left_paren (scratch_buffer);
+                dump_type (type, flags);
+                print_right_paren (scratch_buffer);
+                goto do_int;
+             }
          }
        else if (type == boolean_type_node)
          {
-           if (t == boolean_false_node
-               || (TREE_INT_CST_LOW (t) == 0
-                   && TREE_INT_CST_HIGH (t) == 0))
-             OB_PUTS ("false");
+           if (t == boolean_false_node || integer_zerop (t))
+             print_identifier (scratch_buffer, "false");
            else if (t == boolean_true_node)
-             OB_PUTS ("true");
+             print_identifier (scratch_buffer, "true");
          }
        else if (type == char_type_node)
          {
-           OB_PUTC ('\'');
-           dump_char (TREE_INT_CST_LOW (t));
-           OB_PUTC ('\'');
+           output_add_character (scratch_buffer, '\'');
+           if (host_integerp (t, TREE_UNSIGNED (type)))
+             dump_char (tree_low_cst (t, TREE_UNSIGNED (type)));
+           else
+             output_printf (scratch_buffer, "\\x%x",
+                            (unsigned int) TREE_INT_CST_LOW (t));
+           output_add_character (scratch_buffer, '\'');
          }
-       else if (TREE_INT_CST_HIGH (t)
-                != (TREE_INT_CST_LOW (t) >> (HOST_BITS_PER_WIDE_INT - 1)))
+       else
          {
-           tree val = t;
-           if (TREE_INT_CST_HIGH (val) < 0)
+           do_int:
+           if (! host_integerp (t, 0))
              {
-               OB_PUTC ('-');
-               val = build_int_2 (~TREE_INT_CST_LOW (val),
-                                  -TREE_INT_CST_HIGH (val));
+               tree val = t;
+
+               if (tree_int_cst_sgn (val) < 0)
+                 {
+                   output_add_character (scratch_buffer, '-');
+                   val = build_int_2 (-TREE_INT_CST_LOW (val),
+                                      ~TREE_INT_CST_HIGH (val)
+                                      + !TREE_INT_CST_LOW (val));
+                 }
+               /* Would "%x%0*x" or "%x%*0x" get zero-padding on all
+                  systems?  */
+               {
+                 static char format[12]; /* "0x%x%09999x\0" */
+                 if (!format[0])
+                   sprintf (format, "0x%%x%%0%dx", HOST_BITS_PER_INT / 4);
+                 sprintf (digit_buffer, format, TREE_INT_CST_HIGH (val),
+                          TREE_INT_CST_LOW (val));
+                 output_add_string (scratch_buffer, digit_buffer);
+               }
              }
-           /* Would "%x%0*x" or "%x%*0x" get zero-padding on all
-              systems?  */
-           {
-             static char format[10]; /* "%x%09999x\0" */
-             if (!format[0])
-               sprintf (format, "%%x%%0%dx", HOST_BITS_PER_INT / 4);
-             sprintf (digit_buffer, format, TREE_INT_CST_HIGH (val),
-                      TREE_INT_CST_LOW (val));
-             OB_PUTCP (digit_buffer);
-           }
+           else
+             print_integer (scratch_buffer, TREE_INT_CST_LOW (t));
          }
-       else
-         OB_PUTI (TREE_INT_CST_LOW (t));
       }
       break;
 
     case REAL_CST:
-#ifndef REAL_IS_NOT_DOUBLE
-      sprintf (digit_buffer, "%g", TREE_REAL_CST (t));
-#else
-      {
-       const unsigned char *p = (const unsigned char *) &TREE_REAL_CST (t);
-       size_t i;
-       strcpy (digit_buffer, "0x");
-       for (i = 0; i < sizeof TREE_REAL_CST (t); i++)
-         sprintf (digit_buffer + 2 + 2*i, "%02x", *p++);
-      }
-#endif
-      OB_PUTCP (digit_buffer);
+      real_to_decimal (digit_buffer, &TREE_REAL_CST (t),
+                      sizeof (digit_buffer), 0, 1);
+      output_add_string (scratch_buffer, digit_buffer);
       break;
 
     case PTRMEM_CST:
-      OB_PUTC ('&');
+      output_add_character (scratch_buffer, '&');
       dump_type (PTRMEM_CST_CLASS (t), flags);
-      OB_PUTS ("::");
-      OB_PUTID (DECL_NAME (PTRMEM_CST_MEMBER (t)));
+      print_scope_operator (scratch_buffer);
+      print_tree_identifier
+        (scratch_buffer, DECL_NAME (PTRMEM_CST_MEMBER (t)));
       break;
 
     case STRING_CST:
@@ -1544,71 +1508,72 @@ dump_expr (t, flags)
        int len = TREE_STRING_LENGTH (t) - 1;
        int i;
 
-       OB_PUTC ('\"');
+       output_add_character (scratch_buffer, '\"');
        for (i = 0; i < len; i++)
          dump_char (p[i]);
-       OB_PUTC ('\"');
+       output_add_character (scratch_buffer, '\"');
       }
       break;
 
     case COMPOUND_EXPR:
-      OB_PUTC ('(');
-      dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
-      OB_PUTS (", ");
-      dump_expr (TREE_OPERAND (t, 1), flags | TS_EXPR_PARENS);
-      OB_PUTC (')');
+      print_left_paren (scratch_buffer);
+      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
+      separate_with_comma (scratch_buffer);
+      dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
+      print_right_paren (scratch_buffer);
       break;
 
     case COND_EXPR:
-      OB_PUTC ('(');
-      dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
-      OB_PUTS (" ? ");
-      dump_expr (TREE_OPERAND (t, 1), flags | TS_EXPR_PARENS);
-      OB_PUTS (" : ");
-      dump_expr (TREE_OPERAND (t, 2), flags | TS_EXPR_PARENS);
-      OB_PUTC (')');
+      print_left_paren (scratch_buffer);
+      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
+      output_add_string (scratch_buffer, " ? ");
+      dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
+      output_add_string (scratch_buffer, " : ");
+      dump_expr (TREE_OPERAND (t, 2), flags | TFF_EXPR_IN_PARENS);
+      print_right_paren (scratch_buffer);
       break;
 
     case SAVE_EXPR:
       if (TREE_HAS_CONSTRUCTOR (t))
        {
-         OB_PUTS ("new ");
+         output_add_string (scratch_buffer, "new ");
          dump_type (TREE_TYPE (TREE_TYPE (t)), flags);
        }
       else
        {
-         dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
+         dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
        }
       break;
 
     case AGGR_INIT_EXPR:
       {
        tree fn = NULL_TREE;
-       
+
        if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
          fn = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
 
        if (fn && TREE_CODE (fn) == FUNCTION_DECL)
          {
            if (DECL_CONSTRUCTOR_P (fn))
-             OB_PUTID (TYPE_IDENTIFIER (TREE_TYPE (t)));
+             print_tree_identifier
+                (scratch_buffer, TYPE_IDENTIFIER (TREE_TYPE (t)));
            else
              dump_decl (fn, 0);
          }
        else
          dump_expr (TREE_OPERAND (t, 0), 0);
       }
-      OB_PUTC ('(');
+      print_left_paren (scratch_buffer);
       if (TREE_OPERAND (t, 1))
        dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags);
-      OB_PUTC (')');
+      print_right_paren (scratch_buffer);
       break;
 
     case CALL_EXPR:
       {
        tree fn = TREE_OPERAND (t, 0);
        tree args = TREE_OPERAND (t, 1);
-       
+
        if (TREE_CODE (fn) == ADDR_EXPR)
          fn = TREE_OPERAND (fn, 0);
 
@@ -1617,21 +1582,21 @@ dump_expr (t, flags)
            tree ob = TREE_VALUE (args);
            if (TREE_CODE (ob) == ADDR_EXPR)
              {
-               dump_expr (TREE_OPERAND (ob, 0), flags | TS_EXPR_PARENS);
-               OB_PUTC ('.');
+               dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS);
+               output_add_character (scratch_buffer, '.');
              }
            else if (TREE_CODE (ob) != PARM_DECL
                     || strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this"))
              {
-               dump_expr (ob, flags | TS_EXPR_PARENS);
-               OB_PUTS ("->");
+               dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
+               output_add_string (scratch_buffer, "->");
              }
            args = TREE_CHAIN (args);
          }
-       dump_expr (fn, flags | TS_EXPR_PARENS);
-       OB_PUTC ('(');
+       dump_expr (fn, flags | TFF_EXPR_IN_PARENS);
+       print_left_paren (scratch_buffer);
        dump_expr_list (args, flags);
-       OB_PUTC (')');
+       print_right_paren (scratch_buffer);
       }
       break;
 
@@ -1639,13 +1604,13 @@ dump_expr (t, flags)
       {
        tree type = TREE_OPERAND (t, 1);
        if (NEW_EXPR_USE_GLOBAL (t))
-         OB_PUTS ("::");
-       OB_PUTS ("new ");
+         print_scope_operator (scratch_buffer);
+       output_add_string (scratch_buffer, "new ");
        if (TREE_OPERAND (t, 0))
          {
-           OB_PUTC ('(');
+           print_left_paren (scratch_buffer);
            dump_expr_list (TREE_OPERAND (t, 0), flags);
-           OB_PUTS (") ");
+           output_add_string (scratch_buffer, ") ");
          }
        if (TREE_CODE (type) == ARRAY_REF)
          type = build_cplus_array_type
@@ -1656,9 +1621,9 @@ dump_expr (t, flags)
        dump_type (type, flags);
        if (TREE_OPERAND (t, 2))
          {
-           OB_PUTC ('(');
+           print_left_paren (scratch_buffer);
            dump_expr_list (TREE_OPERAND (t, 2), flags);
-           OB_PUTC (')');
+           print_right_paren (scratch_buffer);
          }
       }
       break;
@@ -1670,7 +1635,7 @@ dump_expr (t, flags)
         default argument.  Note we may have cleared out the first
         operand in expand_expr, so don't go killing ourselves.  */
       if (TREE_OPERAND (t, 1))
-       dump_expr (TREE_OPERAND (t, 1), flags | TS_EXPR_PARENS);
+       dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
       break;
 
     case INIT_EXPR:
@@ -1697,7 +1662,7 @@ dump_expr (t, flags)
     case EQ_EXPR:
     case NE_EXPR:
     case EXACT_DIV_EXPR:
-      dump_binary_op (opname_tab[(int) TREE_CODE (t)], t, flags);
+      dump_binary_op (operator_name_info[(int) TREE_CODE (t)].name, t, flags);
       break;
 
     case CEIL_DIV_EXPR:
@@ -1721,30 +1686,32 @@ dump_expr (t, flags)
            if (TREE_CODE (ob) != PARM_DECL
                || strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this"))
              {
-               dump_expr (ob, flags | TS_EXPR_PARENS);
-               OB_PUTS ("->");
+               dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
+               output_add_string (scratch_buffer, "->");
              }
          }
        else
          {
-           dump_expr (ob, flags | TS_EXPR_PARENS);
-           OB_PUTC ('.');
+           dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
+           output_add_character (scratch_buffer, '.');
          }
-       dump_expr (TREE_OPERAND (t, 1), flags & ~TS_EXPR_PARENS);
+       dump_expr (TREE_OPERAND (t, 1), flags & ~TFF_EXPR_IN_PARENS);
       }
       break;
 
     case ARRAY_REF:
-      dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
-      OB_PUTC ('[');
-      dump_expr (TREE_OPERAND (t, 1), flags | TS_EXPR_PARENS);
-      OB_PUTC (']');
+      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
+      print_left_bracket (scratch_buffer);
+      dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
+      print_right_bracket (scratch_buffer);
       break;
 
     case CONVERT_EXPR:
-      if (same_type_p (TREE_TYPE (t), void_type_node))
+      if (TREE_TYPE (t) && VOID_TYPE_P (TREE_TYPE (t)))
        {
-         OB_PUTS ("(void)");
+         print_left_paren (scratch_buffer);
+         dump_type (TREE_TYPE (t), flags);
+         print_right_paren (scratch_buffer);
          dump_expr (TREE_OPERAND (t, 0), flags);
        }
       else
@@ -1753,8 +1720,13 @@ dump_expr (t, flags)
 
     case ADDR_EXPR:
       if (TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
-         || TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST)
-       dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
+         || TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST
+         /* An ADDR_EXPR can have reference type.  In that case, we
+            shouldn't print the `&' doing so indicates to the user
+            that the expression has pointer type.  */
+         || (TREE_TYPE (t)
+             && TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE))
+       dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
       else
        dump_unary_op ("&", t, flags);
       break;
@@ -1764,10 +1736,10 @@ dump_expr (t, flags)
        {
          t = TREE_OPERAND (t, 0);
          my_friendly_assert (TREE_CODE (t) == CALL_EXPR, 237);
-         dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
-         OB_PUTC ('(');
+         dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
+         print_left_paren (scratch_buffer);
          dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags);
-         OB_PUTC (')');
+         print_right_paren (scratch_buffer);
        }
       else
        {
@@ -1785,15 +1757,16 @@ dump_expr (t, flags)
     case TRUTH_NOT_EXPR:
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
-      dump_unary_op (opname_tab [(int)TREE_CODE (t)], t, flags);
+      dump_unary_op (operator_name_info [(int)TREE_CODE (t)].name, t, flags);
       break;
 
     case POSTDECREMENT_EXPR:
     case POSTINCREMENT_EXPR:
-      OB_PUTC ('(');
-      dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
-      OB_PUTCP (opname_tab[(int)TREE_CODE (t)]);
-      OB_PUTC (')');
+      print_left_paren (scratch_buffer);
+      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
+      print_identifier
+        (scratch_buffer, operator_name_info[(int)TREE_CODE (t)].name);
+      print_right_paren (scratch_buffer);
       break;
 
     case NON_LVALUE_EXPR:
@@ -1806,20 +1779,20 @@ dump_expr (t, flags)
 
          while (TREE_CODE (next) == POINTER_TYPE)
            next = TREE_TYPE (next);
-         
+
          if (TREE_CODE (next) == FUNCTION_TYPE)
            {
-             if (flags & TS_EXPR_PARENS)
-               OB_PUTC ('(');
-             OB_PUTC ('*');
-             dump_expr (TREE_OPERAND (t, 0), flags & ~TS_EXPR_PARENS);
-             if (flags & TS_EXPR_PARENS)
-               OB_PUTC (')');
+             if (flags & TFF_EXPR_IN_PARENS)
+               print_left_paren (scratch_buffer);
+             output_add_character (scratch_buffer, '*');
+             dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
+             if (flags & TFF_EXPR_IN_PARENS)
+               print_right_paren (scratch_buffer);
              break;
            }
          /* else FALLTHRU */
        }
-      dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
+      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
       break;
 
     case NOP_EXPR:
@@ -1833,25 +1806,17 @@ dump_expr (t, flags)
     case CONSTRUCTOR:
       if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
        {
-         tree idx = build_component_ref (t, index_identifier, NULL_TREE, 0);
+         tree idx = build_ptrmemfunc_access_expr (t, pfn_identifier);
 
-         if (integer_all_onesp (idx))
-           {
-             tree pfn = PFN_FROM_PTRMEMFUNC (t);
-             dump_unary_op ("&", pfn, flags | TS_EXPR_PARENS);
-             break;
-           }
-         else if (TREE_CODE (idx) == INTEGER_CST
-                  && tree_int_cst_equal (idx, integer_zero_node))
+         if (integer_zerop (idx))
            {
              /* A NULL pointer-to-member constant.  */
-             OB_PUTS ("((");
+             output_add_string (scratch_buffer, "((");
              dump_type (TREE_TYPE (t), flags);
-             OB_PUTS (") 0)");
+             output_add_string (scratch_buffer, ") 0)");
              break;
            }
-         else if (TREE_CODE (idx) == INTEGER_CST
-                  && TREE_INT_CST_HIGH (idx) == 0)
+         else if (host_integerp (idx, 0))
            {
              tree virtuals;
              unsigned HOST_WIDE_INT n;
@@ -1859,8 +1824,8 @@ dump_expr (t, flags)
              t = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)));
              t = TYPE_METHOD_BASETYPE (t);
              virtuals = TYPE_BINFO_VIRTUALS (TYPE_MAIN_VARIANT (t));
-             
-             n = TREE_INT_CST_LOW (idx);
+
+             n = tree_low_cst (idx, 0);
 
              /* Map vtable index back one, to allow for the null pointer to
                 member.  */
@@ -1873,15 +1838,25 @@ dump_expr (t, flags)
                }
              if (virtuals)
                {
-                 dump_expr (TREE_VALUE (virtuals),
-                            flags | TS_EXPR_PARENS);
+                 dump_expr (BV_FN (virtuals),
+                            flags | TFF_EXPR_IN_PARENS);
                  break;
                }
            }
        }
-      OB_PUTC ('{');
-      dump_expr_list (CONSTRUCTOR_ELTS (t), flags);
-      OB_PUTC ('}');
+      if (TREE_TYPE (t) && !CONSTRUCTOR_ELTS (t))
+       {
+         dump_type (TREE_TYPE (t), 0);
+         output_add_character (scratch_buffer, '(');
+         output_add_character (scratch_buffer, ')');
+       }
+      else
+       {
+         output_add_character (scratch_buffer, '{');
+         dump_expr_list (CONSTRUCTOR_ELTS (t), flags);
+         output_add_character (scratch_buffer, '}');
+       }
+      
       break;
 
     case OFFSET_REF:
@@ -1892,9 +1867,10 @@ dump_expr (t, flags)
            t = TREE_OPERAND (t, 1);
            if (TREE_CODE (t) == FUNCTION_DECL)
              /* A::f */
-             dump_expr (t, flags | TS_EXPR_PARENS);
+             dump_expr (t, flags | TFF_EXPR_IN_PARENS);
            else if (BASELINK_P (t))
-             dump_expr (OVL_CURRENT (TREE_VALUE (t)), flags | TS_EXPR_PARENS);
+             dump_expr (OVL_CURRENT (BASELINK_FUNCTIONS (t)), 
+                        flags | TFF_EXPR_IN_PARENS);
            else
              dump_decl (t, flags);
          }
@@ -1902,31 +1878,27 @@ dump_expr (t, flags)
          {
            if (TREE_CODE (ob) == INDIRECT_REF)
              {
-               dump_expr (TREE_OPERAND (ob, 0), flags | TS_EXPR_PARENS);
-               OB_PUTS (" ->* ");
+               dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS);
+               output_add_string (scratch_buffer, "->*");
              }
            else
              {
-               dump_expr (ob, flags | TS_EXPR_PARENS);
-               OB_PUTS (" .* ");
+               dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
+               output_add_string (scratch_buffer, ".*");
              }
-           dump_expr (TREE_OPERAND (t, 1), flags | TS_EXPR_PARENS);
+           dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
          }
        break;
       }
 
     case TEMPLATE_PARM_INDEX:
-      dump_decl (TEMPLATE_PARM_DECL (t), flags & ~TS_DECL_TYPE);
-      break;
-
-    case IDENTIFIER_NODE:
-      OB_PUTID (t);
+      dump_decl (TEMPLATE_PARM_DECL (t), flags & ~TFF_DECL_SPECIFIERS);
       break;
 
     case SCOPE_REF:
       dump_type (TREE_OPERAND (t, 0), flags);
-      OB_PUTS ("::");
-      dump_expr (TREE_OPERAND (t, 1), flags | TS_EXPR_PARENS);
+      print_scope_operator (scratch_buffer);
+      dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
       break;
 
     case CAST_EXPR:
@@ -1934,48 +1906,65 @@ dump_expr (t, flags)
          || TREE_CHAIN (TREE_OPERAND (t, 0)))
        {
          dump_type (TREE_TYPE (t), flags);
-         OB_PUTC ('(');
+         print_left_paren (scratch_buffer);
          dump_expr_list (TREE_OPERAND (t, 0), flags);
-         OB_PUTC (')');
+         print_right_paren (scratch_buffer);
        }
       else
        {
-         OB_PUTC ('(');
+         print_left_paren (scratch_buffer);
          dump_type (TREE_TYPE (t), flags);
-         OB_PUTC (')');
-         OB_PUTC ('(');
+          output_add_string (scratch_buffer, ")(");
          dump_expr_list (TREE_OPERAND (t, 0), flags);
-         OB_PUTC (')');
+         print_right_paren (scratch_buffer);
        }
       break;
 
+    case STATIC_CAST_EXPR:
+      output_add_string (scratch_buffer, "static_cast<");
+      goto cast;
+    case REINTERPRET_CAST_EXPR:
+      output_add_string (scratch_buffer, "reinterpret_cast<");
+      goto cast;
+    case CONST_CAST_EXPR:
+      output_add_string (scratch_buffer, "const_cast<");
+      goto cast;
+    case DYNAMIC_CAST_EXPR:
+      output_add_string (scratch_buffer, "dynamic_cast<");
+    cast:
+      dump_type (TREE_TYPE (t), flags);
+      output_add_string (scratch_buffer, ">(");
+      dump_expr (TREE_OPERAND (t, 0), flags);
+      print_right_paren (scratch_buffer);
+      break;
+
     case LOOKUP_EXPR:
-      OB_PUTID (TREE_OPERAND (t, 0));
+      print_tree_identifier (scratch_buffer, TREE_OPERAND (t, 0));
       break;
 
     case ARROW_EXPR:
       dump_expr (TREE_OPERAND (t, 0), flags);
-      OB_PUTS ("->");
+      output_add_string (scratch_buffer, "->");
       break;
 
     case SIZEOF_EXPR:
     case ALIGNOF_EXPR:
       if (TREE_CODE (t) == SIZEOF_EXPR)
-       OB_PUTS ("sizeof (");
-      else 
+       output_add_string (scratch_buffer, "sizeof (");
+      else
        {
          my_friendly_assert (TREE_CODE (t) == ALIGNOF_EXPR, 0);
-         OB_PUTS ("__alignof__ (");
+         output_add_string (scratch_buffer, "__alignof__ (");
        }
-      if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 0))) == 't')
+      if (TYPE_P (TREE_OPERAND (t, 0)))
        dump_type (TREE_OPERAND (t, 0), flags);
       else
-       dump_unary_op ("*", t, flags | TS_EXPR_PARENS);
-      OB_PUTC (')');
+       dump_unary_op ("*", t, flags | TFF_EXPR_IN_PARENS);
+      print_right_paren (scratch_buffer);
       break;
 
     case DEFAULT_ARG:
-      OB_PUTS ("{unparsed}");
+      print_identifier (scratch_buffer, "<unparsed>");
       break;
 
     case TRY_CATCH_EXPR:
@@ -1986,9 +1975,9 @@ dump_expr (t, flags)
 
     case PSEUDO_DTOR_EXPR:
       dump_expr (TREE_OPERAND (t, 2), flags);
-      OB_PUTS (".");
+      output_add_character (scratch_buffer, '.');
       dump_type (TREE_OPERAND (t, 0), flags);
-      OB_PUTS ("::~");
+      output_add_string (scratch_buffer, "::~");
       dump_type (TREE_OPERAND (t, 1), flags);
       break;
 
@@ -1999,175 +1988,144 @@ dump_expr (t, flags)
     case STMT_EXPR:
       /* We don't yet have a way of dumping statements in a
         human-readable format.  */
-      OB_PUTS ("{ ... }");
+      output_add_string (scratch_buffer, "({...})");
       break;
 
     case BIND_EXPR:
-      OB_PUTS ("{ ");
-      dump_expr (TREE_OPERAND (t, 1), flags & ~TS_EXPR_PARENS);
-      OB_PUTS ("} ");
+      output_add_character (scratch_buffer, '{');
+      dump_expr (TREE_OPERAND (t, 1), flags & ~TFF_EXPR_IN_PARENS);
+      output_add_character (scratch_buffer, '}');
       break;
-      
+
     case LOOP_EXPR:
-      OB_PUTS ("while (1) { ");
-      dump_expr (TREE_OPERAND (t, 0), flags & ~TS_EXPR_PARENS);
-      OB_PUTS ("} ");
+      output_add_string (scratch_buffer, "while (1) { ");
+      dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
+      output_add_character (scratch_buffer, '}');
       break;
 
     case EXIT_EXPR:
-      OB_PUTS ("if (");
-      dump_expr (TREE_OPERAND (t, 0), flags & ~TS_EXPR_PARENS);
-      OB_PUTS (") break; ");
+      output_add_string (scratch_buffer, "if (");
+      dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
+      output_add_string (scratch_buffer, ") break; ");
       break;
 
-    case TREE_LIST:
-      if (TREE_VALUE (t) && TREE_CODE (TREE_VALUE (t)) == FUNCTION_DECL)
-       {
-         OB_PUTID (DECL_NAME (TREE_VALUE (t)));
-         break;
-       }
-      /* else fall through */  
+    case BASELINK:
+      dump_expr (get_first_fn (t), flags & ~TFF_EXPR_IN_PARENS);
+      break;
+
+      /* else fall through */
 
       /*  This list is incomplete, but should suffice for now.
          It is very important that `sorry' does not call
          `report_error_function'.  That could cause an infinite loop.  */
     default:
-      sorry ("`%s' not supported by dump_expr",
-            tree_code_name[(int) TREE_CODE (t)]);
-
+      sorry_for_unsupported_tree (t);
       /* fall through to ERROR_MARK...  */
     case ERROR_MARK:
-      OB_PUTCP ("{expression error}");
+      print_identifier (scratch_buffer, "<expression error>");
       break;
     }
 }
 
 static void
-dump_binary_op (opstring, t, flags)
-     const char *opstring;
-     tree t;
-     enum tree_string_flags flags;
+dump_binary_op (const char *opstring, tree t, int flags)
 {
-  OB_PUTC ('(');
-  dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
-  OB_PUTC (' ');
+  print_left_paren (scratch_buffer);
+  dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
+  output_add_space (scratch_buffer);
   if (opstring)
-    OB_PUTCP (opstring);
+    print_identifier (scratch_buffer, opstring);
   else
-    OB_PUTS ("<unknown operator>");
-  OB_PUTC (' ');
-  dump_expr (TREE_OPERAND (t, 1), flags | TS_EXPR_PARENS);
-  OB_PUTC (')');
+    print_identifier (scratch_buffer, "<unknown operator>");
+  output_add_space (scratch_buffer);
+  dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
+  print_right_paren (scratch_buffer);
 }
 
 static void
-dump_unary_op (opstring, t, flags)
-     const char *opstring;
-     tree t;
-     enum tree_string_flags flags;
+dump_unary_op (const char *opstring, tree t, int flags)
 {
-  if (flags & TS_EXPR_PARENS)
-    OB_PUTC ('(');
-  OB_PUTCP (opstring);
-  dump_expr (TREE_OPERAND (t, 0), flags & ~TS_EXPR_PARENS);
-  if (flags & TS_EXPR_PARENS)
-    OB_PUTC (')');
+  if (flags & TFF_EXPR_IN_PARENS)
+    print_left_paren (scratch_buffer);
+  print_identifier (scratch_buffer, opstring);
+  dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
+  if (flags & TFF_EXPR_IN_PARENS)
+    print_right_paren (scratch_buffer);
 }
 
-/* Exported interface to stringifying types, exprs and decls under TS_*
+/* Exported interface to stringifying types, exprs and decls under TFF_*
    control.  */
 
 const char *
-type_as_string (typ, flags)
-     tree typ;
-     enum tree_string_flags flags;
+type_as_string (tree typ, int flags)
 {
-  OB_INIT ();
+  reinit_global_formatting_buffer ();
 
   dump_type (typ, flags);
 
-  OB_FINISH ();
-
-  return (char *)obstack_base (&scratch_obstack);
+  return output_finalize_message (scratch_buffer);
 }
 
 const char *
-expr_as_string (decl, flags)
-     tree decl;
-     enum tree_string_flags flags;
+expr_as_string (tree decl, int flags)
 {
-  OB_INIT ();
+  reinit_global_formatting_buffer ();
 
   dump_expr (decl, flags);
 
-  OB_FINISH ();
-
-  return (char *)obstack_base (&scratch_obstack);
+  return output_finalize_message (scratch_buffer);
 }
 
 const char *
-decl_as_string (decl, flags)
-     tree decl;
-     enum tree_string_flags flags;
+decl_as_string (tree decl, int flags)
 {
-  OB_INIT ();
+  reinit_global_formatting_buffer ();
 
   dump_decl (decl, flags);
 
-  OB_FINISH ();
-
-  return (char *)obstack_base (&scratch_obstack);
+  return output_finalize_message (scratch_buffer);
 }
 
 const char *
-context_as_string (context, flags)
-     tree context;
-     enum tree_string_flags flags;
+context_as_string (tree context, int flags)
 {
-  OB_INIT ();
-  
+  reinit_global_formatting_buffer ();
+
   dump_scope (context, flags);
-  
-  OB_FINISH ();
 
-  return (char *)obstack_base (&scratch_obstack);
+  return output_finalize_message (scratch_buffer);
 }
 
-/* Generate the three forms of printable names for lang_printable_name.  */
+/* Generate the three forms of printable names for cxx_printable_name.  */
 
 const char *
-lang_decl_name (decl, v)
-     tree decl;
-     int v;
+lang_decl_name (tree decl, int v)
 {
   if (v >= 2)
-    return decl_as_string (decl, TS_DECL_TYPE);
+    return decl_as_string (decl, TFF_DECL_SPECIFIERS);
 
-  OB_INIT ();
+  reinit_global_formatting_buffer ();
 
   if (v == 1 && DECL_CLASS_SCOPE_P (decl))
     {
-      dump_type (CP_DECL_CONTEXT (decl), TS_PLAIN);
-      OB_PUTS ("::");
+      dump_type (CP_DECL_CONTEXT (decl), TFF_PLAIN_IDENTIFIER);
+      print_scope_operator (scratch_buffer);
     }
 
   if (TREE_CODE (decl) == FUNCTION_DECL)
-    dump_function_name (decl, TS_PLAIN);
+    dump_function_name (decl, TFF_PLAIN_IDENTIFIER);
   else
-    dump_decl (DECL_NAME (decl), TS_PLAIN);
-
-  OB_FINISH ();
+    dump_decl (DECL_NAME (decl), TFF_PLAIN_IDENTIFIER);
 
-  return (char *)obstack_base (&scratch_obstack);
+  return output_finalize_message (scratch_buffer);
 }
 
 const char *
-cp_file_of (t)
-     tree t;
+cp_file_of (tree t)
 {
   if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t))
     return DECL_SOURCE_FILE (DECL_CONTEXT (t));
-  else if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
+  else if (TYPE_P (t))
     return DECL_SOURCE_FILE (TYPE_MAIN_DECL (t));
   else if (TREE_CODE (t) == OVERLOAD)
     return DECL_SOURCE_FILE (OVL_FUNCTION (t));
@@ -2176,8 +2134,7 @@ cp_file_of (t)
 }
 
 int
-cp_line_of (t)
-     tree t;
+cp_line_of (tree t)
 {
   int line = 0;
   if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t))
@@ -2186,7 +2143,7 @@ cp_line_of (t)
       && TYPE_MAIN_DECL (TREE_TYPE (t)))
     t = TREE_TYPE (t);
 
-  if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
+  if (TYPE_P (t))
     line = DECL_SOURCE_LINE (TYPE_MAIN_DECL (t));
   else if (TREE_CODE (t) == OVERLOAD)
     line = DECL_SOURCE_LINE (OVL_FUNCTION (t));
@@ -2199,81 +2156,65 @@ cp_line_of (t)
   return line;
 }
 
-/* Now the interfaces from cp_error et al to dump_type et al. Each takes an
-   on/off VERBOSE flag and supply the appropriate TS_ flags to a dump_
+/* Now the interfaces from error et al to dump_type et al. Each takes an
+   on/off VERBOSE flag and supply the appropriate TFF_ flags to a dump_
    function.  */
 
 static const char *
-decl_to_string (decl, verbose)
-     tree decl;
-     int verbose;
+decl_to_string (tree decl, int verbose)
 {
-  enum tree_string_flags flags = 0;
+  int flags = 0;
 
   if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == RECORD_TYPE
       || TREE_CODE (decl) == UNION_TYPE || TREE_CODE (decl) == ENUMERAL_TYPE)
-    flags = TS_AGGR_TAGS;
+    flags = TFF_CLASS_KEY_OR_ENUM;
   if (verbose)
-    flags |= TS_DECL_TYPE | TS_DECORATE | TS_PARM_DEFAULTS;
+    flags |= TFF_DECL_SPECIFIERS | TFF_FUNCTION_DEFAULT_ARGUMENTS;
   else if (TREE_CODE (decl) == FUNCTION_DECL)
-    flags |= TS_DECL_TYPE | TS_FUNC_NORETURN;
-  flags |= TS_TEMPLATE_PREFIX;
-  
-  OB_INIT ();
+    flags |= TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE;
+  flags |= TFF_TEMPLATE_HEADER;
 
-  dump_decl (decl, flags);
+  reinit_global_formatting_buffer ();
 
-  OB_FINISH ();
+  dump_decl (decl, flags);
 
-  return (char *)obstack_base (&scratch_obstack);
+  return output_finalize_message (scratch_buffer);
 }
 
 static const char *
-expr_to_string (decl, verbose)
-     tree decl;
-     int verbose ATTRIBUTE_UNUSED;
+expr_to_string (tree decl, int verbose ATTRIBUTE_UNUSED)
 {
-  OB_INIT ();
+  reinit_global_formatting_buffer ();
 
   dump_expr (decl, 0);
 
-  OB_FINISH ();
-
-  return (char *)obstack_base (&scratch_obstack);
+  return output_finalize_message (scratch_buffer);
 }
 
 static const char *
-fndecl_to_string (fndecl, verbose)
-     tree fndecl;
-     int verbose;
+fndecl_to_string (tree fndecl, int verbose)
 {
-  enum tree_string_flags flags;
-  
-  flags = TS_FUNC_THROW | TS_DECL_TYPE;
+  int flags;
+
+  flags = TFF_EXCEPTION_SPECIFICATION | TFF_DECL_SPECIFIERS;
   if (verbose)
-    flags |= TS_PARM_DEFAULTS;
-  OB_INIT ();
+    flags |= TFF_FUNCTION_DEFAULT_ARGUMENTS;
+  reinit_global_formatting_buffer ();
 
   dump_decl (fndecl, flags);
-  
-  OB_FINISH ();
 
-  return (char *)obstack_base (&scratch_obstack);
+  return output_finalize_message (scratch_buffer);
 }
 
 
 static const char *
-code_to_string (c, v)
-     enum tree_code c;
-     int v ATTRIBUTE_UNUSED;
+code_to_string (enum tree_code c, int v ATTRIBUTE_UNUSED)
 {
   return tree_code_name [c];
 }
 
-static const char *
-language_to_string (c, v)
-     enum languages c;
-     int v ATTRIBUTE_UNUSED;
+const char *
+language_to_string (enum languages c, int v ATTRIBUTE_UNUSED)
 {
   switch (c)
     {
@@ -2287,7 +2228,7 @@ language_to_string (c, v)
       return "Java";
 
     default:
-      my_friendly_abort (355);
+      abort ();
       return 0;
     }
 }
@@ -2295,9 +2236,7 @@ language_to_string (c, v)
 /* Return the proper printed version of a parameter to a C++ function.  */
 
 static const char *
-parm_to_string (p, v)
-     int p;
-     int v ATTRIBUTE_UNUSED;
+parm_to_string (int p, int v ATTRIBUTE_UNUSED)
 {
   if (p < 0)
     return "`this'";
@@ -2307,93 +2246,415 @@ parm_to_string (p, v)
 }
 
 static const char *
-op_to_string (p, v)
-     enum tree_code p;
-     int v ATTRIBUTE_UNUSED;
+op_to_string (enum tree_code p, int v ATTRIBUTE_UNUSED)
 {
-  static char buf[] = "operator                ";
+  tree id;
 
-  if (p == 0)
-    return "{unknown}";
-  
-  strcpy (buf + 8, opname_tab [p]);
-  return buf;
+  id = operator_name_info[(int) p].identifier;
+  return id ? IDENTIFIER_POINTER (id) : "{unknown}";
 }
 
 static const char *
-type_to_string (typ, verbose)
-     tree typ;
-     int verbose;
+type_to_string (tree typ, int verbose)
 {
-  enum tree_string_flags flags;
-  
+  int flags;
+
   flags = 0;
   if (verbose)
-    flags |= TS_AGGR_TAGS;
-  flags |= TS_TEMPLATE_PREFIX;
-  
-  OB_INIT ();
+    flags |= TFF_CLASS_KEY_OR_ENUM;
+  flags |= TFF_TEMPLATE_HEADER;
 
-  dump_type (typ, flags);
+  reinit_global_formatting_buffer ();
 
-  OB_FINISH ();
+  dump_type (typ, flags);
 
-  return (char *)obstack_base (&scratch_obstack);
+  return output_finalize_message (scratch_buffer);
 }
 
 static const char *
-assop_to_string (p, v)
-     enum tree_code p;
-     int v ATTRIBUTE_UNUSED;
+assop_to_string (enum tree_code p, int v ATTRIBUTE_UNUSED)
 {
-  static char buf[] = "operator                ";
+  tree id;
 
-  if (p == 0)
-    return "{unknown}";
-  
-  strcpy (buf + 9, assignop_tab [p]);
-  return buf;
+  id = assignment_operator_name_info[(int) p].identifier;
+  return id ? IDENTIFIER_POINTER (id) : "{unknown}";
 }
 
 static const char *
-args_to_string (p, verbose)
-     tree p;
-     int verbose;
+args_to_string (tree p, int verbose)
 {
-  enum tree_string_flags flags = 0;
+  int flags = 0;
   if (verbose)
-    flags |= TS_AGGR_TAGS;
-  
+    flags |= TFF_CLASS_KEY_OR_ENUM;
+
   if (p == NULL_TREE)
     return "";
 
-  if (TREE_CODE_CLASS (TREE_CODE (TREE_VALUE (p))) == 't')
+  if (TYPE_P (TREE_VALUE (p)))
     return type_as_string (p, flags);
 
-  OB_INIT ();
+  reinit_global_formatting_buffer ();
   for (; p; p = TREE_CHAIN (p))
     {
       if (TREE_VALUE (p) == null_node)
-       OB_PUTS ("NULL");
+       print_identifier (scratch_buffer, "NULL");
       else
        dump_type (error_type (TREE_VALUE (p)), flags);
       if (TREE_CHAIN (p))
-       OB_PUTS (", ");
+       separate_with_comma (scratch_buffer);
     }
-  OB_FINISH ();
-  return (char *)obstack_base (&scratch_obstack);
+  return output_finalize_message (scratch_buffer);
 }
 
 static const char *
-cv_to_string (p, v)
-     tree p;
-     int v ATTRIBUTE_UNUSED;
+cv_to_string (tree p, int v)
 {
-  OB_INIT ();
+  reinit_global_formatting_buffer ();
 
-  dump_qualifiers (p, before);
+  dump_qualifiers (p, v ? before : none);
 
-  OB_FINISH ();
+  return output_finalize_message (scratch_buffer);
+}
 
-  return (char *)obstack_base (&scratch_obstack);
+/* Langhook for print_error_function.  */
+void
+cxx_print_error_function (diagnostic_context *context, const char *file)
+{
+  lhd_print_error_function (context, file);
+  output_set_prefix (&context->buffer, file);
+  maybe_print_instantiation_context (context);
+}
+
+static void
+cp_diagnostic_starter (diagnostic_context *context,
+                       diagnostic_info *diagnostic)
+{
+  diagnostic_report_current_module (context);
+  cp_print_error_function (context, diagnostic);
+  maybe_print_instantiation_context (context);
+  output_set_prefix (&context->buffer, diagnostic_build_prefix (diagnostic));
+}
+
+static void
+cp_diagnostic_finalizer (diagnostic_context *context,
+                         diagnostic_info *diagnostic ATTRIBUTE_UNUSED)
+{
+  output_destroy_prefix (&context->buffer);
+}
+
+/* Print current function onto BUFFER, in the process of reporting
+   a diagnostic message.  Called from cp_diagnostic_starter.  */
+static void
+cp_print_error_function (diagnostic_context *context,
+                         diagnostic_info *diagnostic)
+{
+  if (diagnostic_last_function_changed (context))
+    {
+      const char *old_prefix = output_prefix (&context->buffer);
+      char *new_prefix = diagnostic->location.file
+        ? file_name_as_prefix (diagnostic->location.file)
+        : NULL;
+
+      output_set_prefix (&context->buffer, new_prefix);
+
+      if (current_function_decl == NULL)
+        output_add_string (&context->buffer, "At global scope:");
+      else
+        output_printf (&context->buffer, "In %s `%s':",
+                       function_category (current_function_decl),
+                       cxx_printable_name (current_function_decl, 2));
+      output_add_newline (&context->buffer);
+
+      diagnostic_set_last_function (context);
+      output_destroy_prefix (&context->buffer);
+      context->buffer.state.prefix = old_prefix;
+    }
+}
+
+/* Returns a description of FUNCTION using standard terminology.  */
+static const char *
+function_category (tree fn)
+{
+  if (DECL_FUNCTION_MEMBER_P (fn))
+    {
+      if (DECL_STATIC_FUNCTION_P (fn))
+        return "static member function";
+      else if (DECL_COPY_CONSTRUCTOR_P (fn))
+        return "copy constructor";
+      else if (DECL_CONSTRUCTOR_P (fn))
+        return "constructor";
+      else if (DECL_DESTRUCTOR_P (fn))
+        return "destructor";
+      else
+        return "member function";
+    }
+  else
+    return "function";
+}
+
+/* Report the full context of a current template instantiation,
+   onto BUFFER.  */
+static void
+print_instantiation_full_context (diagnostic_context *context)
+{
+  tree p = current_instantiation ();
+  int line = lineno;
+  const char *file = input_filename;
+
+  if (p)
+    {
+      if (current_function_decl != TINST_DECL (p)
+         && current_function_decl != NULL_TREE)
+       /* We can get here during the processing of some synthesized
+          method.  Then, TINST_DECL (p) will be the function that's causing
+          the synthesis.  */
+       ;
+      else
+       {
+         if (current_function_decl == TINST_DECL (p))
+           /* Avoid redundancy with the the "In function" line.  */;
+         else
+           output_verbatim (&context->buffer,
+                             "%s: In instantiation of `%s':\n", file,
+                             decl_as_string (TINST_DECL (p),
+                                             TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
+
+         line = TINST_LINE (p);
+         file = TINST_FILE (p);
+         p = TREE_CHAIN (p);
+       }
+    }
+
+  print_instantiation_partial_context (context, p, file, line);
+}
+
+/* Same as above but less verbose.  */
+static void
+print_instantiation_partial_context (diagnostic_context *context,
+                                     tree t, const char *file, int line)
+{
+  for (; t; t = TREE_CHAIN (t))
+    {
+      output_verbatim
+        (&context->buffer, "%s:%d:   instantiated from `%s'\n", file, line,
+         decl_as_string (TINST_DECL (t), TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
+      line = TINST_LINE (t);
+      file = TINST_FILE (t);
+    }
+  output_verbatim (&context->buffer, "%s:%d:   instantiated from here\n", file, line);
+}
+
+/* Called from cp_thing to print the template context for an error.  */
+static void
+maybe_print_instantiation_context (diagnostic_context *context)
+{
+  if (!problematic_instantiation_changed () || current_instantiation () == 0)
+    return;
+
+  record_last_problematic_instantiation ();
+  print_instantiation_full_context (context);
+}
+
+/* Report the bare minimum context of a template instantiation.  */
+void
+print_instantiation_context (void)
+{
+  print_instantiation_partial_context
+    (global_dc, current_instantiation (), input_filename, lineno);
+  diagnostic_flush_buffer (global_dc);
+}
+\f
+/* Called from output_format -- during diagnostic message processing --
+   to handle C++ specific format specifier with the following meanings:
+   %A   function argument-list.
+   %C  tree code.
+   %D   declaration.
+   %E   expression.
+   %F   function declaration.
+   %L  language as used in extern "lang".
+   %O  binary operator.
+   %P   function parameter whose position is indicated by an integer.
+   %Q  assignment operator.
+   %T   type.
+   %V   cv-qualifier.  */
+static bool
+cp_printer (output_buffer *buffer, text_info *text)
+{
+  int verbose = 0;
+  const char *result;
+#define next_tree    va_arg (*text->args_ptr, tree)
+#define next_tcode   va_arg (*text->args_ptr, enum tree_code)
+#define next_lang    va_arg (*text->args_ptr, enum languages)
+#define next_int     va_arg (*text->args_ptr, int)
+
+  if (*text->format_spec == '+')
+    ++text->format_spec;
+  if (*text->format_spec == '#')
+    {
+      verbose = 1;
+      ++text->format_spec;
+    }
+
+  switch (*text->format_spec)
+    {
+    case 'A': result = args_to_string (next_tree, verbose);    break;
+    case 'C': result = code_to_string (next_tcode, verbose);   break;
+    case 'D': result = decl_to_string (next_tree, verbose);    break;
+    case 'E': result = expr_to_string (next_tree, verbose);    break;
+    case 'F': result = fndecl_to_string (next_tree, verbose);  break;
+    case 'L': result = language_to_string (next_lang, verbose); break;
+    case 'O': result = op_to_string (next_tcode, verbose);     break;
+    case 'P': result = parm_to_string (next_int, verbose);     break;
+    case 'Q': result = assop_to_string (next_tcode, verbose);  break;
+    case 'T': result = type_to_string (next_tree, verbose);    break;
+    case 'V': result = cv_to_string (next_tree, verbose);      break;
+    default:
+      return false;
+    }
+
+  output_add_string (buffer, result);
+  return true;
+#undef next_tree
+#undef next_tcode
+#undef next_lang
+#undef next_int
+}
+
+static void
+print_integer (output_buffer *buffer, HOST_WIDE_INT i)
+{
+  sprintf (digit_buffer, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) i);
+  output_add_string (buffer, digit_buffer);
+}
+
+static void
+print_non_consecutive_character (output_buffer *buffer, int c)
+{
+  const char *p = output_last_position (buffer);
+
+  if (p != NULL && *p == c)
+    output_add_space (buffer);
+  output_add_character (buffer, c);
+}
+
+/* These are temporary wrapper functions which handle the historic
+   behavior of cp_*_at.  */
+
+static tree
+locate_error (const char *msgid, va_list ap)
+{
+  tree here = 0, t;
+  int plus = 0;
+  const char *f;
+
+  for (f = msgid; *f; f++)
+    {
+      plus = 0;
+      if (*f == '%')
+       {
+         f++;
+         if (*f == '+')
+           f++, plus = 1;
+         if (*f == '#')
+           f++;
+
+         switch (*f)
+           {
+             /* Just ignore these possibilities.  */
+           case '%':                                           break;
+           case 'd':   (void) va_arg (ap, int);                break;
+           case 's':   (void) va_arg (ap, char *);             break;
+           case 'L':   (void) va_arg (ap, enum languages);     break;
+           case 'C':
+           case 'O':
+           case 'Q':   (void) va_arg (ap, enum tree_code);     break;
+
+             /* These take a tree, which may be where the error is
+                located.  */
+           case 'A':
+           case 'D':
+           case 'E':
+           case 'F':
+           case 'P':
+           case 'T':
+           case 'V':
+             t = va_arg (ap, tree);
+             if (!here || plus)
+               here = t;
+             break;
+
+           default:
+             errorcount = 0;  /* damn ICE suppression */
+             internal_error ("unexpected letter `%c' in locate_error\n", *f);
+           }
+       }
+    }
+
+  if (here == 0)
+    here = va_arg (ap, tree);
+
+  return here;
+}
+
+
+void
+cp_error_at VPARAMS ((const char *msgid, ...))
+{
+  tree here;
+  diagnostic_info diagnostic;
+
+  VA_OPEN (ap, msgid);
+  VA_FIXEDARG (ap, const char *, msgid);
+  here = locate_error (msgid, ap);
+  VA_CLOSE (ap);
+
+  VA_OPEN (ap, msgid);
+  VA_FIXEDARG (ap, const char *, msgid);
+
+  diagnostic_set_info (&diagnostic, msgid, &ap,
+                       cp_file_of (here), cp_line_of (here), DK_ERROR);
+  report_diagnostic (&diagnostic);
+  VA_CLOSE (ap);
+}
+
+void
+cp_warning_at VPARAMS ((const char *msgid, ...))
+{
+  tree here;
+  diagnostic_info diagnostic;
+
+  VA_OPEN (ap, msgid);
+  VA_FIXEDARG (ap, const char *, msgid);
+  here = locate_error (msgid, ap);
+  VA_CLOSE (ap);
+
+  VA_OPEN (ap, msgid);
+  VA_FIXEDARG (ap, const char *, msgid);
+
+  diagnostic_set_info (&diagnostic, msgid, &ap,
+                       cp_file_of (here), cp_line_of (here), DK_WARNING);
+  report_diagnostic (&diagnostic);
+  VA_CLOSE (ap);
+}
+
+void
+cp_pedwarn_at VPARAMS ((const char *msgid, ...))
+{
+  tree here;
+  diagnostic_info diagnostic;
+
+  VA_OPEN (ap, msgid);
+  VA_FIXEDARG (ap, const char *, msgid);
+  here = locate_error (msgid, ap);
+  VA_CLOSE (ap);
+
+  VA_OPEN (ap, msgid);
+  VA_FIXEDARG (ap, const char *, msgid);
+
+  diagnostic_set_info (&diagnostic, msgid, &ap,
+                       cp_file_of (here), cp_line_of (here),
+                       pedantic_error_kind());
+  report_diagnostic (&diagnostic);
+  VA_CLOSE (ap);
 }