Augment stringification of trees.
authorNathan Sidwell <nathan@acm.org>
Mon, 27 Sep 1999 08:26:00 +0000 (08:26 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Mon, 27 Sep 1999 08:26:00 +0000 (08:26 +0000)
* cp-tree.h (tree_string_flags): New error stringifying enumeration.
(fndecl_as_string, type_as_string_real, args_as_string,
code_as_string, language_as_string, parm_as_string,
op_as_string, assop_as_string, cv_as_string): Remove.
(type_as_string, decl_as_string, expr_as_string): Adjust prototype.
(context_as_string): Declare new function.
* error.c (cp_printers): Move definition.
(OB_UNPUT): Remove.
(OB_END_TEMPLATE_ID): Adjust.
(interesting_scope_p): Remove.
(dump_scope): New static function.
(dump_qualifiers): Adjust prototype, reimplement.
(dump_template_value): Use tree_string_flags.
(dump_type_real): Move back to dump_type.
(dump_type): Adjust prototype. Use tree_string_flags.
(dump_aggr_type): Likewise. Use dump_template_parms.
(dump_type_prefix): Adjust prototype. Use tree_string_flags. Return pad flag.
(dump_type_suffix): Adjust prototype. Use tree_string_flags.
(dump_simple_decl): Likewise.
(dump_decl): Likewise. Use dump_template_decl.
(dump_template_decl): New static function broken out of dump_decl.
(dump_function_decl): Adjust prototype. Use tree_string_flags.
(dump_parameters): Likewise. Prefix space.
(dump_exception_spec): Adjust prototype. Use tree_string_flags.
(dump_function_name): Likewise. Use dump_template_parms.
(dump_template_parms): New static function broken out of
dump_function_name.
(dump_expr_list): Adjust prototype. Use tree_string_flags.
(dump_expr): Likewise.
(fndecl_as_string): Removed
(type_as_string_real): Removed
(dump_binary_op): Adjust prototype. Use tree_string_flags.
(dump_unary_op): Likewise.
(type_as_string): Likewise.
(expr_as_string): Likewise.
(decl_as_string): Likewise.
(context_as_string): New function.
(lang_decl_name): Adjust.
(decl_to_string): New static print callback.
(expr_to_string): Likewise.
(fndecl_to_string): Likewise.
(code_as_string): Renamed to ...
(code_to_string): ... here. Adjust.
(language_as_string): Renamed to ...
(language_to_string): ... here. Adjust.
(parm_as_string): Renamed to ...
(parm_to_string): ... here.
(op_as_string): Renamed to ...
(op_to_string): ... here.
(assop_as_string): Renamed to ...
(assop_to_string): ... here.
(type_to_string): New static print callback.
(args_as_string): Renamed to ...
(args_to_string): ... here. Adjust.
(cv_as_string): Renamed to ...
(cv_to_string): ... here. Adjust.
* pt.c (mangle_class_name_for_template): Use tree_string_flags.
(print_template_context): Likewise.

From-SVN: r29673

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/error.c
gcc/cp/pt.c

index 19e4dd3..fa5f56b 100644 (file)
@@ -1,3 +1,65 @@
+1999-09-27  Nathan Sidwell  <nathan@acm.org>
+
+       Augment stringification of trees.
+       * cp-tree.h (tree_string_flags): New error stringifying enumeration.
+       (fndecl_as_string, type_as_string_real, args_as_string,
+       code_as_string, language_as_string, parm_as_string,
+       op_as_string, assop_as_string, cv_as_string): Remove.
+       (type_as_string, decl_as_string, expr_as_string): Adjust prototype.
+       (context_as_string): Declare new function.
+       * error.c (cp_printers): Move definition.
+       (OB_UNPUT): Remove.
+       (OB_END_TEMPLATE_ID): Adjust.
+       (interesting_scope_p): Remove.
+       (dump_scope): New static function.
+       (dump_qualifiers): Adjust prototype, reimplement.
+       (dump_template_value): Use tree_string_flags.
+       (dump_type_real): Move back to dump_type.
+       (dump_type): Adjust prototype. Use tree_string_flags.
+       (dump_aggr_type): Likewise. Use dump_template_parms.
+       (dump_type_prefix): Adjust prototype. Use tree_string_flags. Return pad flag.
+       (dump_type_suffix): Adjust prototype. Use tree_string_flags.
+       (dump_simple_decl): Likewise.
+       (dump_decl): Likewise. Use dump_template_decl.
+       (dump_template_decl): New static function broken out of dump_decl.
+       (dump_function_decl): Adjust prototype. Use tree_string_flags.
+       (dump_parameters): Likewise. Prefix space.
+       (dump_exception_spec): Adjust prototype. Use tree_string_flags.
+       (dump_function_name): Likewise. Use dump_template_parms.
+       (dump_template_parms): New static function broken out of
+       dump_function_name.
+       (dump_expr_list): Adjust prototype. Use tree_string_flags.
+       (dump_expr): Likewise.
+       (fndecl_as_string): Removed
+       (type_as_string_real): Removed
+       (dump_binary_op): Adjust prototype. Use tree_string_flags.
+       (dump_unary_op): Likewise.
+       (type_as_string): Likewise.
+       (expr_as_string): Likewise.
+       (decl_as_string): Likewise.
+       (context_as_string): New function.
+       (lang_decl_name): Adjust.
+       (decl_to_string): New static print callback.
+       (expr_to_string): Likewise.
+       (fndecl_to_string): Likewise.
+       (code_as_string): Renamed to ...
+       (code_to_string): ... here. Adjust.
+       (language_as_string): Renamed to ...
+       (language_to_string): ... here. Adjust.
+       (parm_as_string): Renamed to ...
+       (parm_to_string): ... here.
+       (op_as_string): Renamed to ...
+       (op_to_string): ... here.
+       (assop_as_string): Renamed to ...
+       (assop_to_string): ... here.
+       (type_to_string): New static print callback.
+       (args_as_string): Renamed to ...
+       (args_to_string): ... here. Adjust.
+       (cv_as_string): Renamed to ...
+       (cv_to_string): ... here. Adjust.
+       * pt.c (mangle_class_name_for_template): Use tree_string_flags.
+       (print_template_context): Likewise.
+
 1999-09-26  Mark Mitchell  <mark@codesourcery.com>
 
        * cp-tree.h (expand_throw): Remove prototype.
index 3abea7d..9202354 100644 (file)
@@ -3122,6 +3122,30 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
 #define TEMPLATE_TYPE_DECL(NODE) \
   (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 
+/* Control stringification of trees (types, decls & exprs).
+   Bit or them together.  */
+enum tree_string_flags
+{
+    TS_PLAIN,                    /* nothing special */
+    TS_CHASE_TYPEDEFS = 1 <<  0, /* look through typedefs */
+    TS_DECORATE       = 1 <<  1, /* decorate things */
+    TS_FUNC_NORETURN  = 1 <<  2, /* inhibit function return type */
+    TS_FUNC_THROW     = 1 <<  3, /* show throw spec */
+    TS_PARM_DEFAULTS  = 1 <<  4, /* show parm defaults */
+    TS_EXPR_PARENS    = 1 <<  5, /* enclose in parens */
+    TS_AGGR_TAGS      = 1 <<  6, /* show struct tags */
+    TS_DECL_TYPE      = 1 <<  7, /* show decl's type */
+    TS_FUNC_SCOPE     = 1 <<  8, /* show function scope */
+    TS_PEDANTIC_NAME  = 1 <<  9, /* pedantically name things */
+    TS_TEMPLATE_PREFIX= 1 << 10, /* show template <parms> prefix */
+    
+    /* Internal use flags */
+    TS_TEMPLATE_PARM  = 1 << 11, /* decl is really a non-type template parm */
+    TS_TEMPLATE_PLAIN = 1 << 12, /* don't decorate primary template_name */
+    
+    TS_NEXT_BIT       = 13       /* next available bit */
+};
+
 /* in lex.c  */
 /* Indexed by TREE_CODE, these tables give C-looking names to
    operators represented by TREE_CODES.  For example,
@@ -3430,18 +3454,10 @@ extern void cp_deprecated                       PROTO((const char*));
 
 /* in error.c */
 extern void init_error                         PROTO((void));
-extern const char *fndecl_as_string            PROTO((tree, int));
-extern const char *type_as_string              PROTO((tree, int));
-extern const char *type_as_string_real         PROTO((tree, int, int));
-extern const char *args_as_string              PROTO((tree, int));
-extern const char *decl_as_string              PROTO((tree, int));
-extern const char *expr_as_string              PROTO((tree, int));
-extern const char *code_as_string              PROTO((enum tree_code, int));
-extern const char *language_as_string          PROTO((enum languages, int));
-extern const char *parm_as_string              PROTO((int, int));
-extern const char *op_as_string                        PROTO((enum tree_code, int));
-extern const char *assop_as_string             PROTO((enum tree_code, int));
-extern const char *cv_as_string                        PROTO((tree, int));
+extern const char *type_as_string              PROTO((tree, enum tree_string_flags));
+extern const char *decl_as_string              PROTO((tree, enum tree_string_flags));
+extern const char *expr_as_string              PROTO((tree, enum tree_string_flags));
+extern const char *context_as_string            PROTO((tree, enum tree_string_flags));
 extern const char *lang_decl_name              PROTO((tree, int));
 extern const char *cp_file_of                  PROTO((tree));
 extern int cp_line_of                          PROTO((tree));
index 883a2e5..fc64cab 100644 (file)
@@ -28,43 +28,6 @@ Boston, MA 02111-1307, USA.  */
 
 typedef const char *cp_printer ();
 
-#define A args_as_string
-#define C code_as_string
-#define D decl_as_string
-#define E expr_as_string
-#define F fndecl_as_string
-#define L language_as_string
-#define O op_as_string
-#define P parm_as_string
-#define Q assop_as_string
-#define T type_as_string
-#define V cv_as_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 obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
@@ -84,39 +47,88 @@ static char *scratch_firstobj;
 # 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_UNPUT(N) obstack_blank (&scratch_obstack, - (N));
 
 # define OB_END_TEMPLATE_ID()                                              \
-  ((obstack_next_free (&scratch_obstack) != obstack_base (&scratch_obstack) \
+  (((obstack_next_free (&scratch_obstack) != obstack_base (&scratch_obstack) \
     && obstack_next_free (&scratch_obstack)[-1] == '>')                            \
-   ? OB_PUTC2 (' ', '>') : OB_PUTC ('>'))
+   ? OB_PUTC (' ') : (void)0), OB_PUTC ('>'))
 
 # define NEXT_CODE(t) (TREE_CODE (TREE_TYPE (t)))
 
 enum pad { none, before, after };
 
-static void dump_type PROTO((tree, int));
-static void dump_type_real PROTO((tree, int, int));
-static void dump_simple_decl PROTO((tree, tree, int));
-static void dump_decl PROTO((tree, int));
-static void dump_function_decl PROTO((tree, int));
-static void dump_expr PROTO((tree, int));
-static void dump_unary_op PROTO((const char *, tree, int));
-static void dump_binary_op PROTO((const char *, tree));
-static void dump_aggr_type PROTO((tree, int, int));
-static void dump_type_prefix PROTO((tree, int, int));
-static void dump_type_suffix PROTO((tree, int, int));
-static void dump_function_name PROTO((tree));
-static void dump_expr_list PROTO((tree));
+static const char *args_to_string              PROTO((tree, int));
+static const char *assop_to_string             PROTO((enum tree_code, int));
+static const char *code_to_string              PROTO((enum tree_code, int));
+static const char *cv_to_string                        PROTO((tree, int));
+static const char *decl_to_string              PROTO((tree, int));
+static const char *expr_to_string              PROTO((tree, int));
+static const char *fndecl_to_string            PROTO((tree, int));
+static const char *language_to_string          PROTO((enum languages, int));
+static const char *op_to_string                        PROTO((enum tree_code, int));
+static const char *parm_to_string              PROTO((int, int));
+static const char *type_to_string              PROTO((tree, int));
+
+static void dump_type PROTO((tree, enum tree_string_flags));
+static void dump_simple_decl PROTO((tree, tree, enum tree_string_flags));
+static void dump_decl PROTO((tree, enum tree_string_flags));
+static void dump_template_decl PROTO((tree, enum tree_string_flags));
+static void dump_function_decl PROTO((tree, enum tree_string_flags));
+static void dump_expr PROTO((tree, enum tree_string_flags));
+static void dump_unary_op PROTO((const char *, tree, enum tree_string_flags));
+static void dump_binary_op PROTO((const char *, tree, enum tree_string_flags));
+static void dump_aggr_type PROTO((tree, enum tree_string_flags));
+static enum pad dump_type_prefix PROTO((tree, enum tree_string_flags));
+static void dump_type_suffix PROTO((tree, enum tree_string_flags));
+static void dump_function_name PROTO((tree, enum tree_string_flags));
+static void dump_expr_list PROTO((tree, enum tree_string_flags));
 static void dump_global_iord PROTO((tree));
-static void dump_qualifiers PROTO((tree, enum pad));
+static enum pad dump_qualifiers PROTO((tree, enum pad));
 static void dump_char PROTO((int));
-static void dump_parameters PROTO((tree, int, int));
-static void dump_exception_spec PROTO((tree, int));
+static void dump_parameters PROTO((tree, enum tree_string_flags));
+static void dump_exception_spec PROTO((tree, enum tree_string_flags));
 static const char *aggr_variety PROTO((tree));
 static tree ident_fndecl PROTO((tree));
-static int interesting_scope_p PROTO((tree));
-static void dump_template_value PROTO((tree, int, int));
+static void dump_template_value PROTO((tree, enum tree_string_flags));
+static void dump_scope PROTO((tree, enum tree_string_flags));
+static void dump_template_parms PROTO((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
 
 void
 init_error ()
@@ -125,92 +137,102 @@ init_error ()
   scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0);
 }
 
-/* Returns nonzero if SCOPE is something we want to print for random decls.  */
+/* Dump a scope, if deemed necessary.  */
 
-static int
-interesting_scope_p (scope)
+static void
+dump_scope (scope, flags)
      tree scope;
+     enum tree_string_flags flags;
 {
-  if (scope == NULL_TREE
-      || scope == global_namespace)
-    return 0;
-
-  return (TREE_CODE (scope) == NAMESPACE_DECL
-         || AGGREGATE_TYPE_P (scope));
+  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 ("::");
+        }
+      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 ("::");
+    }
+  else if ((flags & (TS_PEDANTIC_NAME | TS_FUNC_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 ("::");
+    }
 }
 
-static void
+/* Dump type qualifiers, providing padding as requested. Return an
+   indication of whether we dumped something.  */
+
+static enum pad
 dump_qualifiers (t, p)
      tree t;
      enum pad p;
 {
-  if (TYPE_QUALS (t))
+  static const int masks[] =
+    {TYPE_QUAL_CONST, TYPE_QUAL_VOLATILE, TYPE_QUAL_RESTRICT};
+  static const char *const names[] =
+    {"const", "volatile", "__restrict"};
+  int ix;
+  int quals = TYPE_QUALS (t);
+  int do_after = p == after;
+  
+  if (quals)
     {
-      if (p == before) OB_PUTC (' ');
-      switch (TYPE_QUALS (t))
-       {
-       case TYPE_QUAL_CONST:
-         OB_PUTS ("const");
-         break;
-
-       case TYPE_QUAL_VOLATILE:
-         OB_PUTS ("volatile");
-         break;
-
-       case TYPE_QUAL_RESTRICT:
-         OB_PUTS ("__restrict");
-         break;
-
-       case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
-         OB_PUTS ("const volatile");
-         break;
-
-       case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
-         OB_PUTS ("const __restrict");
-         break;
-
-       case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
-         OB_PUTS ("volatile __restrict");
-         break;
-
-       case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
-         OB_PUTS ("const volatile __restrict");
-         break;
-
-       default:
-         my_friendly_abort (0);
-       }
-      if (p == after) OB_PUTC (' ');
+      for (ix = 0; ix != 3; ix++)
+        if (masks[ix] & quals)
+          {
+            if (p == before)
+              OB_PUTC (' ');
+            p = before;
+            OB_PUTCP (names[ix]);
+          }
+      if (do_after)
+        OB_PUTC (' ');
     }
+  else
+    p = none;
+  return p;
 }
 
 /* This must be large enough to hold any printed integer or floating-point
    value.  */
 static char digit_buffer[128];
 
-/* Dump a template parameter or template argument VALUE at VERBOSITY
-   level.  The boolean CANONICAL_NAME indicates whether to dump abstract
-   names, e.g. typedefs, or not. */
+/* Dump a template parameter or template argument VALUE under
+   control of FLAGS. */
 
 static void
-dump_template_value (value, verbosity, canonical_name)
+dump_template_value (value, flags)
      tree value;
-     int verbosity, canonical_name;
+     enum tree_string_flags flags;
 {
   if (TREE_CODE_CLASS (TREE_CODE (value)) == 't'
       || TREE_CODE (value) == TEMPLATE_DECL)
-    dump_type_real (value, verbosity, canonical_name);
+    dump_type (value, flags & ~TS_AGGR_TAGS);
   else
-    dump_expr (value, verbosity);
+    dump_expr (value, (flags | TS_EXPR_PARENS) & ~TS_AGGR_TAGS);
 }
 
-/* Dump into the obstack a human-readable equivalent of TYPE.  */
+/* Dump into the obstack a human-readable equivalent of TYPE.  FLAGS
+   controls the format.  */
 
 static void
-dump_type_real (t, v, canonical_name)
+dump_type (t, flags)
      tree t;
-     int v;                    /* verbose? */
-     int canonical_name;
+     enum tree_string_flags flags;
 {
   if (t == NULL_TREE)
     return;
@@ -220,17 +242,13 @@ dump_type_real (t, v, canonical_name)
 
   switch (TREE_CODE (t))
     {
-    case ERROR_MARK:
-      OB_PUTS ("{error}");
-      break;
-
     case UNKNOWN_TYPE:
       OB_PUTS ("{unknown type}");
       break;
 
     case TREE_LIST:
       /* A list of function parms.  */
-      dump_parameters (t, 0, canonical_name);
+      dump_parameters (t, flags);
       break;
 
     case IDENTIFIER_NODE:
@@ -238,24 +256,32 @@ dump_type_real (t, v, canonical_name)
       break;
 
     case TREE_VEC:
-      dump_type_real (BINFO_TYPE (t), v, canonical_name);
+      dump_type (BINFO_TYPE (t), flags);
       break;
 
     case RECORD_TYPE:
     case UNION_TYPE:
     case ENUMERAL_TYPE:
-      dump_aggr_type (t, v, canonical_name);
+      dump_aggr_type (t, flags);
       break;
 
     case TYPE_DECL:
+      if (flags & TS_CHASE_TYPEDEFS)
+        {
+          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, v);
+      dump_decl (t, flags & ~TS_DECL_TYPE);
       break;
-
+    
     case COMPLEX_TYPE:
       OB_PUTS ("complex ");
-      dump_type_real (TREE_TYPE (t), v, canonical_name);
+      dump_type (TREE_TYPE (t), flags);
       break;
 
     case INTEGER_TYPE:
@@ -271,7 +297,7 @@ dump_type_real (t, v, canonical_name)
       {
        tree type;
        dump_qualifiers (t, after);
-       type = canonical_name ? TYPE_MAIN_VARIANT (t) : t;
+       type = flags & TS_CHASE_TYPEDEFS ? TYPE_MAIN_VARIANT (t) : t;
        if (TYPE_NAME (type) && TYPE_IDENTIFIER (type))
          OB_PUTID (TYPE_IDENTIFIER (type));
        else
@@ -299,9 +325,10 @@ dump_type_real (t, v, canonical_name)
          OB_PUTC ('<');
          for (i = 0; i < TREE_VEC_LENGTH (args); i++)
            {
-              dump_template_value (TREE_VEC_ELT (args, i), 0, canonical_name);
-             if (i < TREE_VEC_LENGTH (args)-1)
-               OB_PUTC2 (',', ' ');
+             tree arg = TREE_VEC_ELT (args, i);
+             if (i)
+               OB_PUTS (", ");
+             dump_template_value (arg, flags);
            }
          OB_END_TEMPLATE_ID ();
        }
@@ -324,29 +351,37 @@ dump_type_real (t, v, canonical_name)
     offset_type:
     case FUNCTION_TYPE:
     case METHOD_TYPE:
-      dump_type_prefix (t, v, canonical_name);
-      dump_type_suffix (t, v, canonical_name);
+    {
+      dump_type_prefix (t, flags);
+      dump_type_suffix (t, flags);
       break;
-
+    }
     case TYPENAME_TYPE:
       OB_PUTS ("typename ");
-      dump_type_real (TYPE_CONTEXT (t), 0, canonical_name);
+      dump_type (TYPE_CONTEXT (t), flags);
       OB_PUTS ("::");
-      dump_decl (TYPENAME_TYPE_FULLNAME (t), v);
+      dump_decl (TYPENAME_TYPE_FULLNAME (t), flags);
       break;
 
     case TYPEOF_TYPE:
       OB_PUTS ("__typeof (");
-      dump_expr (TYPE_FIELDS (t), 1);
+      dump_expr (TYPE_FIELDS (t), flags & ~TS_EXPR_PARENS);
       OB_PUTC (')');
       break;
 
     default:
       sorry ("`%s' not supported by dump_type",
             tree_code_name[(int) TREE_CODE (t)]);
+      /* Fall through to error. */
+
+    case ERROR_MARK:
+      OB_PUTS ("{typeerror}");
+      break;
     }
 }
 
+/* Return the name of the supplied aggregate, or enumeral type.  */
+
 static const char *
 aggr_variety (t)
      tree t;
@@ -361,50 +396,59 @@ aggr_variety (t)
     return "struct";
 }
 
-static void
-dump_type (t, v)
-     tree t;
-     int v;                    /* verbose? */
-{
-  dump_type_real (t, v, 0);
-}
-
-/* Print out a class declaration, in the form `class foo'.  */
+/* Print out a class declaration T under the control of FLAGS,
+   in the form `class foo'.  */
 
 static void
-dump_aggr_type (t, v, canonical_name)
+dump_aggr_type (t, flags)
      tree t;
-     int v;                    /* verbose? */
-     int canonical_name;
+     enum tree_string_flags flags;
 {
   tree name;
   const char *variety = aggr_variety (t);
+  int typdef = 0;
+  int tmplate = 0;
 
   dump_qualifiers (t, after);
 
-  if (v > 0)
+  if (flags & TS_AGGR_TAGS)
     {
       OB_PUTCP (variety);
       OB_PUTC (' ');
     }
   
-  name = TYPE_NAME (canonical_name ? TYPE_MAIN_VARIANT (t) : t);
+  if (flags & TS_CHASE_TYPEDEFS)
+    t = TYPE_MAIN_VARIANT (t);
 
-  if (name && CP_DECL_CONTEXT (name) != global_namespace)
+  name = TYPE_NAME (t);
+
+  if (name)
     {
-      /* FUNCTION_DECL or RECORD_TYPE */
-      dump_decl (DECL_CONTEXT (name), 0);
-      OB_PUTC2 (':', ':');
+      typdef = !DECL_ARTIFICIAL (name);
+      tmplate = !typdef && TREE_CODE (t) != ENUMERAL_TYPE
+                && TYPE_LANG_SPECIFIC (t) && CLASSTYPE_TEMPLATE_INFO (t)
+                && (CLASSTYPE_TEMPLATE_SPECIALIZATION (t)
+                    || 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);
+      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;
+        }
+      name = DECL_NAME (name);
     }
 
-  /* kludge around weird behavior on g++.brendan/line1.C */
-  if (name && TREE_CODE (name) != IDENTIFIER_NODE)
-    name = DECL_NAME (name);
-
   if (name == 0 || ANON_AGGRNAME_P (name))
     {
       OB_PUTS ("{anonymous");
-      if (!v)
+      if (!(flags & TS_AGGR_TAGS))
        {
          OB_PUTC (' ');
          OB_PUTCP (variety);
@@ -413,6 +457,10 @@ dump_aggr_type (t, v, canonical_name)
     }
   else
     OB_PUTID (name);
+  if (tmplate)
+    dump_template_parms (TYPE_TEMPLATE_INFO (t),
+                         !CLASSTYPE_USE_TEMPLATE (t),
+                         flags & ~TS_TEMPLATE_PREFIX);
 }
 
 /* Dump into the obstack the initial part of the output for a given type.
@@ -424,14 +472,18 @@ dump_aggr_type (t, v, canonical_name)
    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 void
-dump_type_prefix (t, v, canonical_name)
+static enum pad
+dump_type_prefix (t, flags)
      tree t;
-     int v;                    /* verbosity */
-     int canonical_name;
+     enum tree_string_flags flags;
 {
+  enum pad padding = before;
+  
   if (TYPE_PTRMEMFUNC_P (t))
     {
       t = TYPE_PTRMEMFUNC_FN_TYPE (t);
@@ -445,73 +497,60 @@ dump_type_prefix (t, v, canonical_name)
       {
        tree sub = TREE_TYPE (t);
        
-       dump_type_prefix (sub, v, canonical_name);
+       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))
          {
-           switch (TREE_CODE (sub))
-             {
-               /* We don't want int ( *)() */
-             case FUNCTION_TYPE:
-             case METHOD_TYPE:
-               break;
-               
-             case ARRAY_TYPE:
-               OB_PUTC2 (' ', '(');
-               break;
-
-             case POINTER_TYPE:
-               /* We don't want "char * *" */
-               if (TYPE_QUALS (sub) == TYPE_UNQUALIFIED)
-                 break;
-               /* But we do want "char *const *" */
-               
-             default:
-               OB_PUTC (' ');
-             }
-           if (TREE_CODE (t) == POINTER_TYPE)
-             OB_PUTC ('*');
-           else
-             OB_PUTC ('&');
-           dump_qualifiers (t, none);
+           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);
          }
       }
       break;
 
     case OFFSET_TYPE:
     offset_type:
-      dump_type_prefix (TREE_TYPE (t), v, canonical_name);
+      padding = dump_type_prefix (TREE_TYPE (t), flags);
       if (TREE_CODE (t) == OFFSET_TYPE)        /* pmfs deal with this in d_t_p */
        {
-         OB_PUTC (' ');
-         dump_type_real (TYPE_OFFSET_BASETYPE (t), 0, canonical_name);
-         OB_PUTC2 (':', ':');
+         if (padding != none)
+           OB_PUTC (' ');
+         dump_type (TYPE_OFFSET_BASETYPE (t), flags);
+         OB_PUTS ("::");
        }
       OB_PUTC ('*');
-      dump_qualifiers (t, none);
+      padding = dump_qualifiers (t, none);
       break;
 
       /* Can only be reached through function pointer -- this would not be
          correct if FUNCTION_DECLs used it.  */
     case FUNCTION_TYPE:
-      dump_type_prefix (TREE_TYPE (t), v, canonical_name);
-      OB_PUTC2 (' ', '(');
+      padding = dump_type_prefix (TREE_TYPE (t), flags);
+      if (padding != none)
+        OB_PUTC (' ');
+      OB_PUTC ('(');
+      padding = none;
       break;
 
     case METHOD_TYPE:
-      dump_type_prefix (TREE_TYPE (t), v, canonical_name);
-      OB_PUTC2 (' ', '(');
-      dump_aggr_type (TYPE_METHOD_BASETYPE (t), 0, canonical_name);
-      OB_PUTC2 (':', ':');
+      padding = dump_type_prefix (TREE_TYPE (t), flags);
+      if (padding != none)
+        OB_PUTC (' ');
+      OB_PUTC ('(');
+      padding = none;
+      dump_aggr_type (TYPE_METHOD_BASETYPE (t), flags);
+      OB_PUTS ("::");
       break;
 
     case ARRAY_TYPE:
-      dump_type_prefix (TREE_TYPE (t), v, canonical_name);
+      padding = dump_type_prefix (TREE_TYPE (t), flags);
       break;
 
     case ENUMERAL_TYPE:
-    case ERROR_MARK:
     case IDENTIFIER_NODE:
     case INTEGER_TYPE:
     case BOOLEAN_TYPE:
@@ -527,20 +566,28 @@ dump_type_prefix (t, v, canonical_name)
     case VOID_TYPE:
     case TYPENAME_TYPE:
     case COMPLEX_TYPE:
-      dump_type_real (t, v, canonical_name);
+      dump_type (t, flags);
+      padding = before;
       break;
       
     default:
       sorry ("`%s' not supported by dump_type_prefix",
             tree_code_name[(int) TREE_CODE (t)]);
+
+    case ERROR_MARK:
+      OB_PUTS ("{typeprefixerror}");
+      break;
     }
+  return padding;
 }
 
+/* Dump the suffix of type T, under control of FLAGS.  This is the part
+   which appears after the identifier (or function parms).  */
+
 static void
-dump_type_suffix (t, v, canonical_name)
+dump_type_suffix (t, flags)
      tree t;
-     int v;                    /* verbose? */
-     int canonical_name;
+     enum tree_string_flags flags;
 {
   if (TYPE_PTRMEMFUNC_P (t))
     t = TYPE_PTRMEMFUNC_FN_TYPE (t);
@@ -552,7 +599,7 @@ dump_type_suffix (t, v, canonical_name)
     case OFFSET_TYPE:
       if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
        OB_PUTC (')');
-      dump_type_suffix (TREE_TYPE (t), v, canonical_name);
+      dump_type_suffix (TREE_TYPE (t), flags);
       break;
 
       /* Can only be reached through function pointer */
@@ -567,13 +614,13 @@ dump_type_suffix (t, v, canonical_name)
 
        /* 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, 0, canonical_name);
+       dump_parameters (arg, flags & ~TS_PARM_DEFAULTS);
 
        if (TREE_CODE (t) == METHOD_TYPE)
          dump_qualifiers
            (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), before);
-       dump_type_suffix (TREE_TYPE (t), v, canonical_name);
-       dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), canonical_name);
+       dump_type_suffix (TREE_TYPE (t), flags);
+       dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags);
        break;
       }
 
@@ -584,18 +631,19 @@ dump_type_suffix (t, v, canonical_name)
          if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == INTEGER_CST)
            OB_PUTI (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) + 1);
          else if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == MINUS_EXPR)
-           dump_expr (TREE_OPERAND (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0), 0);
+           dump_expr (TREE_OPERAND (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0),
+                      flags & ~TS_EXPR_PARENS);
          else
            dump_expr (fold (build_binary_op
                             (PLUS_EXPR, TYPE_MAX_VALUE (TYPE_DOMAIN (t)),
-                             integer_one_node)), 0);
+                             integer_one_node)),
+                      flags & ~TS_EXPR_PARENS);
        }
       OB_PUTC (']');
-      dump_type_suffix (TREE_TYPE (t), v, canonical_name);
+      dump_type_suffix (TREE_TYPE (t), flags);
       break;
       
     case ENUMERAL_TYPE:
-    case ERROR_MARK:
     case IDENTIFIER_NODE:
     case INTEGER_TYPE:
     case BOOLEAN_TYPE:
@@ -616,6 +664,11 @@ dump_type_suffix (t, v, canonical_name)
     default:
       sorry ("`%s' not supported by dump_type_suffix",
             tree_code_name[(int) TREE_CODE (t)]);
+
+    case ERROR_MARK:
+      /* Don't mark it here, we should have already done in
+         dump_type_prefix.  */
+      break;
     }
 }
 
@@ -674,60 +727,57 @@ dump_global_iord (t)
 }
 
 static void
-dump_simple_decl (t, type, v)
+dump_simple_decl (t, type, flags)
      tree t;
      tree type;
-     int v;
+     enum tree_string_flags flags;
 {
-  if (v > 0)
+  if (flags & TS_DECL_TYPE)
     {
-      dump_type_prefix (type, v, 0);
-      OB_PUTC (' ');
-    }
-  if (interesting_scope_p (DECL_CONTEXT (t)))
-    {
-      dump_decl (DECL_CONTEXT (t), 0);
-      OB_PUTC2 (':',':');
+      if (dump_type_prefix (type, flags) != none)
+        OB_PUTC (' ');
     }
+  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), v);
+    dump_decl (DECL_NAME (t), flags);
   else
     OB_PUTS ("{anon}");
-  if (v > 0)
-    dump_type_suffix (type, v, 0);
+  if (flags & TS_DECL_TYPE)
+    dump_type_suffix (type, flags);
 }
 
+/* Dump a human readable string for the decl T under control of FLAGS.  */
+
 static void
-dump_decl (t, v)
+dump_decl (t, flags)
      tree t;
-     int v;                    /* verbosity */
+     enum tree_string_flags flags;
 {
   if (t == NULL_TREE)
     return;
 
   switch (TREE_CODE (t))
     {
-    case ERROR_MARK:
-      OB_PUTS (" /* decl error */ ");
-      break;
-
     case TYPE_DECL:
       {
        /* Don't say 'typedef class A' */
         if (DECL_ARTIFICIAL (t))
          {
-           if (v > 0 && TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
+           if ((flags & TS_DECL_TYPE)
+               && TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
              /* Say `class T' not just `T'. */
              OB_PUTS ("class ");
 
-           dump_type (TREE_TYPE (t), v);
+           dump_type (TREE_TYPE (t), flags);
            break;
          }
       }
-      if (v > 0)
+      if (flags & TS_DECORATE)
        OB_PUTS ("typedef ");
       dump_simple_decl (t, DECL_ORIGINAL_TYPE (t) 
-                       ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t), v);
+                       ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t),
+                       flags);
       break;
       
     case VAR_DECL:
@@ -735,7 +785,7 @@ dump_decl (t, v)
        {
          OB_PUTS ("vtable for ");
          if (TYPE_P (DECL_CONTEXT (t)))
-           dump_type (DECL_CONTEXT (t), v);
+           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
@@ -746,15 +796,11 @@ dump_decl (t, v)
       /* else fall through */
     case FIELD_DECL:
     case PARM_DECL:
-      dump_simple_decl (t, TREE_TYPE (t), v);
+      dump_simple_decl (t, TREE_TYPE (t), flags);
       break;
 
     case NAMESPACE_DECL:
-      if (CP_DECL_CONTEXT (t) != global_namespace)
-       {
-         dump_decl (DECL_CONTEXT (t), v);
-         OB_PUTC2 (':',':');
-       }
+      dump_scope (CP_DECL_CONTEXT (t), flags);
       if (DECL_NAME (t) == anonymous_namespace_name)
        OB_PUTS ("{anonymous}");
       else
@@ -762,24 +808,23 @@ dump_decl (t, v)
       break;
 
     case SCOPE_REF:
-      dump_decl (TREE_OPERAND (t, 0), 0);
+      dump_decl (TREE_OPERAND (t, 0), flags & ~TS_DECL_TYPE);
       OB_PUTS ("::");
-      dump_decl (TREE_OPERAND (t, 1), 0);
+      dump_decl (TREE_OPERAND (t, 1), flags);
       break;      
 
     case ARRAY_REF:
-      dump_decl (TREE_OPERAND (t, 0), v);
+      dump_decl (TREE_OPERAND (t, 0), flags);
       OB_PUTC ('[');
-      dump_decl (TREE_OPERAND (t, 1), v);
+      dump_decl (TREE_OPERAND (t, 1), flags);
       OB_PUTC (']');
       break;
 
-      /* So that we can do dump_decl in dump_aggr_type and have it work for
-        both class and function scope.  */
+      /* So that we can do dump_decl on an aggr type.  */
     case RECORD_TYPE:
     case UNION_TYPE:
     case ENUMERAL_TYPE:
-      dump_type (t, v);
+      dump_type (t, flags);
       break;
 
     case TYPE_EXPR:
@@ -795,13 +840,13 @@ dump_decl (t, v)
            && DECL_LANGUAGE (f) == lang_cplusplus)
          {
            OB_PUTC ('~');
-           dump_decl (DECL_NAME (f), 0);
+           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), 0);
+           dump_type (TREE_TYPE (t), flags);
            break;
          }
        else if (IDENTIFIER_OPNAME_P (t))
@@ -824,77 +869,17 @@ dump_decl (t, v)
        dump_global_iord (DECL_ASSEMBLER_NAME (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);
       else
-       dump_function_decl (t, v);
+        dump_function_decl (t, flags);
       break;
 
     case TEMPLATE_DECL:
-      {
-       tree orig_args = DECL_TEMPLATE_PARMS (t);
-       tree args;
-       int i; 
-       for (args = orig_args = nreverse (orig_args); 
-            args;
-            args = TREE_CHAIN (args))
-         {
-           int len = TREE_VEC_LENGTH (TREE_VALUE (args));
-
-           OB_PUTS ("template <");
-           for (i = 0; i < len; i++)
-             {
-               tree arg = TREE_VEC_ELT (TREE_VALUE (args), i);
-               tree defval = TREE_PURPOSE (arg);
-               arg = TREE_VALUE (arg);
-               if (TREE_CODE (arg) == TYPE_DECL)
-                 {
-                   if (DECL_NAME (arg))
-                     {
-                       OB_PUTS ("class ");
-                       OB_PUTID (DECL_NAME (arg));
-                     }
-                   else
-                     OB_PUTS ("class");
-                 }
-               else
-                 dump_decl (arg, 1);
-               
-               if (defval)
-                 {
-                   OB_PUTS (" = ");
-                   if (TREE_CODE (arg) == TYPE_DECL
-                       || TREE_CODE (arg) == TEMPLATE_DECL)
-                     dump_type (defval, 1);
-                   else
-                     dump_expr (defval, 1);
-                 }
-               
-               OB_PUTC2 (',', ' ');
-             }
-           if (len != 0)
-             OB_UNPUT (2);
-           OB_END_TEMPLATE_ID ();
-           OB_PUTC (' ');
-         }
-       nreverse(orig_args);
-
-       if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
-         dump_type (TREE_TYPE (t), v);
-       else if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL)
-         dump_decl (DECL_TEMPLATE_RESULT (t), v);
-       else if (TREE_TYPE (t) == NULL_TREE)
-          my_friendly_abort (353);
-       else switch (NEXT_CODE (t))
-         {
-         case METHOD_TYPE:
-         case FUNCTION_TYPE:
-           dump_function_decl (t, v);
-           break;
-
-         default:
-           /* This case can occur with some illegal code.  */
-           dump_type (TREE_TYPE (t), v);
-         }
-      }
+      if (flags & TS_PEDANTIC_NAME)
+        dump_template_decl (t, flags | TS_FUNC_NORETURN | TS_DECL_TYPE);
+      else
+        dump_template_decl (t, flags);
       break;
 
     case TEMPLATE_ID_EXPR:
@@ -903,20 +888,20 @@ dump_decl (t, v)
        tree name = TREE_OPERAND (t, 0);
        if (is_overloaded_fn (name))
          name = DECL_NAME (get_first_fn (name));
-       dump_decl (name, v);
+       dump_decl (name, flags);
        OB_PUTC ('<');
        for (args = TREE_OPERAND (t, 1); args; args = TREE_CHAIN (args))
          {
-            dump_template_value (TREE_VALUE (args), 0, 0);
+           dump_template_value (TREE_VALUE (args), flags);
            if (TREE_CHAIN (args))
-             OB_PUTC2 (',', ' ');
+             OB_PUTS (", ");
          }
        OB_END_TEMPLATE_ID ();
       }
       break;
 
     case LOOKUP_EXPR:
-      dump_decl (TREE_OPERAND (t, 0), v);
+      dump_decl (TREE_OPERAND (t, 0), flags);
       break;
 
     case LABEL_DECL:
@@ -927,18 +912,18 @@ dump_decl (t, v)
       if ((TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == ENUMERAL_TYPE)
          || (DECL_INITIAL (t) &&
              TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_PARM_INDEX))
-       dump_simple_decl (t, TREE_TYPE (t), v);
+       dump_simple_decl (t, TREE_TYPE (t), flags);
       else if (DECL_NAME (t))
-       dump_decl (DECL_NAME (t), v);
+       dump_decl (DECL_NAME (t), flags);
       else if (DECL_INITIAL (t))
-       dump_expr (DECL_INITIAL (t), 0);
+       dump_expr (DECL_INITIAL (t), flags | TS_EXPR_PARENS);
       else
        OB_PUTS ("enumerator");
       break;
 
     case USING_DECL:
       OB_PUTS ("using ");
-      dump_type (DECL_INITIAL (t), 0);
+      dump_type (DECL_INITIAL (t), flags);
       OB_PUTS ("::");
       OB_PUTID (DECL_NAME (t));
       break;
@@ -946,33 +931,114 @@ dump_decl (t, v)
     default:
       sorry ("`%s' not supported by dump_decl",
             tree_code_name[(int) TREE_CODE (t)]);
+      /* Fallthrough to error.  */
+
+    case ERROR_MARK:
+      OB_PUTS ("{declerror}");
+      break;
+    }
+}
+
+/* Dump a template declaration T under control of FLAGS. This means the
+   'template <...> leaders plus the 'class X' or 'void fn(...)' part.  */
+
+static void
+dump_template_decl (t, flags)
+     tree t;
+     enum tree_string_flags flags;
+{
+  tree orig_args = DECL_TEMPLATE_PARMS (t);
+  tree args;
+  int i; 
+  
+  if (flags & TS_TEMPLATE_PREFIX)
+    {
+      for (args = orig_args = nreverse (orig_args); 
+           args;
+           args = TREE_CHAIN (args))
+        {
+          int len = TREE_VEC_LENGTH (TREE_VALUE (args));
+          
+          OB_PUTS ("template <");
+          for (i = 0; i < len; i++)
+            {
+             tree arg = TREE_VEC_ELT (TREE_VALUE (args), i);
+             tree defval = TREE_PURPOSE (arg);
+             arg = TREE_VALUE (arg);
+              if (i)
+                OB_PUTS (", ");
+             if (TREE_CODE (arg) == TYPE_DECL)
+               {
+                 if (DECL_NAME (arg))
+                   {
+                     OB_PUTS ("class ");
+                     OB_PUTID (DECL_NAME (arg));
+                   }
+                 else
+                   OB_PUTS ("class");
+               }
+             else
+               dump_decl (arg, flags | TS_DECL_TYPE);
+             
+             if (defval)
+               {
+                 OB_PUTS (" = ");
+                 if (TREE_CODE (arg) == TYPE_DECL
+                     || TREE_CODE (arg) == TEMPLATE_DECL)
+                   dump_type (defval, flags);
+                 else
+                   dump_expr (defval, flags | TS_EXPR_PARENS);
+               }
+            }
+          OB_END_TEMPLATE_ID ();
+          OB_PUTC (' ');
+        }
+      nreverse(orig_args);
+      /* If we've shown the template<args> prefix, we'd better show the
+       * decl's type too.  */
+      flags |= TS_DECL_TYPE;
+    }
+  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)));
+  else if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL)
+    dump_decl (DECL_TEMPLATE_RESULT (t), flags | TS_TEMPLATE_PLAIN);
+  else if (TREE_TYPE (t) == NULL_TREE)
+    my_friendly_abort (353);
+  else
+    switch (NEXT_CODE (t))
+    {
+      case METHOD_TYPE:
+      case FUNCTION_TYPE:
+        dump_function_decl (t, flags | TS_TEMPLATE_PLAIN);
+        break;
+      default:
+        /* This case can occur with some illegal code.  */
+        dump_type (TREE_TYPE (t),
+                   (flags & ~TS_AGGR_TAGS) | TS_TEMPLATE_PLAIN
+                   | (flags & TS_DECL_TYPE ? TS_AGGR_TAGS : 0));
     }
 }
 
 /* Pretty print a function decl. There are several ways we want to print a
-   function declaration. We use V to tell us what.
-     V    - 01 23
-   args   - ++ ++
-   retval - -+ ++
-   default- -+ -+
-   throw  - -- ++
+   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. */
 
 static void
-dump_function_decl (t, v)
+dump_function_decl (t, flags)
      tree t;
-     int v;
+     enum tree_string_flags flags;
 {
-  tree name;
   tree fntype;
   tree parmtypes;
   tree cname = NULL_TREE;
+  int show_return = !(flags & TS_FUNC_NORETURN) && (flags & TS_DECL_TYPE);
 
   if (TREE_CODE (t) == TEMPLATE_DECL)
     t = DECL_TEMPLATE_RESULT (t);
 
-  name = DECL_ASSEMBLER_NAME (t);
   fntype = TREE_TYPE (t);
   parmtypes = TYPE_ARG_TYPES (fntype);
 
@@ -983,90 +1049,86 @@ dump_function_decl (t, v)
   else if (TREE_CODE (fntype) == METHOD_TYPE)
     cname = TREE_TYPE (TREE_VALUE (parmtypes));
 
-  /* Print the return type.  */
-  if (v > 0)
+  if (!(flags & TS_DECORATE))
+    /* OK */;
+  else if (DECL_STATIC_FUNCTION_P (t))
+    OB_PUTS ("static ");
+  else if (TYPE_VIRTUAL_P (t))
+    OB_PUTS ("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 (DECL_STATIC_FUNCTION_P (t))
-       OB_PUTS ("static ");
-    
-      if (! DECL_CONV_FN_P (t)
-         && ! DECL_CONSTRUCTOR_P (t)
-         && ! DECL_DESTRUCTOR_P (t))
-       {
-         dump_type_prefix (TREE_TYPE (fntype), 0, 0);
-         OB_PUTC (' ');
-       }
+      if (dump_type_prefix (TREE_TYPE (fntype), flags) != none)
+        OB_PUTC (' ');
     }
 
   /* Print the function name.  */
   if (cname)
     {
-      dump_type (cname, 0);
-      OB_PUTC2 (':', ':');
-      if (TREE_CODE (fntype) == METHOD_TYPE && parmtypes)
-       parmtypes = TREE_CHAIN (parmtypes);
-      if (DECL_CONSTRUCTOR_FOR_VBASE_P (t))
-       /* Skip past "in_charge" identifier.  */
-       parmtypes = TREE_CHAIN (parmtypes);
-    }
-  else if (CP_DECL_CONTEXT (t) != global_namespace)
-    {
-      dump_decl (DECL_CONTEXT (t), 0);
-      OB_PUTC2 (':',':');
+      dump_type (cname, flags);
+      OB_PUTS ("::");
     }
+  else
+    dump_scope (CP_DECL_CONTEXT (t), flags);
 
-  if (DESTRUCTOR_NAME_P (name) && DECL_LANGUAGE (t) == lang_cplusplus)
-    parmtypes = TREE_CHAIN (parmtypes);
+  dump_function_name (t, flags);
   
-  dump_function_name (t);
-
-  /* If V is negative, we don't print the argument types.  */
-  if (v < 0)
+  if (!(flags & TS_DECL_TYPE))
     return;
-
-  dump_parameters (parmtypes, v & 1, 0);
+  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 (v && ! DECL_CONV_FN_P (t))
-    dump_type_suffix (TREE_TYPE (fntype), 1, 0);
+  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 (v >= 2)
-    dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), 0);
+  if (flags & TS_FUNC_THROW)
+    dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), flags);
 }
 
-/* Print a parameter list. V indicates if we show default values or not. If
-   these are for a member function, the member object ptr
-   (and any other hidden args) should have already been removed. */
+/* 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. */
 
 static void
-dump_parameters (parmtypes, v, canonical_name)
+dump_parameters (parmtypes, flags)
      tree parmtypes;
-     int v;
-     int canonical_name;
+     enum tree_string_flags flags;
 {
   int first;
-  OB_PUTC ('(');
+  OB_PUTS (" (");
 
   for (first = 1; parmtypes != void_list_node;
        parmtypes = TREE_CHAIN (parmtypes))
     {
       if (!first)
-        OB_PUTC2 (',', ' ');
+        OB_PUTS (", ");
       first = 0;
       if (!parmtypes)
         {
           OB_PUTS ("...");
           break;
         }
-      dump_type_real (TREE_VALUE (parmtypes), 0, canonical_name);
+      dump_type (TREE_VALUE (parmtypes), flags);
       
-      if (TREE_PURPOSE (parmtypes) && v)
+      if ((flags & TS_PARM_DEFAULTS) && TREE_PURPOSE (parmtypes))
         {
           OB_PUTS (" = ");
-          dump_expr (TREE_PURPOSE (parmtypes), 0);
+          dump_expr (TREE_PURPOSE (parmtypes), flags | TS_EXPR_PARENS);
         }
     }
 
@@ -1076,9 +1138,9 @@ dump_parameters (parmtypes, v, canonical_name)
 /* Print an exception specification. T is the exception specification. */
 
 static void
-dump_exception_spec (t, canonical_name)
+dump_exception_spec (t, flags)
      tree t;
-     int canonical_name;
+     enum tree_string_flags flags;
 {
   if (t)
     {
@@ -1086,11 +1148,11 @@ dump_exception_spec (t, canonical_name)
       if (TREE_VALUE (t) != NULL_TREE)
         while (1)
           {
-            dump_type_real (TREE_VALUE (t), 0, canonical_name);
+            dump_type (TREE_VALUE (t), flags);
             t = TREE_CHAIN (t);
             if (!t)
               break;
-            OB_PUTC2 (',', ' ');
+            OB_PUTS (", ");
           }
       OB_PUTC (')');
     }
@@ -1100,15 +1162,16 @@ dump_exception_spec (t, canonical_name)
    and destructors properly.  */
 
 static void
-dump_function_name (t)
+dump_function_name (t, flags)
      tree t;
+     enum tree_string_flags flags;
 {
   tree name = DECL_NAME (t);
 
   if (DECL_DESTRUCTOR_P (t))
     {
       OB_PUTC ('~');
-      dump_decl (name, 0);
+      dump_decl (name, TS_PLAIN);
     }
   else if (DECL_CONV_FN_P (t))
     {
@@ -1119,7 +1182,7 @@ dump_function_name (t)
         the types will be different, hence the TREE_TYPE field
         of the first name will be clobbered by the second.  */
       OB_PUTS ("operator ");
-      dump_type (TREE_TYPE (TREE_TYPE (t)), 0);
+      dump_type (TREE_TYPE (TREE_TYPE (t)), flags);
     }
   else if (IDENTIFIER_OPNAME_P (name))
     {
@@ -1128,66 +1191,118 @@ dump_function_name (t)
       OB_PUTCP (name_string);
     }
   else
-    dump_decl (name, 0);
+    dump_decl (name, flags);
 
-  if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t) 
-      && DECL_TEMPLATE_INFO (t)
+  if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (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))))
-    {
-      tree args = DECL_TEMPLATE_INFO (t) ? DECL_TI_ARGS (t) : NULL_TREE; 
-      OB_PUTC ('<');
+    dump_template_parms (DECL_TEMPLATE_INFO (t), !DECL_USE_TEMPLATE (t), flags);
+}
 
-      /* Be careful only to print things when we have them, so as not
+/* Dump the template parameters from the template info INFO under control of
+   FLAGS. PRIMARY indicates whether this is a primary template decl, or
+   specialization (partial or complete). For partial specializations we show
+   the specialized parameter values. For a primary template we show no
+   decoration.  */
+
+static void
+dump_template_parms (info, primary, flags)
+     tree info;
+     int primary;
+     enum tree_string_flags flags;
+{
+  tree args = info ? TI_ARGS (info) : NULL_TREE;
+  
+  if (primary && flags & TS_TEMPLATE_PLAIN)
+    return;
+  flags &= ~(TS_AGGR_TAGS | TS_TEMPLATE_PLAIN);
+  OB_PUTC ('<');
+
+  /* Be careful only to print things when we have them, so as not
         to crash producing error messages.  */
-      if (args)
-       {
-         if (TREE_CODE (args) == TREE_LIST)
-           {
-             tree arg;
-             int need_comma = 0;
-             
-             for (arg = args; arg; arg = TREE_CHAIN (arg))
-               {
-                 tree a = TREE_VALUE (arg);
-                 
-                 if (need_comma)
-                   OB_PUTS (", ");
-                 
-                 if (a)
-                    dump_template_value (a, 0, 0);
-                 
-                 need_comma = 1;
-               }
-           }
-         else if (TREE_CODE (args) == TREE_VEC)
-           {
-             int i;
-             int need_comma = 0;
-             
-             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);
-             
-             for (i = 0; i < TREE_VEC_LENGTH (args); i++)
-               {
-                 tree a = TREE_VEC_ELT (args, i);
-                 
-                 if (need_comma)
-                   OB_PUTS (", ");
-                 
-                 if (a)
-                    dump_template_value (a, 0, 0);
-                 
-                 need_comma = 1;
-               }
-           }
-       }
-      OB_END_TEMPLATE_ID ();
+  if (args && !primary)
+    {
+      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);
+          
+          len = TREE_VEC_LENGTH (args);
+        }
+      else if (TREE_CODE (args) == TREE_LIST)
+        len = -1;
+      while (ix != len && args)
+        {
+          tree arg;
+          if (len >= 0)
+            {
+              arg = TREE_VEC_ELT (args, ix);
+              ix++;
+            }
+          else
+            {
+              arg = TREE_VALUE (args);
+              args = TREE_CHAIN (args);
+            }
+          if (need_comma)
+            OB_PUTS (", ");
+              
+          if (!arg)
+            OB_PUTS ("{tplparmerror}");
+          else
+            dump_template_value (arg, flags);
+          need_comma = 1;
+        }
+    }
+  else if (flags & TS_PEDANTIC_NAME)
+    {
+      tree tpl = TI_TEMPLATE (info);
+      tree parms = TREE_VALUE (DECL_TEMPLATE_PARMS (tpl));
+      int len = TREE_VEC_LENGTH (parms);
+      int ix;
+      
+      for (ix = 0; ix != len; ix++)
+        {
+          tree parm = TREE_VALUE (TREE_VEC_ELT (parms, ix));
+          
+          if (ix)
+            OB_PUTS (", ");
+          if (TREE_CODE (parm) == TYPE_DECL)
+            OB_PUTS ("class");
+          else if (TREE_CODE (parm) == TEMPLATE_DECL)
+            dump_decl (DECL_TEMPLATE_RESULT (parm), flags);
+          else
+            dump_type (TREE_TYPE (parm),
+                       flags | TS_TEMPLATE_PARM);
+        }
+    }
+  else if (primary)
+    {
+      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);
+        }
     }
+  OB_END_TEMPLATE_ID ();
 }
 
 static void
@@ -1240,24 +1355,25 @@ dump_char (c)
 /* Print out a list of initializers (subr of dump_expr) */
 
 static void
-dump_expr_list (l)
+dump_expr_list (l, flags)
      tree l;
+     enum tree_string_flags flags;
 {
   while (l)
     {
-      dump_expr (TREE_VALUE (l), 0);
-      if (TREE_CHAIN (l))
-       OB_PUTC2 (',', ' ');
+      dump_expr (TREE_VALUE (l), flags | TS_EXPR_PARENS);
       l = TREE_CHAIN (l);
+      if (l)
+       OB_PUTS (", ");
     }
 }
 
-/* Print out an expression */
+/* Print out an expression E under control of FLAGS. */
 
 static void
-dump_expr (t, nop)
+dump_expr (t, flags)
      tree t;
-     int nop;                  /* suppress parens */
+     enum tree_string_flags flags;
 {
   switch (TREE_CODE (t))
     {
@@ -1269,7 +1385,7 @@ dump_expr (t, nop)
     case TEMPLATE_DECL:
     case NAMESPACE_DECL:
     case OVERLOAD:
-      dump_decl (t, -1);
+      dump_decl (t, flags & ~TS_DECL_TYPE);
       break;
 
     case INTEGER_CST:
@@ -1341,7 +1457,7 @@ dump_expr (t, nop)
 
     case PTRMEM_CST:
       OB_PUTC ('&');
-      dump_type (PTRMEM_CST_CLASS (t), 0);
+      dump_type (PTRMEM_CST_CLASS (t), flags);
       OB_PUTS ("::");
       OB_PUTID (DECL_NAME (PTRMEM_CST_MEMBER (t)));
       break;
@@ -1360,16 +1476,20 @@ dump_expr (t, nop)
       break;
 
     case COMPOUND_EXPR:
-      dump_binary_op (",", t);
+      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 (')');
       break;
 
     case COND_EXPR:
       OB_PUTC ('(');
-      dump_expr (TREE_OPERAND (t, 0), 0);
+      dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
       OB_PUTS (" ? ");
-      dump_expr (TREE_OPERAND (t, 1), 0);
+      dump_expr (TREE_OPERAND (t, 1), flags | TS_EXPR_PARENS);
       OB_PUTS (" : ");
-      dump_expr (TREE_OPERAND (t, 2), 0);
+      dump_expr (TREE_OPERAND (t, 2), flags | TS_EXPR_PARENS);
       OB_PUTC (')');
       break;
 
@@ -1377,11 +1497,11 @@ dump_expr (t, nop)
       if (TREE_HAS_CONSTRUCTOR (t))
        {
          OB_PUTS ("new ");
-         dump_type (TREE_TYPE (TREE_TYPE (t)), 0);
+         dump_type (TREE_TYPE (TREE_TYPE (t)), flags);
        }
       else
        {
-         dump_expr (TREE_OPERAND (t, 0), 0);
+         dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
        }
       break;
 
@@ -1404,7 +1524,7 @@ dump_expr (t, nop)
       }
       OB_PUTC ('(');
       if (TREE_OPERAND (t, 1))
-       dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)));
+       dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags);
       OB_PUTC (')');
       break;
 
@@ -1421,20 +1541,20 @@ dump_expr (t, nop)
            tree ob = TREE_VALUE (args);
            if (TREE_CODE (ob) == ADDR_EXPR)
              {
-               dump_expr (TREE_OPERAND (ob, 0), 0);
+               dump_expr (TREE_OPERAND (ob, 0), flags | TS_EXPR_PARENS);
                OB_PUTC ('.');
              }
            else if (TREE_CODE (ob) != PARM_DECL
                     || strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this"))
              {
-               dump_expr (ob, 0);
-               OB_PUTC2 ('-', '>');
+               dump_expr (ob, flags | TS_EXPR_PARENS);
+               OB_PUTS ("->");
              }
            args = TREE_CHAIN (args);
          }
-       dump_expr (fn, 0);
+       dump_expr (fn, flags | TS_EXPR_PARENS);
        OB_PUTC ('(');
-       dump_expr_list (args);
+       dump_expr_list (args, flags);
        OB_PUTC (')');
       }
       break;
@@ -1448,7 +1568,7 @@ dump_expr (t, nop)
        if (TREE_OPERAND (t, 0))
          {
            OB_PUTC ('(');
-           dump_expr_list (TREE_OPERAND (t, 0));
+           dump_expr_list (TREE_OPERAND (t, 0), flags);
            OB_PUTS (") ");
          }
        if (TREE_CODE (type) == ARRAY_REF)
@@ -1456,11 +1576,11 @@ dump_expr (t, nop)
            (TREE_OPERAND (type, 0),
             build_index_type (size_binop (MINUS_EXPR, TREE_OPERAND (type, 1),
                                           integer_one_node)));
-       dump_type (type, 0);
+       dump_type (type, flags);
        if (TREE_OPERAND (t, 2))
          {
            OB_PUTC ('(');
-           dump_expr_list (TREE_OPERAND (t, 2));
+           dump_expr_list (TREE_OPERAND (t, 2), flags);
            OB_PUTC (')');
          }
       }
@@ -1473,7 +1593,7 @@ dump_expr (t, nop)
         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), 0);
+       dump_expr (TREE_OPERAND (t, 1), flags | TS_EXPR_PARENS);
       break;
 
     case INIT_EXPR:
@@ -1500,19 +1620,19 @@ dump_expr (t, nop)
     case EQ_EXPR:
     case NE_EXPR:
     case EXACT_DIV_EXPR:
-      dump_binary_op (opname_tab[(int) TREE_CODE (t)], t);
+      dump_binary_op (opname_tab[(int) TREE_CODE (t)], t, flags);
       break;
 
     case CEIL_DIV_EXPR:
     case FLOOR_DIV_EXPR:
     case ROUND_DIV_EXPR:
-      dump_binary_op ("/", t);
+      dump_binary_op ("/", t, flags);
       break;
 
     case CEIL_MOD_EXPR:
     case FLOOR_MOD_EXPR:
     case ROUND_MOD_EXPR:
-      dump_binary_op ("%", t);
+      dump_binary_op ("%", t, flags);
       break;
 
     case COMPONENT_REF:
@@ -1524,23 +1644,23 @@ dump_expr (t, nop)
            if (TREE_CODE (ob) != PARM_DECL
                || strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this"))
              {
-               dump_expr (ob, 0);
-               OB_PUTC2 ('-', '>');
+               dump_expr (ob, flags | TS_EXPR_PARENS);
+               OB_PUTS ("->");
              }
          }
        else
          {
-           dump_expr (ob, 0);
+           dump_expr (ob, flags | TS_EXPR_PARENS);
            OB_PUTC ('.');
          }
-       dump_expr (TREE_OPERAND (t, 1), 1);
+       dump_expr (TREE_OPERAND (t, 1), flags & ~TS_EXPR_PARENS);
       }
       break;
 
     case ARRAY_REF:
-      dump_expr (TREE_OPERAND (t, 0), 0);
+      dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
       OB_PUTC ('[');
-      dump_expr (TREE_OPERAND (t, 1), 0);
+      dump_expr (TREE_OPERAND (t, 1), flags | TS_EXPR_PARENS);
       OB_PUTC (']');
       break;
 
@@ -1548,18 +1668,18 @@ dump_expr (t, nop)
       if (same_type_p (TREE_TYPE (t), void_type_node))
        {
          OB_PUTS ("(void)");
-         dump_expr (TREE_OPERAND (t, 0), 0);
+         dump_expr (TREE_OPERAND (t, 0), flags);
        }
       else
-       dump_unary_op ("+", t, nop);
+       dump_unary_op ("+", t, flags);
       break;
 
     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), 0);
+       dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
       else
-       dump_unary_op ("&", t, nop);
+       dump_unary_op ("&", t, flags);
       break;
 
     case INDIRECT_REF:
@@ -1567,9 +1687,9 @@ dump_expr (t, nop)
        {
          t = TREE_OPERAND (t, 0);
          my_friendly_assert (TREE_CODE (t) == CALL_EXPR, 237);
-         dump_expr (TREE_OPERAND (t, 0), 0);
+         dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
          OB_PUTC ('(');
-         dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)));
+         dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags);
          OB_PUTC (')');
        }
       else
@@ -1577,9 +1697,9 @@ dump_expr (t, nop)
          if (TREE_OPERAND (t,0) != NULL_TREE
              && TREE_TYPE (TREE_OPERAND (t, 0))
              && NEXT_CODE (TREE_OPERAND (t, 0)) == REFERENCE_TYPE)
-           dump_expr (TREE_OPERAND (t, 0), nop);
+           dump_expr (TREE_OPERAND (t, 0), flags);
          else
-           dump_unary_op ("*", t, nop);
+           dump_unary_op ("*", t, flags);
        }
       break;
 
@@ -1588,13 +1708,13 @@ dump_expr (t, nop)
     case TRUTH_NOT_EXPR:
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
-      dump_unary_op (opname_tab [(int)TREE_CODE (t)], t, nop);
+      dump_unary_op (opname_tab [(int)TREE_CODE (t)], t, flags);
       break;
 
     case POSTDECREMENT_EXPR:
     case POSTINCREMENT_EXPR:
       OB_PUTC ('(');
-      dump_expr (TREE_OPERAND (t, 0), 0);
+      dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
       OB_PUTCP (opname_tab[(int)TREE_CODE (t)]);
       OB_PUTC (')');
       break;
@@ -1612,19 +1732,21 @@ dump_expr (t, nop)
          
          if (TREE_CODE (next) == FUNCTION_TYPE)
            {
-             if (!nop) OB_PUTC ('(');
+             if (flags & TS_EXPR_PARENS)
+               OB_PUTC ('(');
              OB_PUTC ('*');
-             dump_expr (TREE_OPERAND (t, 0), 1);
-             if (!nop) OB_PUTC (')');
+             dump_expr (TREE_OPERAND (t, 0), flags & ~TS_EXPR_PARENS);
+             if (flags & TS_EXPR_PARENS)
+               OB_PUTC (')');
              break;
            }
          /* else FALLTHRU */
        }
-      dump_expr (TREE_OPERAND (t, 0), 0);
+      dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
       break;
 
     case NOP_EXPR:
-      dump_expr (TREE_OPERAND (t, 0), nop);
+      dump_expr (TREE_OPERAND (t, 0), flags);
       break;
 
     case CONSTRUCTOR:
@@ -1635,7 +1757,7 @@ dump_expr (t, nop)
          if (integer_all_onesp (idx))
            {
              tree pfn = PFN_FROM_PTRMEMFUNC (t);
-             dump_unary_op ("&", pfn, 0);
+             dump_unary_op ("&", pfn, flags | TS_EXPR_PARENS);
              break;
            }
          else if (TREE_CODE (idx) == INTEGER_CST
@@ -1643,7 +1765,7 @@ dump_expr (t, nop)
            {
              /* A NULL pointer-to-member constant.  */
              OB_PUTS ("((");
-             dump_type (TREE_TYPE (t), 0);
+             dump_type (TREE_TYPE (t), flags);
              OB_PUTS (") 0)");
              break;
            }
@@ -1670,13 +1792,14 @@ dump_expr (t, nop)
                }
              if (virtuals)
                {
-                 dump_expr (TREE_VALUE (virtuals), 0);
+                 dump_expr (TREE_VALUE (virtuals),
+                            flags | TS_EXPR_PARENS);
                  break;
                }
            }
        }
       OB_PUTC ('{');
-      dump_expr_list (CONSTRUCTOR_ELTS (t));
+      dump_expr_list (CONSTRUCTOR_ELTS (t), flags);
       OB_PUTC ('}');
       break;
 
@@ -1688,31 +1811,31 @@ dump_expr (t, nop)
            t = TREE_OPERAND (t, 1);
            if (TREE_CODE (t) == FUNCTION_DECL)
              /* A::f */
-             dump_expr (t, 0);
+             dump_expr (t, flags | TS_EXPR_PARENS);
            else if (BASELINK_P (t))
-             dump_expr (OVL_CURRENT (TREE_VALUE (t)), 0);
+             dump_expr (OVL_CURRENT (TREE_VALUE (t)), flags | TS_EXPR_PARENS);
            else
-             dump_decl (t, 0);
+             dump_decl (t, flags);
          }
        else
          {
            if (TREE_CODE (ob) == INDIRECT_REF)
              {
-               dump_expr (TREE_OPERAND (ob, 0), 0);
+               dump_expr (TREE_OPERAND (ob, 0), flags | TS_EXPR_PARENS);
                OB_PUTS (" ->* ");
              }
            else
              {
-               dump_expr (ob, 0);
+               dump_expr (ob, flags | TS_EXPR_PARENS);
                OB_PUTS (" .* ");
              }
-           dump_expr (TREE_OPERAND (t, 1), 0);
+           dump_expr (TREE_OPERAND (t, 1), flags | TS_EXPR_PARENS);
          }
        break;
       }
 
     case TEMPLATE_PARM_INDEX:
-      dump_decl (TEMPLATE_PARM_DECL (t), -1);
+      dump_decl (TEMPLATE_PARM_DECL (t), flags & ~TS_DECL_TYPE);
       break;
 
     case IDENTIFIER_NODE:
@@ -1720,27 +1843,27 @@ dump_expr (t, nop)
       break;
 
     case SCOPE_REF:
-      dump_type (TREE_OPERAND (t, 0), 0);
+      dump_type (TREE_OPERAND (t, 0), flags);
       OB_PUTS ("::");
-      dump_expr (TREE_OPERAND (t, 1), 0);
+      dump_expr (TREE_OPERAND (t, 1), flags | TS_EXPR_PARENS);
       break;
 
     case CAST_EXPR:
       if (TREE_OPERAND (t, 0) == NULL_TREE
          || TREE_CHAIN (TREE_OPERAND (t, 0)))
        {
-         dump_type (TREE_TYPE (t), 0);
+         dump_type (TREE_TYPE (t), flags);
          OB_PUTC ('(');
-         dump_expr_list (TREE_OPERAND (t, 0));
+         dump_expr_list (TREE_OPERAND (t, 0), flags);
          OB_PUTC (')');
        }
       else
        {
          OB_PUTC ('(');
-         dump_type (TREE_TYPE (t), 0);
+         dump_type (TREE_TYPE (t), flags);
          OB_PUTC (')');
          OB_PUTC ('(');
-         dump_expr_list (TREE_OPERAND (t, 0));
+         dump_expr_list (TREE_OPERAND (t, 0), flags);
          OB_PUTC (')');
        }
       break;
@@ -1750,7 +1873,7 @@ dump_expr (t, nop)
       break;
 
     case ARROW_EXPR:
-      dump_expr (TREE_OPERAND (t, 0), nop);
+      dump_expr (TREE_OPERAND (t, 0), flags);
       OB_PUTS ("->");
       break;
 
@@ -1764,9 +1887,9 @@ dump_expr (t, nop)
          OB_PUTS ("__alignof__ (");
        }
       if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 0))) == 't')
-       dump_type (TREE_OPERAND (t, 0), 0);
+       dump_type (TREE_OPERAND (t, 0), flags);
       else
-       dump_unary_op ("*", t, 0);
+       dump_unary_op ("*", t, flags | TS_EXPR_PARENS);
       OB_PUTC (')');
       break;
 
@@ -1777,19 +1900,19 @@ dump_expr (t, nop)
     case TRY_CATCH_EXPR:
     case WITH_CLEANUP_EXPR:
     case CLEANUP_POINT_EXPR:
-      dump_expr (TREE_OPERAND (t, 0), nop);
+      dump_expr (TREE_OPERAND (t, 0), flags);
       break;
 
     case PSEUDO_DTOR_EXPR:
-      dump_expr (TREE_OPERAND (t, 2), nop);
+      dump_expr (TREE_OPERAND (t, 2), flags);
       OB_PUTS (".");
-      dump_type (TREE_OPERAND (t, 0), nop);
+      dump_type (TREE_OPERAND (t, 0), flags);
       OB_PUTS ("::~");
-      dump_type (TREE_OPERAND (t, 1), nop);
+      dump_type (TREE_OPERAND (t, 1), flags);
       break;
 
     case TEMPLATE_ID_EXPR:
-      dump_decl (t, 0);
+      dump_decl (t, flags);
       break;
 
     case STMT_EXPR:
@@ -1800,19 +1923,19 @@ dump_expr (t, nop)
 
     case BIND_EXPR:
       OB_PUTS ("{ ");
-      dump_expr (TREE_OPERAND (t, 1), nop);
+      dump_expr (TREE_OPERAND (t, 1), flags & ~TS_EXPR_PARENS);
       OB_PUTS ("} ");
       break;
       
     case LOOP_EXPR:
       OB_PUTS ("while (1) { ");
-      dump_expr (TREE_OPERAND (t, 0), nop);
+      dump_expr (TREE_OPERAND (t, 0), flags & ~TS_EXPR_PARENS);
       OB_PUTS ("} ");
       break;
 
     case EXIT_EXPR:
       OB_PUTS ("if (");
-      dump_expr (TREE_OPERAND (t, 0), nop);
+      dump_expr (TREE_OPERAND (t, 0), flags & ~TS_EXPR_PARENS);
       OB_PUTS (") break; ");
       break;
 
@@ -1833,112 +1956,97 @@ dump_expr (t, nop)
 
       /* fall through to ERROR_MARK...  */
     case ERROR_MARK:
-      OB_PUTCP ("{error}");
+      OB_PUTCP ("{exprerror}");
       break;
     }
 }
 
 static void
-dump_binary_op (opstring, t)
+dump_binary_op (opstring, t, flags)
      const char *opstring;
      tree t;
+     enum tree_string_flags flags;
 {
   OB_PUTC ('(');
-  dump_expr (TREE_OPERAND (t, 0), 1);
+  dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
   OB_PUTC (' ');
   if (opstring)
     OB_PUTCP (opstring);
   else
     OB_PUTS ("<unknown operator>");
   OB_PUTC (' ');
-  dump_expr (TREE_OPERAND (t, 1), 1);
+  dump_expr (TREE_OPERAND (t, 1), flags | TS_EXPR_PARENS);
   OB_PUTC (')');
 }
 
 static void
-dump_unary_op (opstring, t, nop)
+dump_unary_op (opstring, t, flags)
      const char *opstring;
      tree t;
-     int nop;
+     enum tree_string_flags flags;
 {
-  if (!nop) OB_PUTC ('(');
+  if (flags & TS_EXPR_PARENS)
+    OB_PUTC ('(');
   OB_PUTCP (opstring);
-  dump_expr (TREE_OPERAND (t, 0), 1);
-  if (!nop) OB_PUTC (')');
+  dump_expr (TREE_OPERAND (t, 0), flags & ~TS_EXPR_PARENS);
+  if (flags & TS_EXPR_PARENS)
+    OB_PUTC (')');
 }
 
-/* Print a function decl with exception specification included. */
+/* Exported interface to stringifying types, exprs and decls under TS_*
+   control.  */
 
 const char *
-fndecl_as_string (fndecl, print_default_args_p)
-     tree fndecl;
-     int print_default_args_p;
+type_as_string (typ, flags)
+     tree typ;
+     enum tree_string_flags flags;
 {
   OB_INIT ();
 
-  dump_function_decl (fndecl, 2 + print_default_args_p);
-  
+  dump_type (typ, flags);
+
   OB_FINISH ();
 
   return (char *)obstack_base (&scratch_obstack);
 }
 
-/* Same, but handle a _TYPE.
-   Called from convert_to_reference, mangle_class_name_for_template,
-   build_unary_op, and GNU_xref_decl.  If CANONICAL_NAME is non-zero,
-   when describing a typedef, we use the name of the type described,
-   rather than the name of the typedef.  */
-
 const char *
-type_as_string_real (typ, v, canonical_name)
-     tree typ;
-     int v;
-     int canonical_name;
+expr_as_string (decl, flags)
+     tree decl;
+     enum tree_string_flags flags;
 {
   OB_INIT ();
 
-  dump_type_real (typ, v, canonical_name);
+  dump_expr (decl, flags);
 
   OB_FINISH ();
 
   return (char *)obstack_base (&scratch_obstack);
 }
 
-
 const char *
-type_as_string (typ, v)
-     tree typ;
-     int v;
-{
-  return type_as_string_real (typ, v, 0);
-}
-
-const char *
-expr_as_string (decl, v)
+decl_as_string (decl, flags)
      tree decl;
-     int v ATTRIBUTE_UNUSED;
+     enum tree_string_flags flags;
 {
   OB_INIT ();
 
-  dump_expr (decl, 1);
+  dump_decl (decl, flags);
 
   OB_FINISH ();
 
   return (char *)obstack_base (&scratch_obstack);
 }
 
-/* A cross between type_as_string and fndecl_as_string.
-   Only called from substitute_nice_name.  */
-
 const char *
-decl_as_string (decl, v)
-     tree decl;
-     int v;
+context_as_string (context, flags)
+     tree context;
+     enum tree_string_flags flags;
 {
   OB_INIT ();
-
-  dump_decl (decl, v);
-
+  
+  dump_scope (context, flags);
+  
   OB_FINISH ();
 
   return (char *)obstack_base (&scratch_obstack);
@@ -1952,7 +2060,7 @@ lang_decl_name (decl, v)
      int v;
 {
   if (v >= 2)
-    return decl_as_string (decl, 1);
+    return decl_as_string (decl, TS_DECL_TYPE);
 
   OB_INIT ();
 
@@ -1963,20 +2071,19 @@ lang_decl_name (decl, v)
        cname = DECL_CLASS_CONTEXT (decl);
       else
        cname = DECL_CONTEXT (decl);
-      dump_type (cname, 0);
-      OB_PUTC2 (':', ':');
+      dump_type (cname, TS_PLAIN);
+      OB_PUTS ("::");
     }
 
   if (TREE_CODE (decl) == FUNCTION_DECL)
-    dump_function_name (decl);
+    dump_function_name (decl, TS_PLAIN);
   else
-    dump_decl (DECL_NAME (decl), 0);
+    dump_decl (DECL_NAME (decl), TS_PLAIN);
 
   OB_FINISH ();
 
   return (char *)obstack_base (&scratch_obstack);
 }
-  
 
 const char *
 cp_file_of (t)
@@ -2016,16 +2123,79 @@ cp_line_of (t)
   return line;
 }
 
-const char *
-code_as_string (c, v)
+/* 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_
+   function.  */
+
+static const char *
+decl_to_string (decl, verbose)
+     tree decl;
+     int verbose;
+{
+  enum tree_string_flags 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;
+  if (verbose)
+    flags |= TS_DECL_TYPE | TS_DECORATE | TS_PARM_DEFAULTS;
+  else if (TREE_CODE (decl) == FUNCTION_DECL)
+    flags |= TS_DECL_TYPE | TS_FUNC_NORETURN;
+  flags |= TS_TEMPLATE_PREFIX;
+  
+  OB_INIT ();
+
+  dump_decl (decl, flags);
+
+  OB_FINISH ();
+
+  return (char *)obstack_base (&scratch_obstack);
+}
+
+static const char *
+expr_to_string (decl, verbose)
+     tree decl;
+     int verbose ATTRIBUTE_UNUSED;
+{
+  OB_INIT ();
+
+  dump_expr (decl, 0);
+
+  OB_FINISH ();
+
+  return (char *)obstack_base (&scratch_obstack);
+}
+
+static const char *
+fndecl_to_string (fndecl, verbose)
+     tree fndecl;
+     int verbose;
+{
+  enum tree_string_flags flags;
+  
+  flags = TS_FUNC_THROW | TS_DECL_TYPE;
+  if (verbose)
+    flags |= TS_PARM_DEFAULTS;
+  OB_INIT ();
+
+  dump_decl (fndecl, flags);
+  
+  OB_FINISH ();
+
+  return (char *)obstack_base (&scratch_obstack);
+}
+
+
+static const char *
+code_to_string (c, v)
      enum tree_code c;
      int v ATTRIBUTE_UNUSED;
 {
   return tree_code_name [c];
 }
 
-const char *
-language_as_string (c, v)
+static const char *
+language_to_string (c, v)
      enum languages c;
      int v ATTRIBUTE_UNUSED;
 {
@@ -2048,8 +2218,8 @@ language_as_string (c, v)
 
 /* Return the proper printed version of a parameter to a C++ function.  */
 
-const char *
-parm_as_string (p, v)
+static const char *
+parm_to_string (p, v)
      int p;
      int v ATTRIBUTE_UNUSED;
 {
@@ -2060,8 +2230,8 @@ parm_as_string (p, v)
   return digit_buffer;
 }
 
-const char *
-op_as_string (p, v)
+static const char *
+op_to_string (p, v)
      enum tree_code p;
      int v ATTRIBUTE_UNUSED;
 {
@@ -2074,8 +2244,29 @@ op_as_string (p, v)
   return buf;
 }
 
-const char *
-assop_as_string (p, v)
+static const char *
+type_to_string (typ, verbose)
+     tree typ;
+     int verbose;
+{
+  enum tree_string_flags flags;
+  
+  flags = 0;
+  if (verbose)
+    flags |= TS_AGGR_TAGS;
+  flags |= TS_TEMPLATE_PREFIX;
+  
+  OB_INIT ();
+
+  dump_type (typ, flags);
+
+  OB_FINISH ();
+
+  return (char *)obstack_base (&scratch_obstack);
+}
+
+static const char *
+assop_to_string (p, v)
      enum tree_code p;
      int v ATTRIBUTE_UNUSED;
 {
@@ -2088,16 +2279,20 @@ assop_as_string (p, v)
   return buf;
 }
 
-const char *
-args_as_string (p, v)
+static const char *
+args_to_string (p, verbose)
      tree p;
-     int v;
+     int verbose;
 {
+  enum tree_string_flags flags = 0;
+  if (verbose)
+    flags |= TS_AGGR_TAGS;
+  
   if (p == NULL_TREE)
     return "";
 
   if (TREE_CODE_CLASS (TREE_CODE (TREE_VALUE (p))) == 't')
-    return type_as_string (p, v);
+    return type_as_string (p, flags);
 
   OB_INIT ();
   for (; p; p = TREE_CHAIN (p))
@@ -2105,7 +2300,7 @@ args_as_string (p, v)
       if (TREE_VALUE (p) == null_node)
        OB_PUTS ("NULL");
       else
-       dump_type (error_type (TREE_VALUE (p)), v);
+       dump_type (error_type (TREE_VALUE (p)), flags);
       if (TREE_CHAIN (p))
        OB_PUTS (", ");
     }
@@ -2113,8 +2308,8 @@ args_as_string (p, v)
   return (char *)obstack_base (&scratch_obstack);
 }
 
-const char *
-cv_as_string (p, v)
+static const char *
+cv_to_string (p, v)
      tree p;
      int v ATTRIBUTE_UNUSED;
 {
index 3fca3d8..a4cb422 100644 (file)
@@ -3527,7 +3527,7 @@ mangle_class_name_for_template (name, parms, arglist)
 
       if (TREE_CODE (parm) == TYPE_DECL)
        {
-         cat (type_as_string_real (arg, 0, 1));
+         cat (type_as_string (arg, TS_CHASE_TYPEDEFS));
          continue;
        }
       else if (TREE_CODE (parm) == TEMPLATE_DECL)
@@ -3551,7 +3551,7 @@ mangle_class_name_for_template (name, parms, arglist)
            }
          else
            /* Output the parameter declaration */
-           cat (type_as_string_real (arg, 0, 1));
+           cat (type_as_string (arg, TS_CHASE_TYPEDEFS));
          continue;
        }
       else
@@ -4401,7 +4401,7 @@ print_template_context (err)
            /* Avoid redundancy with the the "In function" line.  */;
          else 
            fprintf (stderr, "%s: In instantiation of `%s':\n",
-                    file, decl_as_string (p->decl, 0));
+                    file, decl_as_string (p->decl, TS_DECL_TYPE | TS_FUNC_NORETURN));
          
          line = p->line;
          file = p->file;
@@ -4412,7 +4412,7 @@ print_template_context (err)
   for (; p; p = p->next)
     {
       fprintf (stderr, "%s:%d:   instantiated from `%s'\n", file, line,
-              decl_as_string (p->decl, 0));
+              decl_as_string (p->decl, TS_DECL_TYPE | TS_FUNC_NORETURN));
       line = p->line;
       file = p->file;
     }