118334Speter/* Call-backs for C++ error reporting.
218334Speter   This code is non-reentrant.
3132718Skan   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002,
4169689Skan   2003, 2004, 2005 Free Software Foundation, Inc.
5132718Skan   This file is part of GCC.
618334Speter
7132718SkanGCC is free software; you can redistribute it and/or modify
818334Speterit under the terms of the GNU General Public License as published by
918334Speterthe Free Software Foundation; either version 2, or (at your option)
1018334Speterany later version.
1118334Speter
12132718SkanGCC is distributed in the hope that it will be useful,
1318334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of
1418334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1518334SpeterGNU General Public License for more details.
1618334Speter
1718334SpeterYou should have received a copy of the GNU General Public License
18132718Skanalong with GCC; see the file COPYING.  If not, write to
19169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor,
20169689SkanBoston, MA 02110-1301, USA.  */
2118334Speter
2218334Speter#include "config.h"
2350397Sobrien#include "system.h"
24132718Skan#include "coretypes.h"
25132718Skan#include "tm.h"
2618334Speter#include "tree.h"
2718334Speter#include "cp-tree.h"
2890075Sobrien#include "real.h"
2950397Sobrien#include "toplev.h"
3090075Sobrien#include "flags.h"
3190075Sobrien#include "diagnostic.h"
32117395Skan#include "langhooks-def.h"
33132718Skan#include "cxx-pretty-print.h"
3418334Speter
35169689Skan#define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',')
3618334Speter
3790075Sobrien/* The global buffer where we dump everything.  It is there only for
3890075Sobrien   transitional purpose.  It is expected, in the near future, to be
3990075Sobrien   completely removed.  */
40132718Skanstatic cxx_pretty_printer scratch_pretty_printer;
41132718Skan#define cxx_pp (&scratch_pretty_printer)
4218334Speter
4390075Sobrien# define NEXT_CODE(T) (TREE_CODE (TREE_TYPE (T)))
4418334Speter
45132718Skanstatic const char *args_to_string (tree, int);
46132718Skanstatic const char *assop_to_string (enum tree_code);
47132718Skanstatic const char *code_to_string (enum tree_code);
48132718Skanstatic const char *cv_to_string (tree, int);
49132718Skanstatic const char *decl_to_string (tree, int);
50132718Skanstatic const char *expr_to_string (tree);
51132718Skanstatic const char *fndecl_to_string (tree, int);
52132718Skanstatic const char *op_to_string	(enum tree_code);
53132718Skanstatic const char *parm_to_string (int);
54132718Skanstatic const char *type_to_string (tree, int);
5552284Sobrien
56132718Skanstatic void dump_type (tree, int);
57132718Skanstatic void dump_typename (tree, int);
58132718Skanstatic void dump_simple_decl (tree, tree, int);
59132718Skanstatic void dump_decl (tree, int);
60132718Skanstatic void dump_template_decl (tree, int);
61132718Skanstatic void dump_function_decl (tree, int);
62132718Skanstatic void dump_expr (tree, int);
63132718Skanstatic void dump_unary_op (const char *, tree, int);
64132718Skanstatic void dump_binary_op (const char *, tree, int);
65132718Skanstatic void dump_aggr_type (tree, int);
66169689Skanstatic void dump_type_prefix (tree, int);
67132718Skanstatic void dump_type_suffix (tree, int);
68132718Skanstatic void dump_function_name (tree, int);
69132718Skanstatic void dump_expr_list (tree, int);
70132718Skanstatic void dump_global_iord (tree);
71132718Skanstatic void dump_parameters (tree, int);
72132718Skanstatic void dump_exception_spec (tree, int);
73132718Skanstatic void dump_template_argument (tree, int);
74132718Skanstatic void dump_template_argument_list (tree, int);
75132718Skanstatic void dump_template_parameter (tree, int);
76132718Skanstatic void dump_template_bindings (tree, tree);
77132718Skanstatic void dump_scope (tree, int);
78132718Skanstatic void dump_template_parms (tree, int, int);
7918334Speter
80132718Skanstatic const char *function_category (tree);
81132718Skanstatic void maybe_print_instantiation_context (diagnostic_context *);
82132718Skanstatic void print_instantiation_full_context (diagnostic_context *);
83132718Skanstatic void print_instantiation_partial_context (diagnostic_context *,
84169689Skan						 tree, location_t);
85132718Skanstatic void cp_diagnostic_starter (diagnostic_context *, diagnostic_info *);
86132718Skanstatic void cp_diagnostic_finalizer (diagnostic_context *, diagnostic_info *);
87132718Skanstatic void cp_print_error_function (diagnostic_context *, diagnostic_info *);
8818334Speter
89169689Skanstatic bool cp_printer (pretty_printer *, text_info *, const char *,
90169689Skan			int, bool, bool, bool);
91132718Skanstatic location_t location_of (tree);
9250397Sobrien
9318334Spetervoid
94132718Skaninit_error (void)
9518334Speter{
9690075Sobrien  diagnostic_starter (global_dc) = cp_diagnostic_starter;
9790075Sobrien  diagnostic_finalizer (global_dc) = cp_diagnostic_finalizer;
9890075Sobrien  diagnostic_format_decoder (global_dc) = cp_printer;
9990075Sobrien
100132718Skan  pp_construct (pp_base (cxx_pp), NULL, 0);
101132718Skan  pp_cxx_pretty_printer_init (cxx_pp);
10218334Speter}
10318334Speter
10490075Sobrien/* Dump a scope, if deemed necessary.  */
10552284Sobrien
10690075Sobrienstatic void
107132718Skandump_scope (tree scope, int flags)
10852284Sobrien{
10990075Sobrien  int f = ~TFF_RETURN_TYPE & (flags & (TFF_SCOPE | TFF_CHASE_TYPEDEF));
11052284Sobrien
11190075Sobrien  if (scope == NULL_TREE)
11290075Sobrien    return;
11390075Sobrien
11490075Sobrien  if (TREE_CODE (scope) == NAMESPACE_DECL)
11590075Sobrien    {
11690075Sobrien      if (scope != global_namespace)
117169689Skan	{
118169689Skan	  dump_decl (scope, f);
119169689Skan	  pp_cxx_colon_colon (cxx_pp);
120169689Skan	}
12190075Sobrien    }
12290075Sobrien  else if (AGGREGATE_TYPE_P (scope))
12390075Sobrien    {
12490075Sobrien      dump_type (scope, f);
125169689Skan      pp_cxx_colon_colon (cxx_pp);
12690075Sobrien    }
12790075Sobrien  else if ((flags & TFF_SCOPE) && TREE_CODE (scope) == FUNCTION_DECL)
12890075Sobrien    {
12990075Sobrien      dump_function_decl (scope, f);
130169689Skan      pp_cxx_colon_colon (cxx_pp);
13190075Sobrien    }
13252284Sobrien}
13352284Sobrien
13490075Sobrien/* Dump the template ARGument under control of FLAGS.  */
13552284Sobrien
13690075Sobrienstatic void
137132718Skandump_template_argument (tree arg, int flags)
13890075Sobrien{
13990075Sobrien  if (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL)
14090075Sobrien    dump_type (arg, flags & ~TFF_CLASS_KEY_OR_ENUM);
14190075Sobrien  else
14290075Sobrien    dump_expr (arg, (flags | TFF_EXPR_IN_PARENS) & ~TFF_CLASS_KEY_OR_ENUM);
14390075Sobrien}
14452284Sobrien
14590075Sobrien/* Dump a template-argument-list ARGS (always a TREE_VEC) under control
14690075Sobrien   of FLAGS.  */
14752284Sobrien
14890075Sobrienstatic void
149132718Skandump_template_argument_list (tree args, int flags)
15090075Sobrien{
15190075Sobrien  int n = TREE_VEC_LENGTH (args);
15290075Sobrien  int need_comma = 0;
15390075Sobrien  int i;
15452284Sobrien
15590075Sobrien  for (i = 0; i< n; ++i)
15690075Sobrien    {
15790075Sobrien      if (need_comma)
158169689Skan	pp_separate_with_comma (cxx_pp);
15990075Sobrien      dump_template_argument (TREE_VEC_ELT (args, i), flags);
16090075Sobrien      need_comma = 1;
16190075Sobrien    }
16290075Sobrien}
16352284Sobrien
16490075Sobrien/* Dump a template parameter PARM (a TREE_LIST) under control of FLAGS.  */
16590075Sobrien
16690075Sobrienstatic void
167132718Skandump_template_parameter (tree parm, int flags)
16890075Sobrien{
169169689Skan  tree p;
170169689Skan  tree a;
17190075Sobrien
172169689Skan  if (parm == error_mark_node)
173169689Skan   return;
174169689Skan
175169689Skan  p = TREE_VALUE (parm);
176169689Skan  a = TREE_PURPOSE (parm);
177169689Skan
17890075Sobrien  if (TREE_CODE (p) == TYPE_DECL)
17990075Sobrien    {
18090075Sobrien      if (flags & TFF_DECL_SPECIFIERS)
181169689Skan	{
182169689Skan	  pp_cxx_identifier (cxx_pp, "class");
183169689Skan	  if (DECL_NAME (p))
184169689Skan	    pp_cxx_tree_identifier (cxx_pp, DECL_NAME (p));
185169689Skan	}
18690075Sobrien      else if (DECL_NAME (p))
187169689Skan	pp_cxx_tree_identifier (cxx_pp, DECL_NAME (p));
18890075Sobrien      else
189169689Skan	pp_cxx_canonical_template_parameter (cxx_pp, TREE_TYPE (p));
19090075Sobrien    }
19190075Sobrien  else
19290075Sobrien    dump_decl (p, flags | TFF_DECL_SPECIFIERS);
19390075Sobrien
19490075Sobrien  if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && a != NULL_TREE)
19590075Sobrien    {
196169689Skan      pp_cxx_whitespace (cxx_pp);
197169689Skan      pp_equal (cxx_pp);
198169689Skan      pp_cxx_whitespace (cxx_pp);
19990075Sobrien      if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL)
200169689Skan	dump_type (a, flags & ~TFF_CHASE_TYPEDEF);
20190075Sobrien      else
202169689Skan	dump_expr (a, flags | TFF_EXPR_IN_PARENS);
20390075Sobrien    }
20490075Sobrien}
20590075Sobrien
20690075Sobrien/* Dump, under control of FLAGS, a template-parameter-list binding.
20790075Sobrien   PARMS is a TREE_LIST of TREE_VEC of TREE_LIST and ARGS is a
20890075Sobrien   TREE_VEC.  */
20990075Sobrien
21090075Sobrienstatic void
211132718Skandump_template_bindings (tree parms, tree args)
21290075Sobrien{
21390075Sobrien  int need_comma = 0;
21490075Sobrien
21590075Sobrien  while (parms)
21690075Sobrien    {
21790075Sobrien      tree p = TREE_VALUE (parms);
21890075Sobrien      int lvl = TMPL_PARMS_DEPTH (parms);
21990075Sobrien      int arg_idx = 0;
22090075Sobrien      int i;
22190075Sobrien
22290075Sobrien      for (i = 0; i < TREE_VEC_LENGTH (p); ++i)
22390075Sobrien	{
22490075Sobrien	  tree arg = NULL_TREE;
22590075Sobrien
22690075Sobrien	  /* Don't crash if we had an invalid argument list.  */
22790075Sobrien	  if (TMPL_ARGS_DEPTH (args) >= lvl)
22890075Sobrien	    {
22990075Sobrien	      tree lvl_args = TMPL_ARGS_LEVEL (args, lvl);
23090075Sobrien	      if (NUM_TMPL_ARGS (lvl_args) > arg_idx)
23190075Sobrien		arg = TREE_VEC_ELT (lvl_args, arg_idx);
23290075Sobrien	    }
23390075Sobrien
23490075Sobrien	  if (need_comma)
235132718Skan	    pp_separate_with_comma (cxx_pp);
23690075Sobrien	  dump_template_parameter (TREE_VEC_ELT (p, i), TFF_PLAIN_IDENTIFIER);
237169689Skan	  pp_cxx_whitespace (cxx_pp);
238169689Skan	  pp_equal (cxx_pp);
239169689Skan	  pp_cxx_whitespace (cxx_pp);
24090075Sobrien	  if (arg)
24190075Sobrien	    dump_template_argument (arg, TFF_PLAIN_IDENTIFIER);
24290075Sobrien	  else
243132718Skan	    pp_identifier (cxx_pp, "<missing>");
24490075Sobrien
24590075Sobrien	  ++arg_idx;
24690075Sobrien	  need_comma = 1;
24752284Sobrien	}
24890075Sobrien
24990075Sobrien      parms = TREE_CHAIN (parms);
25018334Speter    }
25118334Speter}
25218334Speter
253117395Skan/* Dump a human-readable equivalent of TYPE.  FLAGS controls the
254117395Skan   format.  */
25518334Speter
25618334Speterstatic void
257132718Skandump_type (tree t, int flags)
25818334Speter{
25918334Speter  if (t == NULL_TREE)
26018334Speter    return;
26190075Sobrien
26218334Speter  if (TYPE_PTRMEMFUNC_P (t))
26318334Speter    goto offset_type;
26418334Speter
26518334Speter  switch (TREE_CODE (t))
26618334Speter    {
26718334Speter    case UNKNOWN_TYPE:
268169689Skan      pp_identifier (cxx_pp, "<unresolved overloaded function type>");
26918334Speter      break;
27018334Speter
27118334Speter    case TREE_LIST:
27252284Sobrien      /* A list of function parms.  */
27390075Sobrien      dump_parameters (t, flags);
27418334Speter      break;
27518334Speter
27618334Speter    case IDENTIFIER_NODE:
277169689Skan      pp_cxx_tree_identifier (cxx_pp, t);
27818334Speter      break;
27918334Speter
280169689Skan    case TREE_BINFO:
28190075Sobrien      dump_type (BINFO_TYPE (t), flags);
28218334Speter      break;
28318334Speter
28418334Speter    case RECORD_TYPE:
28518334Speter    case UNION_TYPE:
28618334Speter    case ENUMERAL_TYPE:
28790075Sobrien      dump_aggr_type (t, flags);
28818334Speter      break;
28918334Speter
29018334Speter    case TYPE_DECL:
29190075Sobrien      if (flags & TFF_CHASE_TYPEDEF)
292169689Skan	{
293169689Skan	  dump_type (DECL_ORIGINAL_TYPE (t)
294169689Skan		     ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t), flags);
295169689Skan	  break;
296169689Skan	}
297132718Skan      /* Else fall through.  */
29890075Sobrien
29950397Sobrien    case TEMPLATE_DECL:
30052284Sobrien    case NAMESPACE_DECL:
30190075Sobrien      dump_decl (t, flags & ~TFF_DECL_SPECIFIERS);
30218334Speter      break;
30318334Speter
30418334Speter    case INTEGER_TYPE:
30518334Speter    case REAL_TYPE:
30618334Speter    case VOID_TYPE:
30718334Speter    case BOOLEAN_TYPE:
308132718Skan    case COMPLEX_TYPE:
309132718Skan    case VECTOR_TYPE:
310132718Skan      pp_type_specifier_seq (cxx_pp, t);
31118334Speter      break;
31218334Speter
31350397Sobrien    case TEMPLATE_TEMPLATE_PARM:
314117395Skan      /* For parameters inside template signature.  */
31590075Sobrien      if (TYPE_IDENTIFIER (t))
316169689Skan	pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t));
31750397Sobrien      else
318169689Skan	pp_cxx_canonical_template_parameter (cxx_pp, t);
31918334Speter      break;
32018334Speter
32190075Sobrien    case BOUND_TEMPLATE_TEMPLATE_PARM:
32290075Sobrien      {
32390075Sobrien	tree args = TYPE_TI_ARGS (t);
324169689Skan	pp_cxx_cv_qualifier_seq (cxx_pp, t);
325169689Skan	pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t));
326169689Skan	pp_cxx_begin_template_argument_list (cxx_pp);
327169689Skan	dump_template_argument_list (args, flags);
328169689Skan	pp_cxx_end_template_argument_list (cxx_pp);
32990075Sobrien      }
33090075Sobrien      break;
33190075Sobrien
33250397Sobrien    case TEMPLATE_TYPE_PARM:
333169689Skan      pp_cxx_cv_qualifier_seq (cxx_pp, t);
33450397Sobrien      if (TYPE_IDENTIFIER (t))
335169689Skan	pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t));
33650397Sobrien      else
337169689Skan	pp_cxx_canonical_template_parameter
338169689Skan	  (cxx_pp, TEMPLATE_TYPE_PARM_INDEX (t));
33918334Speter      break;
34018334Speter
34118334Speter      /* This is not always necessary for pointers and such, but doing this
34218334Speter	 reduces code size.  */
34318334Speter    case ARRAY_TYPE:
34418334Speter    case POINTER_TYPE:
34518334Speter    case REFERENCE_TYPE:
34618334Speter    case OFFSET_TYPE:
34718334Speter    offset_type:
34818334Speter    case FUNCTION_TYPE:
34918334Speter    case METHOD_TYPE:
35090075Sobrien    {
35190075Sobrien      dump_type_prefix (t, flags);
35290075Sobrien      dump_type_suffix (t, flags);
35318334Speter      break;
35490075Sobrien    }
35550397Sobrien    case TYPENAME_TYPE:
356169689Skan      pp_cxx_cv_qualifier_seq (cxx_pp, t);
357169689Skan      pp_cxx_identifier (cxx_pp,
358169689Skan			 TYPENAME_IS_ENUM_P (t) ? "enum"
359169689Skan			 : TYPENAME_IS_CLASS_P (t) ? "class"
360169689Skan			 : "typename");
36190075Sobrien      dump_typename (t, flags);
36250397Sobrien      break;
36350397Sobrien
36490075Sobrien    case UNBOUND_CLASS_TEMPLATE:
36590075Sobrien      dump_type (TYPE_CONTEXT (t), flags);
366169689Skan      pp_cxx_colon_colon (cxx_pp);
367169689Skan      pp_cxx_identifier (cxx_pp, "template");
36890075Sobrien      dump_type (DECL_NAME (TYPE_NAME (t)), flags);
36990075Sobrien      break;
37090075Sobrien
37152284Sobrien    case TYPEOF_TYPE:
372169689Skan      pp_cxx_identifier (cxx_pp, "__typeof__");
373169689Skan      pp_cxx_whitespace (cxx_pp);
374169689Skan      pp_cxx_left_paren (cxx_pp);
375169689Skan      dump_expr (TYPEOF_TYPE_EXPR (t), flags & ~TFF_EXPR_IN_PARENS);
376169689Skan      pp_cxx_right_paren (cxx_pp);
37752284Sobrien      break;
37852284Sobrien
37918334Speter    default:
380132718Skan      pp_unsupported_tree (cxx_pp, t);
381117395Skan      /* Fall through to error.  */
38290075Sobrien
38390075Sobrien    case ERROR_MARK:
384132718Skan      pp_identifier (cxx_pp, "<type error>");
38590075Sobrien      break;
38618334Speter    }
38718334Speter}
38818334Speter
38990075Sobrien/* Dump a TYPENAME_TYPE. We need to notice when the context is itself
39090075Sobrien   a TYPENAME_TYPE.  */
39190075Sobrien
39290075Sobrienstatic void
393132718Skandump_typename (tree t, int flags)
39418334Speter{
39590075Sobrien  tree ctx = TYPE_CONTEXT (t);
39690075Sobrien
39790075Sobrien  if (TREE_CODE (ctx) == TYPENAME_TYPE)
39890075Sobrien    dump_typename (ctx, flags);
39990075Sobrien  else
40090075Sobrien    dump_type (ctx, flags & ~TFF_CLASS_KEY_OR_ENUM);
401169689Skan  pp_cxx_colon_colon (cxx_pp);
40290075Sobrien  dump_decl (TYPENAME_TYPE_FULLNAME (t), flags);
40390075Sobrien}
40490075Sobrien
40590075Sobrien/* Return the name of the supplied aggregate, or enumeral type.  */
40690075Sobrien
407169689Skanconst char *
408169689Skanclass_key_or_enum_as_string (tree t)
40990075Sobrien{
41018334Speter  if (TREE_CODE (t) == ENUMERAL_TYPE)
41118334Speter    return "enum";
41218334Speter  else if (TREE_CODE (t) == UNION_TYPE)
41318334Speter    return "union";
41418334Speter  else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t))
41518334Speter    return "class";
41618334Speter  else
41718334Speter    return "struct";
41818334Speter}
41918334Speter
42090075Sobrien/* Print out a class declaration T under the control of FLAGS,
42190075Sobrien   in the form `class foo'.  */
42250397Sobrien
42350397Sobrienstatic void
424132718Skandump_aggr_type (tree t, int flags)
42550397Sobrien{
42618334Speter  tree name;
427169689Skan  const char *variety = class_key_or_enum_as_string (t);
42890075Sobrien  int typdef = 0;
42990075Sobrien  int tmplate = 0;
43018334Speter
431169689Skan  pp_cxx_cv_qualifier_seq (cxx_pp, t);
43218334Speter
43390075Sobrien  if (flags & TFF_CLASS_KEY_OR_ENUM)
434169689Skan    pp_cxx_identifier (cxx_pp, variety);
43518334Speter
43690075Sobrien  if (flags & TFF_CHASE_TYPEDEF)
43790075Sobrien    t = TYPE_MAIN_VARIANT (t);
43890075Sobrien
43990075Sobrien  name = TYPE_NAME (t);
44090075Sobrien
44190075Sobrien  if (name)
44218334Speter    {
44390075Sobrien      typdef = !DECL_ARTIFICIAL (name);
44490075Sobrien      tmplate = !typdef && TREE_CODE (t) != ENUMERAL_TYPE
445169689Skan		&& TYPE_LANG_SPECIFIC (t) && CLASSTYPE_TEMPLATE_INFO (t)
446169689Skan		&& (TREE_CODE (CLASSTYPE_TI_TEMPLATE (t)) != TEMPLATE_DECL
447169689Skan		    || PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)));
44890075Sobrien      dump_scope (CP_DECL_CONTEXT (name), flags | TFF_SCOPE);
44990075Sobrien      if (tmplate)
450169689Skan	{
451169689Skan	  /* Because the template names are mangled, we have to locate
452169689Skan	     the most general template, and use that name.  */
453169689Skan	  tree tpl = CLASSTYPE_TI_TEMPLATE (t);
45490075Sobrien
455169689Skan	  while (DECL_TEMPLATE_INFO (tpl))
456169689Skan	    tpl = DECL_TI_TEMPLATE (tpl);
457169689Skan	  name = tpl;
458169689Skan	}
45990075Sobrien      name = DECL_NAME (name);
46018334Speter    }
46118334Speter
46218334Speter  if (name == 0 || ANON_AGGRNAME_P (name))
46318334Speter    {
46490075Sobrien      if (flags & TFF_CLASS_KEY_OR_ENUM)
465169689Skan	pp_identifier (cxx_pp, "<anonymous>");
46690075Sobrien      else
467169689Skan	pp_printf (pp_base (cxx_pp), "<anonymous %s>", variety);
46818334Speter    }
46918334Speter  else
470169689Skan    pp_cxx_tree_identifier (cxx_pp, name);
47190075Sobrien  if (tmplate)
47290075Sobrien    dump_template_parms (TYPE_TEMPLATE_INFO (t),
473169689Skan			 !CLASSTYPE_USE_TEMPLATE (t),
474169689Skan			 flags & ~TFF_TEMPLATE_HEADER);
47518334Speter}
47618334Speter
47718334Speter/* Dump into the obstack the initial part of the output for a given type.
47818334Speter   This is necessary when dealing with things like functions returning
47918334Speter   functions.  Examples:
48018334Speter
48118334Speter   return type of `int (* fee ())()': pointer -> function -> int.  Both
48218334Speter   pointer (and reference and offset) and function (and member) types must
48318334Speter   deal with prefix and suffix.
48418334Speter
48518334Speter   Arrays must also do this for DECL nodes, like int a[], and for things like
486169689Skan   int *[]&.  */
48718334Speter
488169689Skanstatic void
489132718Skandump_type_prefix (tree t, int flags)
49018334Speter{
49118334Speter  if (TYPE_PTRMEMFUNC_P (t))
49218334Speter    {
49318334Speter      t = TYPE_PTRMEMFUNC_FN_TYPE (t);
49418334Speter      goto offset_type;
49518334Speter    }
49690075Sobrien
49718334Speter  switch (TREE_CODE (t))
49818334Speter    {
49918334Speter    case POINTER_TYPE:
50052284Sobrien    case REFERENCE_TYPE:
50118334Speter      {
50218334Speter	tree sub = TREE_TYPE (t);
50390075Sobrien
504169689Skan	dump_type_prefix (sub, flags);
505132718Skan	if (TREE_CODE (sub) == ARRAY_TYPE)
50618334Speter	  {
507169689Skan	    pp_cxx_whitespace (cxx_pp);
508169689Skan	    pp_cxx_left_paren (cxx_pp);
50918334Speter	  }
510132718Skan	pp_character (cxx_pp, "&*"[TREE_CODE (t) == POINTER_TYPE]);
511169689Skan	pp_base (cxx_pp)->padding = pp_before;
512169689Skan	pp_cxx_cv_qualifier_seq (cxx_pp, t);
51318334Speter      }
51418334Speter      break;
51518334Speter
51618334Speter    case OFFSET_TYPE:
51718334Speter    offset_type:
518169689Skan      dump_type_prefix (TREE_TYPE (t), flags);
51918334Speter      if (TREE_CODE (t) == OFFSET_TYPE)	/* pmfs deal with this in d_t_p */
52018334Speter	{
521169689Skan	  pp_maybe_space (cxx_pp);
522169689Skan	  if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
523169689Skan	     pp_cxx_left_paren (cxx_pp);
52490075Sobrien	  dump_type (TYPE_OFFSET_BASETYPE (t), flags);
525169689Skan	  pp_cxx_colon_colon (cxx_pp);
52618334Speter	}
527169689Skan      pp_cxx_star (cxx_pp);
528169689Skan      pp_cxx_cv_qualifier_seq (cxx_pp, t);
529169689Skan      pp_base (cxx_pp)->padding = pp_before;
53018334Speter      break;
53118334Speter
53218334Speter      /* Can only be reached through function pointer -- this would not be
533169689Skan	 correct if FUNCTION_DECLs used it.  */
53418334Speter    case FUNCTION_TYPE:
535169689Skan      dump_type_prefix (TREE_TYPE (t), flags);
536169689Skan      pp_maybe_space (cxx_pp);
537169689Skan      pp_cxx_left_paren (cxx_pp);
53818334Speter      break;
53918334Speter
54018334Speter    case METHOD_TYPE:
541169689Skan      dump_type_prefix (TREE_TYPE (t), flags);
542169689Skan      pp_maybe_space (cxx_pp);
543169689Skan      pp_cxx_left_paren (cxx_pp);
54490075Sobrien      dump_aggr_type (TYPE_METHOD_BASETYPE (t), flags);
545169689Skan      pp_cxx_colon_colon (cxx_pp);
54618334Speter      break;
54718334Speter
54818334Speter    case ARRAY_TYPE:
549169689Skan      dump_type_prefix (TREE_TYPE (t), flags);
55018334Speter      break;
55118334Speter
55218334Speter    case ENUMERAL_TYPE:
55318334Speter    case IDENTIFIER_NODE:
55418334Speter    case INTEGER_TYPE:
55518334Speter    case BOOLEAN_TYPE:
55618334Speter    case REAL_TYPE:
55718334Speter    case RECORD_TYPE:
55818334Speter    case TEMPLATE_TYPE_PARM:
55950397Sobrien    case TEMPLATE_TEMPLATE_PARM:
56090075Sobrien    case BOUND_TEMPLATE_TEMPLATE_PARM:
56118334Speter    case TREE_LIST:
56218334Speter    case TYPE_DECL:
56318334Speter    case TREE_VEC:
56418334Speter    case UNION_TYPE:
56518334Speter    case UNKNOWN_TYPE:
56618334Speter    case VOID_TYPE:
56750397Sobrien    case TYPENAME_TYPE:
56850397Sobrien    case COMPLEX_TYPE:
56990075Sobrien    case VECTOR_TYPE:
570117395Skan    case TYPEOF_TYPE:
57190075Sobrien      dump_type (t, flags);
572169689Skan      pp_base (cxx_pp)->padding = pp_before;
57318334Speter      break;
57490075Sobrien
57518334Speter    default:
576132718Skan      pp_unsupported_tree (cxx_pp, t);
57790075Sobrien      /* fall through.  */
57890075Sobrien    case ERROR_MARK:
579132718Skan      pp_identifier (cxx_pp, "<typeprefixerror>");
58090075Sobrien      break;
58118334Speter    }
58218334Speter}
58318334Speter
58490075Sobrien/* Dump the suffix of type T, under control of FLAGS.  This is the part
58590075Sobrien   which appears after the identifier (or function parms).  */
58690075Sobrien
58718334Speterstatic void
588132718Skandump_type_suffix (tree t, int flags)
58918334Speter{
59018334Speter  if (TYPE_PTRMEMFUNC_P (t))
59118334Speter    t = TYPE_PTRMEMFUNC_FN_TYPE (t);
59218334Speter
59318334Speter  switch (TREE_CODE (t))
59418334Speter    {
59518334Speter    case POINTER_TYPE:
59618334Speter    case REFERENCE_TYPE:
59718334Speter    case OFFSET_TYPE:
59818334Speter      if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
599169689Skan	pp_cxx_right_paren (cxx_pp);
60090075Sobrien      dump_type_suffix (TREE_TYPE (t), flags);
60118334Speter      break;
60218334Speter
603132718Skan      /* Can only be reached through function pointer.  */
60418334Speter    case FUNCTION_TYPE:
60518334Speter    case METHOD_TYPE:
60618334Speter      {
60718334Speter	tree arg;
608169689Skan	pp_cxx_right_paren (cxx_pp);
60918334Speter	arg = TYPE_ARG_TYPES (t);
61018334Speter	if (TREE_CODE (t) == METHOD_TYPE)
61118334Speter	  arg = TREE_CHAIN (arg);
61218334Speter
61352284Sobrien	/* Function pointers don't have default args.  Not in standard C++,
61452284Sobrien	   anyway; they may in g++, but we'll just pretend otherwise.  */
61590075Sobrien	dump_parameters (arg, flags & ~TFF_FUNCTION_DEFAULT_ARGUMENTS);
61652284Sobrien
61718334Speter	if (TREE_CODE (t) == METHOD_TYPE)
618169689Skan	  pp_cxx_cv_qualifier_seq
619169689Skan	    (cxx_pp, TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))));
620169689Skan	else
621169689Skan	  pp_cxx_cv_qualifier_seq(cxx_pp, t);
62290075Sobrien	dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags);
62390075Sobrien	dump_type_suffix (TREE_TYPE (t), flags);
62418334Speter	break;
62518334Speter      }
62618334Speter
62718334Speter    case ARRAY_TYPE:
628169689Skan      pp_maybe_space (cxx_pp);
629169689Skan      pp_cxx_left_bracket (cxx_pp);
63018334Speter      if (TYPE_DOMAIN (t))
63150397Sobrien	{
63290075Sobrien	  if (host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0))
633132718Skan	    pp_wide_integer
634169689Skan	      (cxx_pp, tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0) + 1);
63550397Sobrien	  else if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == MINUS_EXPR)
63690075Sobrien	    dump_expr (TREE_OPERAND (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0),
637169689Skan		       flags & ~TFF_EXPR_IN_PARENS);
63850397Sobrien	  else
63990075Sobrien	    dump_expr (fold (cp_build_binary_op
64050397Sobrien			     (PLUS_EXPR, TYPE_MAX_VALUE (TYPE_DOMAIN (t)),
64190075Sobrien			      integer_one_node)),
642169689Skan		       flags & ~TFF_EXPR_IN_PARENS);
64350397Sobrien	}
644169689Skan      pp_cxx_right_bracket (cxx_pp);
64590075Sobrien      dump_type_suffix (TREE_TYPE (t), flags);
64618334Speter      break;
64790075Sobrien
64818334Speter    case ENUMERAL_TYPE:
64918334Speter    case IDENTIFIER_NODE:
65018334Speter    case INTEGER_TYPE:
65118334Speter    case BOOLEAN_TYPE:
65218334Speter    case REAL_TYPE:
65318334Speter    case RECORD_TYPE:
65418334Speter    case TEMPLATE_TYPE_PARM:
65550397Sobrien    case TEMPLATE_TEMPLATE_PARM:
65690075Sobrien    case BOUND_TEMPLATE_TEMPLATE_PARM:
65718334Speter    case TREE_LIST:
65818334Speter    case TYPE_DECL:
65918334Speter    case TREE_VEC:
66018334Speter    case UNION_TYPE:
66118334Speter    case UNKNOWN_TYPE:
66218334Speter    case VOID_TYPE:
66350397Sobrien    case TYPENAME_TYPE:
66450397Sobrien    case COMPLEX_TYPE:
66590075Sobrien    case VECTOR_TYPE:
666117395Skan    case TYPEOF_TYPE:
66718334Speter      break;
66818334Speter
66918334Speter    default:
670132718Skan      pp_unsupported_tree (cxx_pp, t);
67190075Sobrien    case ERROR_MARK:
67290075Sobrien      /* Don't mark it here, we should have already done in
673169689Skan	 dump_type_prefix.  */
67490075Sobrien      break;
67518334Speter    }
67618334Speter}
67718334Speter
67850397Sobrienstatic void
679132718Skandump_global_iord (tree t)
68018334Speter{
68190075Sobrien  const char *p = NULL;
68218334Speter
68390075Sobrien  if (DECL_GLOBAL_CTOR_P (t))
68490075Sobrien    p = "initializers";
68590075Sobrien  else if (DECL_GLOBAL_DTOR_P (t))
68690075Sobrien    p = "destructors";
68718334Speter  else
688169689Skan    gcc_unreachable ();
68990075Sobrien
690132718Skan  pp_printf (pp_base (cxx_pp), "(static %s for %s)", p, input_filename);
69118334Speter}
69218334Speter
69318334Speterstatic void
694132718Skandump_simple_decl (tree t, tree type, int flags)
69550397Sobrien{
69690075Sobrien  if (flags & TFF_DECL_SPECIFIERS)
69750397Sobrien    {
698169689Skan      dump_type_prefix (type, flags);
699169689Skan      pp_maybe_space (cxx_pp);
70050397Sobrien    }
70190075Sobrien  if (!DECL_INITIAL (t) || TREE_CODE (DECL_INITIAL (t)) != TEMPLATE_PARM_INDEX)
70290075Sobrien    dump_scope (CP_DECL_CONTEXT (t), flags);
70350397Sobrien  if (DECL_NAME (t))
70490075Sobrien    dump_decl (DECL_NAME (t), flags);
70550397Sobrien  else
706132718Skan    pp_identifier (cxx_pp, "<anonymous>");
70790075Sobrien  if (flags & TFF_DECL_SPECIFIERS)
70890075Sobrien    dump_type_suffix (type, flags);
70950397Sobrien}
71050397Sobrien
71190075Sobrien/* Dump a human readable string for the decl T under control of FLAGS.  */
71290075Sobrien
71350397Sobrienstatic void
714132718Skandump_decl (tree t, int flags)
71518334Speter{
71618334Speter  if (t == NULL_TREE)
71718334Speter    return;
71818334Speter
71918334Speter  switch (TREE_CODE (t))
72018334Speter    {
72118334Speter    case TYPE_DECL:
722169689Skan      /* Don't say 'typedef class A' */
723169689Skan      if (DECL_ARTIFICIAL (t))
724169689Skan	{
725169689Skan	  if ((flags & TFF_DECL_SPECIFIERS)
726169689Skan	      && TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
727169689Skan	    /* Say `class T' not just `T'.  */
728169689Skan	    pp_cxx_identifier (cxx_pp, "class");
72950397Sobrien
730169689Skan	  dump_type (TREE_TYPE (t), flags);
731169689Skan	  break;
732169689Skan	}
73390075Sobrien      if (flags & TFF_DECL_SPECIFIERS)
734169689Skan	pp_cxx_identifier (cxx_pp, "typedef");
73590075Sobrien      dump_simple_decl (t, DECL_ORIGINAL_TYPE (t)
73690075Sobrien			? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t),
737169689Skan			flags);
73818334Speter      break;
73990075Sobrien
74018334Speter    case VAR_DECL:
74118334Speter      if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t)))
74218334Speter	{
743132718Skan	  pp_string (cxx_pp, "vtable for ");
744169689Skan	  gcc_assert (TYPE_P (DECL_CONTEXT (t)));
74590075Sobrien	  dump_type (DECL_CONTEXT (t), flags);
74618334Speter	  break;
74718334Speter	}
748132718Skan      /* Else fall through.  */
74918334Speter    case FIELD_DECL:
75018334Speter    case PARM_DECL:
75190075Sobrien      dump_simple_decl (t, TREE_TYPE (t), flags);
75218334Speter      break;
75318334Speter
75490075Sobrien    case RESULT_DECL:
755132718Skan      pp_string (cxx_pp, "<return value> ");
75690075Sobrien      dump_simple_decl (t, TREE_TYPE (t), flags);
75790075Sobrien      break;
75890075Sobrien
75918334Speter    case NAMESPACE_DECL:
760132718Skan      if (flags & TFF_DECL_SPECIFIERS)
761169689Skan	pp_cxx_declaration (cxx_pp, t);
76252284Sobrien      else
763169689Skan	{
764169689Skan	  dump_scope (CP_DECL_CONTEXT (t), flags);
765169689Skan	  if (DECL_NAME (t) == NULL_TREE)
766169689Skan	    pp_identifier (cxx_pp, "<unnamed>");
767169689Skan	  else
768169689Skan	    pp_cxx_tree_identifier (cxx_pp, DECL_NAME (t));
769169689Skan	}
77018334Speter      break;
77118334Speter
77250397Sobrien    case SCOPE_REF:
773146895Skan      pp_expression (cxx_pp, t);
77490075Sobrien      break;
77550397Sobrien
77618334Speter    case ARRAY_REF:
77790075Sobrien      dump_decl (TREE_OPERAND (t, 0), flags);
778169689Skan      pp_cxx_left_bracket (cxx_pp);
77990075Sobrien      dump_decl (TREE_OPERAND (t, 1), flags);
780169689Skan      pp_cxx_right_bracket (cxx_pp);
78118334Speter      break;
78218334Speter
78390075Sobrien      /* So that we can do dump_decl on an aggr type.  */
78418334Speter    case RECORD_TYPE:
78518334Speter    case UNION_TYPE:
78618334Speter    case ENUMERAL_TYPE:
78790075Sobrien      dump_type (t, flags);
78818334Speter      break;
78918334Speter
790132718Skan    case BIT_NOT_EXPR:
791132718Skan      /* This is a pseudo destructor call which has not been folded into
792169689Skan	 a PSEUDO_DTOR_EXPR yet.  */
793169689Skan      pp_cxx_complement (cxx_pp);
794132718Skan      dump_type (TREE_OPERAND (t, 0), flags);
795132718Skan      break;
796132718Skan
79718334Speter    case TYPE_EXPR:
798169689Skan      gcc_unreachable ();
79918334Speter      break;
80018334Speter
80118334Speter      /* These special cases are duplicated here so that other functions
80290075Sobrien	 can feed identifiers to error and get them demangled properly.  */
80318334Speter    case IDENTIFIER_NODE:
80490075Sobrien      if (IDENTIFIER_TYPENAME_P (t))
80590075Sobrien	{
806169689Skan	  pp_cxx_identifier (cxx_pp, "operator");
80790075Sobrien	  /* Not exactly IDENTIFIER_TYPE_VALUE.  */
80890075Sobrien	  dump_type (TREE_TYPE (t), flags);
80990075Sobrien	  break;
81090075Sobrien	}
81190075Sobrien      else
812169689Skan	pp_cxx_tree_identifier (cxx_pp, t);
81318334Speter      break;
81418334Speter
81552284Sobrien    case OVERLOAD:
816110611Skan      if (OVL_CHAIN (t))
817110611Skan	{
818110611Skan	  t = OVL_CURRENT (t);
819110611Skan	  if (DECL_CLASS_SCOPE_P (t))
820110611Skan	    {
821110611Skan	      dump_type (DECL_CONTEXT (t), flags);
822169689Skan	      pp_cxx_colon_colon (cxx_pp);
823110611Skan	    }
824110611Skan	  else if (DECL_CONTEXT (t))
825110611Skan	    {
826110611Skan	      dump_decl (DECL_CONTEXT (t), flags);
827169689Skan	      pp_cxx_colon_colon (cxx_pp);
828110611Skan	    }
829110611Skan	  dump_decl (DECL_NAME (t), flags);
830110611Skan	  break;
831110611Skan	}
832169689Skan
833110611Skan      /* If there's only one function, just treat it like an ordinary
834110611Skan	 FUNCTION_DECL.  */
83552284Sobrien      t = OVL_CURRENT (t);
83652284Sobrien      /* Fall through.  */
83752284Sobrien
83818334Speter    case FUNCTION_DECL:
839169689Skan      if (! DECL_LANG_SPECIFIC (t))
840169689Skan	pp_identifier (cxx_pp, "<built-in>");
841169689Skan      else if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t))
84290075Sobrien	dump_global_iord (t);
84318334Speter      else
844169689Skan	dump_function_decl (t, flags);
84518334Speter      break;
84618334Speter
84718334Speter    case TEMPLATE_DECL:
84890075Sobrien      dump_template_decl (t, flags);
84918334Speter      break;
85018334Speter
85150397Sobrien    case TEMPLATE_ID_EXPR:
85250397Sobrien      {
85350397Sobrien	tree name = TREE_OPERAND (t, 0);
854169689Skan
85550397Sobrien	if (is_overloaded_fn (name))
85650397Sobrien	  name = DECL_NAME (get_first_fn (name));
85790075Sobrien	dump_decl (name, flags);
858169689Skan	pp_cxx_begin_template_argument_list (cxx_pp);
859132718Skan	if (TREE_OPERAND (t, 1))
860132718Skan	  dump_template_argument_list (TREE_OPERAND (t, 1), flags);
861169689Skan	pp_cxx_end_template_argument_list (cxx_pp);
86250397Sobrien      }
86350397Sobrien      break;
86450397Sobrien
86518334Speter    case LABEL_DECL:
866169689Skan      pp_cxx_tree_identifier (cxx_pp, DECL_NAME (t));
86718334Speter      break;
86818334Speter
86918334Speter    case CONST_DECL:
87050397Sobrien      if ((TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == ENUMERAL_TYPE)
87150397Sobrien	  || (DECL_INITIAL (t) &&
87250397Sobrien	      TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_PARM_INDEX))
87390075Sobrien	dump_simple_decl (t, TREE_TYPE (t), flags);
87450397Sobrien      else if (DECL_NAME (t))
87590075Sobrien	dump_decl (DECL_NAME (t), flags);
87650397Sobrien      else if (DECL_INITIAL (t))
87790075Sobrien	dump_expr (DECL_INITIAL (t), flags | TFF_EXPR_IN_PARENS);
87818334Speter      else
879132718Skan	pp_identifier (cxx_pp, "<enumerator>");
88018334Speter      break;
88118334Speter
88250397Sobrien    case USING_DECL:
883169689Skan      pp_cxx_identifier (cxx_pp, "using");
884169689Skan      dump_type (USING_DECL_SCOPE (t), flags);
885169689Skan      pp_cxx_colon_colon (cxx_pp);
886117395Skan      dump_decl (DECL_NAME (t), flags);
88750397Sobrien      break;
88850397Sobrien
889117395Skan    case BASELINK:
890117395Skan      dump_decl (BASELINK_FUNCTIONS (t), flags);
891117395Skan      break;
892117395Skan
893132718Skan    case NON_DEPENDENT_EXPR:
894132718Skan      dump_expr (t, flags);
895132718Skan      break;
896132718Skan
897132718Skan    case TEMPLATE_TYPE_PARM:
898132718Skan      if (flags & TFF_DECL_SPECIFIERS)
899169689Skan	pp_cxx_declaration (cxx_pp, t);
900132718Skan      else
901169689Skan	pp_type_id (cxx_pp, t);
902132718Skan      break;
903132718Skan
904220150Smm    case UNBOUND_CLASS_TEMPLATE:
905220150Smm      dump_type (t, flags);
906220150Smm      break;
907220150Smm
90818334Speter    default:
909132718Skan      pp_unsupported_tree (cxx_pp, t);
910169689Skan      /* Fall through to error.  */
91190075Sobrien
91290075Sobrien    case ERROR_MARK:
913132718Skan      pp_identifier (cxx_pp, "<declaration error>");
91490075Sobrien      break;
91518334Speter    }
91618334Speter}
91718334Speter
91890075Sobrien/* Dump a template declaration T under control of FLAGS. This means the
91990075Sobrien   'template <...> leaders plus the 'class X' or 'void fn(...)' part.  */
92090075Sobrien
92190075Sobrienstatic void
922132718Skandump_template_decl (tree t, int flags)
92390075Sobrien{
92490075Sobrien  tree orig_parms = DECL_TEMPLATE_PARMS (t);
92590075Sobrien  tree parms;
92690075Sobrien  int i;
92790075Sobrien
92890075Sobrien  if (flags & TFF_TEMPLATE_HEADER)
92990075Sobrien    {
93090075Sobrien      for (parms = orig_parms = nreverse (orig_parms);
931169689Skan	   parms;
932169689Skan	   parms = TREE_CHAIN (parms))
933169689Skan	{
93490075Sobrien	  tree inner_parms = INNERMOST_TEMPLATE_PARMS (parms);
935169689Skan	  int len = TREE_VEC_LENGTH (inner_parms);
93690075Sobrien
937169689Skan	  pp_cxx_identifier (cxx_pp, "template");
938169689Skan	  pp_cxx_begin_template_argument_list (cxx_pp);
93990075Sobrien
94090075Sobrien	  /* If we've shown the template prefix, we'd better show the
94190075Sobrien	     parameters' and decl's type too.  */
94290075Sobrien	    flags |= TFF_DECL_SPECIFIERS;
94390075Sobrien
944169689Skan	  for (i = 0; i < len; i++)
945169689Skan	    {
946169689Skan	      if (i)
947169689Skan		pp_separate_with_comma (cxx_pp);
948169689Skan	      dump_template_parameter (TREE_VEC_ELT (inner_parms, i), flags);
949169689Skan	    }
950169689Skan	  pp_cxx_end_template_argument_list (cxx_pp);
951169689Skan	  pp_cxx_whitespace (cxx_pp);
952169689Skan	}
95390075Sobrien      nreverse(orig_parms);
95490075Sobrien
95590075Sobrien      if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
956117395Skan	/* Say `template<arg> class TT' not just `template<arg> TT'.  */
957169689Skan	pp_cxx_identifier (cxx_pp, "class");
95890075Sobrien    }
95990075Sobrien
96090075Sobrien  if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
96190075Sobrien    dump_type (TREE_TYPE (t),
962169689Skan	       ((flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
963169689Skan		| (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0)));
96490075Sobrien  else if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL)
96590075Sobrien    dump_decl (DECL_TEMPLATE_RESULT (t), flags | TFF_TEMPLATE_NAME);
96690075Sobrien  else
96790075Sobrien    {
968169689Skan      gcc_assert (TREE_TYPE (t));
969169689Skan      switch (NEXT_CODE (t))
970169689Skan	{
971169689Skan	case METHOD_TYPE:
972169689Skan	case FUNCTION_TYPE:
973169689Skan	  dump_function_decl (t, flags | TFF_TEMPLATE_NAME);
974169689Skan	  break;
975169689Skan	default:
976169689Skan	  /* This case can occur with some invalid code.  */
977169689Skan	  dump_type (TREE_TYPE (t),
978169689Skan		     (flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
979169689Skan		     | (flags & TFF_DECL_SPECIFIERS
980169689Skan			? TFF_CLASS_KEY_OR_ENUM : 0));
981169689Skan	}
98290075Sobrien    }
98390075Sobrien}
98490075Sobrien
98552284Sobrien/* Pretty print a function decl. There are several ways we want to print a
98690075Sobrien   function declaration. The TFF_ bits in FLAGS tells us how to behave.
98790075Sobrien   As error can only apply the '#' flag once to give 0 and 1 for V, there
988117395Skan   is %D which doesn't print the throw specs, and %F which does.  */
98918334Speter
99018334Speterstatic void
991132718Skandump_function_decl (tree t, int flags)
99218334Speter{
99350397Sobrien  tree fntype;
99450397Sobrien  tree parmtypes;
99518334Speter  tree cname = NULL_TREE;
99690075Sobrien  tree template_args = NULL_TREE;
99790075Sobrien  tree template_parms = NULL_TREE;
99890075Sobrien  int show_return = flags & TFF_RETURN_TYPE || flags & TFF_DECL_SPECIFIERS;
99918334Speter
100050397Sobrien  if (TREE_CODE (t) == TEMPLATE_DECL)
100150397Sobrien    t = DECL_TEMPLATE_RESULT (t);
100250397Sobrien
100390075Sobrien  /* Pretty print template instantiations only.  */
100490075Sobrien  if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t))
100590075Sobrien    {
100690075Sobrien      tree tmpl;
100790075Sobrien
100890075Sobrien      template_args = DECL_TI_ARGS (t);
100990075Sobrien      tmpl = most_general_template (t);
101090075Sobrien      if (tmpl && TREE_CODE (tmpl) == TEMPLATE_DECL)
101190075Sobrien	{
101290075Sobrien	  template_parms = DECL_TEMPLATE_PARMS (tmpl);
101390075Sobrien	  t = tmpl;
101490075Sobrien	}
101590075Sobrien    }
101690075Sobrien
101750397Sobrien  fntype = TREE_TYPE (t);
101890075Sobrien  parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);
101950397Sobrien
102052284Sobrien  if (DECL_CLASS_SCOPE_P (t))
102190075Sobrien    cname = DECL_CONTEXT (t);
1022132718Skan  /* This is for partially instantiated template methods.  */
102318334Speter  else if (TREE_CODE (fntype) == METHOD_TYPE)
102418334Speter    cname = TREE_TYPE (TREE_VALUE (parmtypes));
102518334Speter
102690075Sobrien  if (!(flags & TFF_DECL_SPECIFIERS))
102790075Sobrien    /* OK */;
102890075Sobrien  else if (DECL_STATIC_FUNCTION_P (t))
1029169689Skan    pp_cxx_identifier (cxx_pp, "static");
103090075Sobrien  else if (DECL_VIRTUAL_P (t))
1031169689Skan    pp_cxx_identifier (cxx_pp, "virtual");
103290075Sobrien
103390075Sobrien  /* Print the return type?  */
103490075Sobrien  if (show_return)
103590075Sobrien    show_return = !DECL_CONV_FN_P (t)  && !DECL_CONSTRUCTOR_P (t)
1036169689Skan		  && !DECL_DESTRUCTOR_P (t);
103790075Sobrien  if (show_return)
1038169689Skan    dump_type_prefix (TREE_TYPE (fntype), flags);
103918334Speter
104052284Sobrien  /* Print the function name.  */
104118334Speter  if (cname)
104218334Speter    {
104390075Sobrien      dump_type (cname, flags);
1044169689Skan      pp_cxx_colon_colon (cxx_pp);
104518334Speter    }
104690075Sobrien  else
104790075Sobrien    dump_scope (CP_DECL_CONTEXT (t), flags);
104890075Sobrien
104990075Sobrien  dump_function_name (t, flags);
105090075Sobrien
1051132718Skan  if (!(flags & TFF_NO_FUNCTION_ARGUMENTS))
105252284Sobrien    {
105390075Sobrien      dump_parameters (parmtypes, flags);
105418334Speter
105590075Sobrien      if (TREE_CODE (fntype) == METHOD_TYPE)
1056169689Skan	{
1057169689Skan	  pp_base (cxx_pp)->padding = pp_before;
1058169689Skan	  pp_cxx_cv_qualifier_seq
1059169689Skan	    (cxx_pp, TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))));
1060169689Skan	}
106118334Speter
106290075Sobrien      if (flags & TFF_EXCEPTION_SPECIFICATION)
1063169689Skan	{
1064169689Skan	  pp_base (cxx_pp)->padding = pp_before;
1065169689Skan	  dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), flags);
1066169689Skan	}
106718334Speter
106890075Sobrien      if (show_return)
106990075Sobrien	dump_type_suffix (TREE_TYPE (fntype), flags);
107090075Sobrien    }
107118334Speter
107290075Sobrien  /* If T is a template instantiation, dump the parameter binding.  */
107390075Sobrien  if (template_parms != NULL_TREE && template_args != NULL_TREE)
107418334Speter    {
1075169689Skan      pp_cxx_whitespace (cxx_pp);
1076169689Skan      pp_cxx_left_bracket (cxx_pp);
1077169689Skan      pp_cxx_identifier (cxx_pp, "with");
1078169689Skan      pp_cxx_whitespace (cxx_pp);
107990075Sobrien      dump_template_bindings (template_parms, template_args);
1080169689Skan      pp_cxx_right_bracket (cxx_pp);
108118334Speter    }
108218334Speter}
108318334Speter
108490075Sobrien/* Print a parameter list. If this is for a member function, the
108590075Sobrien   member object ptr (and any other hidden args) should have
1086117395Skan   already been removed.  */
108752284Sobrien
108852284Sobrienstatic void
1089132718Skandump_parameters (tree parmtypes, int flags)
109052284Sobrien{
109152284Sobrien  int first;
109252284Sobrien
1093169689Skan  pp_cxx_left_paren (cxx_pp);
109490075Sobrien
109552284Sobrien  for (first = 1; parmtypes != void_list_node;
109652284Sobrien       parmtypes = TREE_CHAIN (parmtypes))
109752284Sobrien    {
109852284Sobrien      if (!first)
1099169689Skan	pp_separate_with_comma (cxx_pp);
110052284Sobrien      first = 0;
110152284Sobrien      if (!parmtypes)
1102169689Skan	{
1103169689Skan	  pp_cxx_identifier (cxx_pp, "...");
1104169689Skan	  break;
1105169689Skan	}
110690075Sobrien      dump_type (TREE_VALUE (parmtypes), flags);
110790075Sobrien
110890075Sobrien      if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && TREE_PURPOSE (parmtypes))
1109169689Skan	{
1110169689Skan	  pp_cxx_whitespace (cxx_pp);
1111169689Skan	  pp_equal (cxx_pp);
1112169689Skan	  pp_cxx_whitespace (cxx_pp);
1113169689Skan	  dump_expr (TREE_PURPOSE (parmtypes), flags | TFF_EXPR_IN_PARENS);
1114169689Skan	}
111552284Sobrien    }
111652284Sobrien
1117169689Skan  pp_cxx_right_paren (cxx_pp);
111852284Sobrien}
111952284Sobrien
1120117395Skan/* Print an exception specification. T is the exception specification.  */
112152284Sobrien
112252284Sobrienstatic void
1123132718Skandump_exception_spec (tree t, int flags)
112452284Sobrien{
112552284Sobrien  if (t)
112652284Sobrien    {
1127169689Skan      pp_cxx_identifier (cxx_pp, "throw");
1128169689Skan      pp_cxx_whitespace (cxx_pp);
1129169689Skan      pp_cxx_left_paren (cxx_pp);
113052284Sobrien      if (TREE_VALUE (t) != NULL_TREE)
1131169689Skan	while (1)
1132169689Skan	  {
1133169689Skan	    dump_type (TREE_VALUE (t), flags);
1134169689Skan	    t = TREE_CHAIN (t);
1135169689Skan	    if (!t)
1136169689Skan	      break;
1137169689Skan	    pp_separate_with_comma (cxx_pp);
1138169689Skan	  }
1139169689Skan      pp_cxx_right_paren (cxx_pp);
114052284Sobrien    }
114152284Sobrien}
114252284Sobrien
114318334Speter/* Handle the function name for a FUNCTION_DECL node, grokking operators
114418334Speter   and destructors properly.  */
114550397Sobrien
114618334Speterstatic void
1147132718Skandump_function_name (tree t, int flags)
114818334Speter{
114918334Speter  tree name = DECL_NAME (t);
115018334Speter
1151169689Skan  /* We can get here with a decl that was synthesized by language-
1152169689Skan     independent machinery (e.g. coverage.c) in which case it won't
1153169689Skan     have a lang_specific structure attached and DECL_CONSTRUCTOR_P
1154169689Skan     will crash.  In this case it is safe just to print out the
1155169689Skan     literal name.  */
1156169689Skan  if (!DECL_LANG_SPECIFIC (t))
1157169689Skan    {
1158169689Skan      pp_cxx_tree_identifier (cxx_pp, name);
1159169689Skan      return;
1160169689Skan    }
1161169689Skan
1162117395Skan  if (TREE_CODE (t) == TEMPLATE_DECL)
1163117395Skan    t = DECL_TEMPLATE_RESULT (t);
1164117395Skan
116590075Sobrien  /* Don't let the user see __comp_ctor et al.  */
116690075Sobrien  if (DECL_CONSTRUCTOR_P (t)
116790075Sobrien      || DECL_DESTRUCTOR_P (t))
116890075Sobrien    name = constructor_name (DECL_CONTEXT (t));
116990075Sobrien
117052284Sobrien  if (DECL_DESTRUCTOR_P (t))
117118334Speter    {
1172169689Skan      pp_cxx_complement (cxx_pp);
117390075Sobrien      dump_decl (name, TFF_PLAIN_IDENTIFIER);
117418334Speter    }
117552284Sobrien  else if (DECL_CONV_FN_P (t))
117618334Speter    {
117718334Speter      /* This cannot use the hack that the operator's return
117818334Speter	 type is stashed off of its name because it may be
117918334Speter	 used for error reporting.  In the case of conflicting
118018334Speter	 declarations, both will have the same name, yet
118118334Speter	 the types will be different, hence the TREE_TYPE field
118218334Speter	 of the first name will be clobbered by the second.  */
1183169689Skan      pp_cxx_identifier (cxx_pp, "operator");
118490075Sobrien      dump_type (TREE_TYPE (TREE_TYPE (t)), flags);
118518334Speter    }
118618334Speter  else if (IDENTIFIER_OPNAME_P (name))
1187169689Skan    pp_cxx_tree_identifier (cxx_pp, name);
118818334Speter  else
118990075Sobrien    dump_decl (name, flags);
119050397Sobrien
1191169689Skan  if (DECL_TEMPLATE_INFO (t)
119290075Sobrien      && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t)
1193169689Skan      && (TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL
119452284Sobrien	  || PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t))))
119590075Sobrien    dump_template_parms (DECL_TEMPLATE_INFO (t), !DECL_USE_TEMPLATE (t), flags);
119690075Sobrien}
119790075Sobrien
119890075Sobrien/* Dump the template parameters from the template info INFO under control of
119990075Sobrien   FLAGS. PRIMARY indicates whether this is a primary template decl, or
120090075Sobrien   specialization (partial or complete). For partial specializations we show
120190075Sobrien   the specialized parameter values. For a primary template we show no
120290075Sobrien   decoration.  */
120390075Sobrien
120490075Sobrienstatic void
1205132718Skandump_template_parms (tree info, int primary, int flags)
120690075Sobrien{
120790075Sobrien  tree args = info ? TI_ARGS (info) : NULL_TREE;
120890075Sobrien
120990075Sobrien  if (primary && flags & TFF_TEMPLATE_NAME)
121090075Sobrien    return;
121190075Sobrien  flags &= ~(TFF_CLASS_KEY_OR_ENUM | TFF_TEMPLATE_NAME);
1212169689Skan  pp_cxx_begin_template_argument_list (cxx_pp);
121390075Sobrien
121490075Sobrien  /* Be careful only to print things when we have them, so as not
121590075Sobrien	 to crash producing error messages.  */
121690075Sobrien  if (args && !primary)
121750397Sobrien    {
1218132718Skan      int len, ix;
121950397Sobrien
1220132718Skan      if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
1221132718Skan	args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
1222169689Skan
1223132718Skan      len = TREE_VEC_LENGTH (args);
1224132718Skan
1225132718Skan      for (ix = 0; ix != len; ix++)
1226169689Skan	{
1227169689Skan	  tree arg = TREE_VEC_ELT (args, ix);
122890075Sobrien
1229169689Skan	  if (ix)
1230169689Skan	    pp_separate_with_comma (cxx_pp);
1231169689Skan
1232169689Skan	  if (!arg)
1233169689Skan	    pp_identifier (cxx_pp, "<template parameter error>");
1234169689Skan	  else
1235169689Skan	    dump_template_argument (arg, flags);
1236169689Skan	}
123750397Sobrien    }
123890075Sobrien  else if (primary)
123990075Sobrien    {
124090075Sobrien      tree tpl = TI_TEMPLATE (info);
124190075Sobrien      tree parms = DECL_TEMPLATE_PARMS (tpl);
124290075Sobrien      int len, ix;
124390075Sobrien
124490075Sobrien      parms = TREE_CODE (parms) == TREE_LIST ? TREE_VALUE (parms) : NULL_TREE;
124590075Sobrien      len = parms ? TREE_VEC_LENGTH (parms) : 0;
124690075Sobrien
124790075Sobrien      for (ix = 0; ix != len; ix++)
1248169689Skan	{
1249169689Skan	  tree parm;
125090075Sobrien
1251169689Skan          if (TREE_VEC_ELT (parms, ix) == error_mark_node)
1252169689Skan            {
1253169689Skan              pp_identifier (cxx_pp, "<template parameter error>");
1254169689Skan              continue;
1255169689Skan            }
125690075Sobrien
1257169689Skan          parm = TREE_VALUE (TREE_VEC_ELT (parms, ix));
1258169689Skan
1259169689Skan	  if (ix)
1260169689Skan	    pp_separate_with_comma (cxx_pp);
1261169689Skan
1262169689Skan	  dump_decl (parm, flags & ~TFF_DECL_SPECIFIERS);
1263169689Skan	}
126490075Sobrien    }
1265169689Skan  pp_cxx_end_template_argument_list (cxx_pp);
126618334Speter}
126718334Speter
1268132718Skan/* Print out a list of initializers (subr of dump_expr).  */
126918334Speter
127018334Speterstatic void
1271132718Skandump_expr_list (tree l, int flags)
127218334Speter{
127318334Speter  while (l)
127418334Speter    {
127590075Sobrien      dump_expr (TREE_VALUE (l), flags | TFF_EXPR_IN_PARENS);
127618334Speter      l = TREE_CHAIN (l);
127790075Sobrien      if (l)
1278132718Skan	pp_separate_with_comma (cxx_pp);
127918334Speter    }
128018334Speter}
128118334Speter
1282169689Skan/* Print out a vector of initializers (subr of dump_expr).  */
1283169689Skan
1284169689Skanstatic void
1285169689Skandump_expr_init_vec (VEC(constructor_elt,gc) *v, int flags)
1286169689Skan{
1287169689Skan  unsigned HOST_WIDE_INT idx;
1288169689Skan  tree value;
1289169689Skan
1290169689Skan  FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
1291169689Skan    {
1292169689Skan      dump_expr (value, flags | TFF_EXPR_IN_PARENS);
1293169689Skan      if (idx != VEC_length (constructor_elt, v) - 1)
1294169689Skan	pp_separate_with_comma (cxx_pp);
1295169689Skan    }
1296169689Skan}
1297169689Skan
1298169689Skan
1299169689Skan/* We've gotten an indirect REFERENCE (an OBJ_TYPE_REF) to a virtual
1300169689Skan   function.  Resolve it to a close relative -- in the sense of static
1301169689Skan   type -- variant being overridden.  That is close to what was written in
1302169689Skan   the source code.  Subroutine of dump_expr.  */
1303169689Skan
1304169689Skanstatic tree
1305169689Skanresolve_virtual_fun_from_obj_type_ref (tree ref)
1306169689Skan{
1307169689Skan  tree obj_type = TREE_TYPE (OBJ_TYPE_REF_OBJECT (ref));
1308220150Smm  HOST_WIDE_INT index = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1);
1309169689Skan  tree fun = BINFO_VIRTUALS (TYPE_BINFO (TREE_TYPE (obj_type)));
1310220150Smm  while (index)
1311220150Smm    {
1312169689Skan      fun = TREE_CHAIN (fun);
1313220150Smm      index -= (TARGET_VTABLE_USES_DESCRIPTORS
1314220150Smm		? TARGET_VTABLE_USES_DESCRIPTORS : 1);
1315220150Smm    }
1316169689Skan
1317169689Skan  return BV_FN (fun);
1318169689Skan}
1319169689Skan
1320117395Skan/* Print out an expression E under control of FLAGS.  */
132150397Sobrien
132218334Speterstatic void
1323132718Skandump_expr (tree t, int flags)
132418334Speter{
1325117395Skan  if (t == 0)
1326117395Skan    return;
1327169689Skan
132818334Speter  switch (TREE_CODE (t))
132918334Speter    {
133018334Speter    case VAR_DECL:
133118334Speter    case PARM_DECL:
133218334Speter    case FIELD_DECL:
133318334Speter    case CONST_DECL:
133418334Speter    case FUNCTION_DECL:
133550397Sobrien    case TEMPLATE_DECL:
133650397Sobrien    case NAMESPACE_DECL:
1337161651Skan    case LABEL_DECL:
133890075Sobrien    case OVERLOAD:
1339132718Skan    case IDENTIFIER_NODE:
1340132718Skan      dump_decl (t, (flags & ~TFF_DECL_SPECIFIERS) | TFF_NO_FUNCTION_ARGUMENTS);
134118334Speter      break;
134218334Speter
134318334Speter    case INTEGER_CST:
1344169689Skan    case REAL_CST:
1345132718Skan    case STRING_CST:
1346169689Skan      pp_constant (cxx_pp, t);
134718334Speter      break;
134818334Speter
1349132718Skan    case THROW_EXPR:
1350169689Skan      pp_cxx_identifier (cxx_pp, "throw");
1351132718Skan      dump_expr (TREE_OPERAND (t, 0), flags);
135218334Speter      break;
135318334Speter
135452284Sobrien    case PTRMEM_CST:
1355132718Skan      pp_ampersand (cxx_pp);
135690075Sobrien      dump_type (PTRMEM_CST_CLASS (t), flags);
1357169689Skan      pp_cxx_colon_colon (cxx_pp);
1358169689Skan      pp_cxx_tree_identifier (cxx_pp, DECL_NAME (PTRMEM_CST_MEMBER (t)));
135952284Sobrien      break;
136052284Sobrien
136118334Speter    case COMPOUND_EXPR:
1362169689Skan      pp_cxx_left_paren (cxx_pp);
136390075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1364132718Skan      pp_separate_with_comma (cxx_pp);
136590075Sobrien      dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1366169689Skan      pp_cxx_right_paren (cxx_pp);
136718334Speter      break;
136818334Speter
136918334Speter    case COND_EXPR:
1370169689Skan      pp_cxx_left_paren (cxx_pp);
137190075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1372132718Skan      pp_string (cxx_pp, " ? ");
137390075Sobrien      dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1374132718Skan      pp_string (cxx_pp, " : ");
137590075Sobrien      dump_expr (TREE_OPERAND (t, 2), flags | TFF_EXPR_IN_PARENS);
1376169689Skan      pp_cxx_right_paren (cxx_pp);
137718334Speter      break;
137818334Speter
137918334Speter    case SAVE_EXPR:
138018334Speter      if (TREE_HAS_CONSTRUCTOR (t))
138118334Speter	{
1382169689Skan	  pp_cxx_identifier (cxx_pp, "new");
1383169689Skan	  pp_cxx_whitespace (cxx_pp);
138490075Sobrien	  dump_type (TREE_TYPE (TREE_TYPE (t)), flags);
138518334Speter	}
138618334Speter      else
1387169689Skan	dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
138818334Speter      break;
138918334Speter
139050397Sobrien    case AGGR_INIT_EXPR:
139190075Sobrien      {
139290075Sobrien	tree fn = NULL_TREE;
139390075Sobrien
139490075Sobrien	if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
139590075Sobrien	  fn = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
139690075Sobrien
139790075Sobrien	if (fn && TREE_CODE (fn) == FUNCTION_DECL)
139890075Sobrien	  {
139990075Sobrien	    if (DECL_CONSTRUCTOR_P (fn))
1400169689Skan	      dump_type (DECL_CONTEXT (fn), flags);
140190075Sobrien	    else
140290075Sobrien	      dump_decl (fn, 0);
140390075Sobrien	  }
140490075Sobrien	else
140590075Sobrien	  dump_expr (TREE_OPERAND (t, 0), 0);
140690075Sobrien      }
1407169689Skan      pp_cxx_left_paren (cxx_pp);
140850397Sobrien      if (TREE_OPERAND (t, 1))
140990075Sobrien	dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags);
1410169689Skan      pp_cxx_right_paren (cxx_pp);
141118334Speter      break;
141218334Speter
141318334Speter    case CALL_EXPR:
141418334Speter      {
141518334Speter	tree fn = TREE_OPERAND (t, 0);
141618334Speter	tree args = TREE_OPERAND (t, 1);
141790075Sobrien
141818334Speter	if (TREE_CODE (fn) == ADDR_EXPR)
141918334Speter	  fn = TREE_OPERAND (fn, 0);
142018334Speter
1421169689Skan	/* Nobody is interested in seeing the guts of vcalls.  */
1422169689Skan	if (TREE_CODE (fn) == OBJ_TYPE_REF)
1423169689Skan	  fn = resolve_virtual_fun_from_obj_type_ref (fn);
1424169689Skan
142550397Sobrien	if (TREE_TYPE (fn) != NULL_TREE && NEXT_CODE (fn) == METHOD_TYPE)
142618334Speter	  {
142718334Speter	    tree ob = TREE_VALUE (args);
142818334Speter	    if (TREE_CODE (ob) == ADDR_EXPR)
142918334Speter	      {
143090075Sobrien		dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS);
1431220150Smm		pp_cxx_dot (cxx_pp);
143218334Speter	      }
143318334Speter	    else if (TREE_CODE (ob) != PARM_DECL
143418334Speter		     || strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this"))
143518334Speter	      {
143690075Sobrien		dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
1437220150Smm		pp_cxx_arrow (cxx_pp);
143818334Speter	      }
143918334Speter	    args = TREE_CHAIN (args);
144018334Speter	  }
144190075Sobrien	dump_expr (fn, flags | TFF_EXPR_IN_PARENS);
1442169689Skan	pp_cxx_left_paren (cxx_pp);
144390075Sobrien	dump_expr_list (args, flags);
1444169689Skan	pp_cxx_right_paren (cxx_pp);
144518334Speter      }
144618334Speter      break;
144718334Speter
144850397Sobrien    case NEW_EXPR:
144950397Sobrien      {
145050397Sobrien	tree type = TREE_OPERAND (t, 1);
1451117395Skan	tree init = TREE_OPERAND (t, 2);
145250397Sobrien	if (NEW_EXPR_USE_GLOBAL (t))
1453169689Skan	  pp_cxx_colon_colon (cxx_pp);
1454169689Skan	pp_cxx_identifier (cxx_pp, "new");
145550397Sobrien	if (TREE_OPERAND (t, 0))
145650397Sobrien	  {
1457169689Skan	    pp_cxx_left_paren (cxx_pp);
145890075Sobrien	    dump_expr_list (TREE_OPERAND (t, 0), flags);
1459169689Skan	    pp_cxx_right_paren (cxx_pp);
1460169689Skan	    pp_cxx_whitespace (cxx_pp);
146150397Sobrien	  }
146250397Sobrien	if (TREE_CODE (type) == ARRAY_REF)
146350397Sobrien	  type = build_cplus_array_type
146450397Sobrien	    (TREE_OPERAND (type, 0),
1465169689Skan	     build_index_type (fold_build2 (MINUS_EXPR, integer_type_node,
146690075Sobrien					    TREE_OPERAND (type, 1),
1467169689Skan					    integer_one_node)));
146890075Sobrien	dump_type (type, flags);
1469117395Skan	if (init)
147050397Sobrien	  {
1471169689Skan	    pp_cxx_left_paren (cxx_pp);
1472117395Skan	    if (TREE_CODE (init) == TREE_LIST)
1473117395Skan	      dump_expr_list (init, flags);
1474117395Skan	    else if (init == void_zero_node)
1475117395Skan	      /* This representation indicates an empty initializer,
1476117395Skan		 e.g.: "new int()".  */
1477117395Skan	      ;
1478117395Skan	    else
1479117395Skan	      dump_expr (init, flags);
1480169689Skan	    pp_cxx_right_paren (cxx_pp);
148150397Sobrien	  }
148250397Sobrien      }
148318334Speter      break;
148418334Speter
148518334Speter    case TARGET_EXPR:
148618334Speter      /* Note that this only works for G++ target exprs.  If somebody
148718334Speter	 builds a general TARGET_EXPR, there's no way to represent that
148818334Speter	 it initializes anything other that the parameter slot for the
148918334Speter	 default argument.  Note we may have cleared out the first
149018334Speter	 operand in expand_expr, so don't go killing ourselves.  */
149118334Speter      if (TREE_OPERAND (t, 1))
149290075Sobrien	dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
149318334Speter      break;
149418334Speter
149590075Sobrien    case INIT_EXPR:
149618334Speter    case MODIFY_EXPR:
149718334Speter    case PLUS_EXPR:
149818334Speter    case MINUS_EXPR:
149918334Speter    case MULT_EXPR:
150018334Speter    case TRUNC_DIV_EXPR:
150118334Speter    case TRUNC_MOD_EXPR:
150218334Speter    case MIN_EXPR:
150318334Speter    case MAX_EXPR:
150418334Speter    case LSHIFT_EXPR:
150518334Speter    case RSHIFT_EXPR:
150618334Speter    case BIT_IOR_EXPR:
150718334Speter    case BIT_XOR_EXPR:
150818334Speter    case BIT_AND_EXPR:
150918334Speter    case TRUTH_ANDIF_EXPR:
151018334Speter    case TRUTH_ORIF_EXPR:
151118334Speter    case LT_EXPR:
151218334Speter    case LE_EXPR:
151318334Speter    case GT_EXPR:
151418334Speter    case GE_EXPR:
151518334Speter    case EQ_EXPR:
151618334Speter    case NE_EXPR:
151790075Sobrien    case EXACT_DIV_EXPR:
151890075Sobrien      dump_binary_op (operator_name_info[(int) TREE_CODE (t)].name, t, flags);
151918334Speter      break;
152018334Speter
152118334Speter    case CEIL_DIV_EXPR:
152218334Speter    case FLOOR_DIV_EXPR:
152318334Speter    case ROUND_DIV_EXPR:
1524146895Skan    case RDIV_EXPR:
152590075Sobrien      dump_binary_op ("/", t, flags);
152618334Speter      break;
152718334Speter
152818334Speter    case CEIL_MOD_EXPR:
152918334Speter    case FLOOR_MOD_EXPR:
153018334Speter    case ROUND_MOD_EXPR:
153190075Sobrien      dump_binary_op ("%", t, flags);
153218334Speter      break;
153318334Speter
153418334Speter    case COMPONENT_REF:
153518334Speter      {
153618334Speter	tree ob = TREE_OPERAND (t, 0);
153718334Speter	if (TREE_CODE (ob) == INDIRECT_REF)
153818334Speter	  {
153918334Speter	    ob = TREE_OPERAND (ob, 0);
154018334Speter	    if (TREE_CODE (ob) != PARM_DECL
1541169689Skan		|| (DECL_NAME (ob)
1542169689Skan		    && strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this")))
154318334Speter	      {
154490075Sobrien		dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
1545169689Skan		pp_cxx_arrow (cxx_pp);
154618334Speter	      }
154718334Speter	  }
154818334Speter	else
154918334Speter	  {
155090075Sobrien	    dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
1551169689Skan	    pp_cxx_dot (cxx_pp);
155218334Speter	  }
155390075Sobrien	dump_expr (TREE_OPERAND (t, 1), flags & ~TFF_EXPR_IN_PARENS);
155418334Speter      }
155518334Speter      break;
155618334Speter
155718334Speter    case ARRAY_REF:
155890075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1559169689Skan      pp_cxx_left_bracket (cxx_pp);
156090075Sobrien      dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1561169689Skan      pp_cxx_right_bracket (cxx_pp);
156218334Speter      break;
156318334Speter
1564169689Skan    case UNARY_PLUS_EXPR:
1565169689Skan      dump_unary_op ("+", t, flags);
156618334Speter      break;
156718334Speter
156818334Speter    case ADDR_EXPR:
156918334Speter      if (TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
157090075Sobrien	  || TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST
157190075Sobrien	  /* An ADDR_EXPR can have reference type.  In that case, we
157290075Sobrien	     shouldn't print the `&' doing so indicates to the user
157390075Sobrien	     that the expression has pointer type.  */
157490075Sobrien	  || (TREE_TYPE (t)
157590075Sobrien	      && TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE))
157690075Sobrien	dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1577161651Skan      else if (TREE_CODE (TREE_OPERAND (t, 0)) == LABEL_DECL)
1578161651Skan	dump_unary_op ("&&", t, flags);
157918334Speter      else
158090075Sobrien	dump_unary_op ("&", t, flags);
158118334Speter      break;
158218334Speter
158318334Speter    case INDIRECT_REF:
158418334Speter      if (TREE_HAS_CONSTRUCTOR (t))
158518334Speter	{
158618334Speter	  t = TREE_OPERAND (t, 0);
1587169689Skan	  gcc_assert (TREE_CODE (t) == CALL_EXPR);
158890075Sobrien	  dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1589169689Skan	  pp_cxx_left_paren (cxx_pp);
159090075Sobrien	  dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags);
1591169689Skan	  pp_cxx_right_paren (cxx_pp);
159218334Speter	}
159318334Speter      else
159418334Speter	{
159550397Sobrien	  if (TREE_OPERAND (t,0) != NULL_TREE
159652284Sobrien	      && TREE_TYPE (TREE_OPERAND (t, 0))
159750397Sobrien	      && NEXT_CODE (TREE_OPERAND (t, 0)) == REFERENCE_TYPE)
159890075Sobrien	    dump_expr (TREE_OPERAND (t, 0), flags);
159918334Speter	  else
160090075Sobrien	    dump_unary_op ("*", t, flags);
160118334Speter	}
160218334Speter      break;
160318334Speter
160418334Speter    case NEGATE_EXPR:
160518334Speter    case BIT_NOT_EXPR:
160618334Speter    case TRUTH_NOT_EXPR:
160718334Speter    case PREDECREMENT_EXPR:
160818334Speter    case PREINCREMENT_EXPR:
160990075Sobrien      dump_unary_op (operator_name_info [(int)TREE_CODE (t)].name, t, flags);
161018334Speter      break;
161118334Speter
161218334Speter    case POSTDECREMENT_EXPR:
161318334Speter    case POSTINCREMENT_EXPR:
1614169689Skan      pp_cxx_left_paren (cxx_pp);
161590075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1616169689Skan      pp_cxx_identifier (cxx_pp, operator_name_info[(int)TREE_CODE (t)].name);
1617169689Skan      pp_cxx_right_paren (cxx_pp);
161818334Speter      break;
161918334Speter
162018334Speter    case NON_LVALUE_EXPR:
162118334Speter      /* FIXME: This is a KLUDGE workaround for a parsing problem.  There
162218334Speter	 should be another level of INDIRECT_REF so that I don't have to do
162318334Speter	 this.  */
162450397Sobrien      if (TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == POINTER_TYPE)
162518334Speter	{
162618334Speter	  tree next = TREE_TYPE (TREE_TYPE (t));
162718334Speter
162818334Speter	  while (TREE_CODE (next) == POINTER_TYPE)
162918334Speter	    next = TREE_TYPE (next);
163090075Sobrien
163118334Speter	  if (TREE_CODE (next) == FUNCTION_TYPE)
163218334Speter	    {
163390075Sobrien	      if (flags & TFF_EXPR_IN_PARENS)
1634169689Skan		pp_cxx_left_paren (cxx_pp);
1635169689Skan	      pp_cxx_star (cxx_pp);
163690075Sobrien	      dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
163790075Sobrien	      if (flags & TFF_EXPR_IN_PARENS)
1638169689Skan		pp_cxx_right_paren (cxx_pp);
163918334Speter	      break;
164018334Speter	    }
1641132718Skan	  /* Else fall through.  */
164218334Speter	}
164390075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
164418334Speter      break;
164518334Speter
164618334Speter    case NOP_EXPR:
1647169689Skan    case CONVERT_EXPR:
1648132718Skan      {
1649132718Skan	tree op = TREE_OPERAND (t, 0);
1650169689Skan
1651132718Skan	if (!same_type_p (TREE_TYPE (op), TREE_TYPE (t)))
1652132718Skan	  {
1653132718Skan	    /* It is a cast, but we cannot tell whether it is a
1654132718Skan	       reinterpret or static cast. Use the C style notation.  */
1655132718Skan	    if (flags & TFF_EXPR_IN_PARENS)
1656169689Skan	      pp_cxx_left_paren (cxx_pp);
1657169689Skan	    pp_cxx_left_paren (cxx_pp);
1658132718Skan	    dump_type (TREE_TYPE (t), flags);
1659169689Skan	    pp_cxx_right_paren (cxx_pp);
1660132718Skan	    dump_expr (op, flags | TFF_EXPR_IN_PARENS);
1661132718Skan	    if (flags & TFF_EXPR_IN_PARENS)
1662169689Skan	      pp_cxx_right_paren (cxx_pp);
1663132718Skan	  }
1664132718Skan	else
1665132718Skan	  dump_expr (op, flags);
1666132718Skan	break;
1667132718Skan      }
166890075Sobrien
166918334Speter    case CONSTRUCTOR:
167050397Sobrien      if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
167150397Sobrien	{
1672117395Skan	  tree idx = build_ptrmemfunc_access_expr (t, pfn_identifier);
167350397Sobrien
167490075Sobrien	  if (integer_zerop (idx))
167550397Sobrien	    {
167652284Sobrien	      /* A NULL pointer-to-member constant.  */
1677169689Skan	      pp_cxx_left_paren (cxx_pp);
1678169689Skan	      pp_cxx_left_paren (cxx_pp);
167990075Sobrien	      dump_type (TREE_TYPE (t), flags);
1680169689Skan	      pp_cxx_right_paren (cxx_pp);
1681169689Skan	      pp_character (cxx_pp, '0');
1682169689Skan	      pp_cxx_right_paren (cxx_pp);
168352284Sobrien	      break;
168452284Sobrien	    }
168590075Sobrien	  else if (host_integerp (idx, 0))
168652284Sobrien	    {
168750397Sobrien	      tree virtuals;
168850397Sobrien	      unsigned HOST_WIDE_INT n;
168950397Sobrien
169050397Sobrien	      t = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)));
169150397Sobrien	      t = TYPE_METHOD_BASETYPE (t);
1692169689Skan	      virtuals = BINFO_VIRTUALS (TYPE_BINFO (TYPE_MAIN_VARIANT (t)));
169350397Sobrien
169490075Sobrien	      n = tree_low_cst (idx, 0);
169590075Sobrien
169650397Sobrien	      /* Map vtable index back one, to allow for the null pointer to
169750397Sobrien		 member.  */
169850397Sobrien	      --n;
169950397Sobrien
170050397Sobrien	      while (n > 0 && virtuals)
170150397Sobrien		{
170250397Sobrien		  --n;
170350397Sobrien		  virtuals = TREE_CHAIN (virtuals);
170450397Sobrien		}
170550397Sobrien	      if (virtuals)
170650397Sobrien		{
170790075Sobrien		  dump_expr (BV_FN (virtuals),
1708169689Skan			     flags | TFF_EXPR_IN_PARENS);
170950397Sobrien		  break;
171050397Sobrien		}
171150397Sobrien	    }
171250397Sobrien	}
1713169689Skan      if (TREE_TYPE (t) && EMPTY_CONSTRUCTOR_P (t))
1714132718Skan	{
1715132718Skan	  dump_type (TREE_TYPE (t), 0);
1716169689Skan	  pp_cxx_left_paren (cxx_pp);
1717169689Skan	  pp_cxx_right_paren (cxx_pp);
1718132718Skan	}
1719117395Skan      else
1720132718Skan	{
1721169689Skan	  pp_cxx_left_brace (cxx_pp);
1722169689Skan	  dump_expr_init_vec (CONSTRUCTOR_ELTS (t), flags);
1723169689Skan	  pp_cxx_right_brace (cxx_pp);
1724132718Skan	}
1725169689Skan
172618334Speter      break;
172718334Speter
172818334Speter    case OFFSET_REF:
172918334Speter      {
173018334Speter	tree ob = TREE_OPERAND (t, 0);
173152284Sobrien	if (is_dummy_object (ob))
173252284Sobrien	  {
173352284Sobrien	    t = TREE_OPERAND (t, 1);
173452284Sobrien	    if (TREE_CODE (t) == FUNCTION_DECL)
173552284Sobrien	      /* A::f */
173690075Sobrien	      dump_expr (t, flags | TFF_EXPR_IN_PARENS);
173752284Sobrien	    else if (BASELINK_P (t))
1738169689Skan	      dump_expr (OVL_CURRENT (BASELINK_FUNCTIONS (t)),
1739117395Skan			 flags | TFF_EXPR_IN_PARENS);
174052284Sobrien	    else
174190075Sobrien	      dump_decl (t, flags);
174252284Sobrien	  }
174318334Speter	else
174418334Speter	  {
174552284Sobrien	    if (TREE_CODE (ob) == INDIRECT_REF)
174652284Sobrien	      {
174790075Sobrien		dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS);
1748169689Skan		pp_cxx_arrow (cxx_pp);
1749169689Skan		pp_cxx_star (cxx_pp);
175052284Sobrien	      }
175152284Sobrien	    else
175252284Sobrien	      {
175390075Sobrien		dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
1754169689Skan		pp_cxx_dot (cxx_pp);
1755169689Skan		pp_cxx_star (cxx_pp);
175652284Sobrien	      }
175790075Sobrien	    dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
175818334Speter	  }
175918334Speter	break;
176018334Speter      }
176118334Speter
176250397Sobrien    case TEMPLATE_PARM_INDEX:
176390075Sobrien      dump_decl (TEMPLATE_PARM_DECL (t), flags & ~TFF_DECL_SPECIFIERS);
176450397Sobrien      break;
176550397Sobrien
176650397Sobrien    case SCOPE_REF:
1767146895Skan      pp_expression (cxx_pp, t);
176850397Sobrien      break;
176950397Sobrien
177050397Sobrien    case CAST_EXPR:
177150397Sobrien      if (TREE_OPERAND (t, 0) == NULL_TREE
177250397Sobrien	  || TREE_CHAIN (TREE_OPERAND (t, 0)))
177350397Sobrien	{
177490075Sobrien	  dump_type (TREE_TYPE (t), flags);
1775169689Skan	  pp_cxx_left_paren (cxx_pp);
177690075Sobrien	  dump_expr_list (TREE_OPERAND (t, 0), flags);
1777169689Skan	  pp_cxx_right_paren (cxx_pp);
177850397Sobrien	}
177950397Sobrien      else
178050397Sobrien	{
1781169689Skan	  pp_cxx_left_paren (cxx_pp);
178290075Sobrien	  dump_type (TREE_TYPE (t), flags);
1783169689Skan	  pp_cxx_right_paren (cxx_pp);
1784169689Skan	  pp_cxx_left_paren (cxx_pp);
178590075Sobrien	  dump_expr_list (TREE_OPERAND (t, 0), flags);
1786169689Skan	  pp_cxx_right_paren (cxx_pp);
178750397Sobrien	}
178850397Sobrien      break;
178950397Sobrien
179090075Sobrien    case STATIC_CAST_EXPR:
1791169689Skan      pp_cxx_identifier (cxx_pp, "static_cast");
179290075Sobrien      goto cast;
179390075Sobrien    case REINTERPRET_CAST_EXPR:
1794169689Skan      pp_cxx_identifier (cxx_pp, "reinterpret_cast");
179590075Sobrien      goto cast;
179690075Sobrien    case CONST_CAST_EXPR:
1797169689Skan      pp_cxx_identifier (cxx_pp, "const_cast");
179890075Sobrien      goto cast;
179990075Sobrien    case DYNAMIC_CAST_EXPR:
1800169689Skan      pp_cxx_identifier (cxx_pp, "dynamic_cast");
180190075Sobrien    cast:
1802169689Skan      pp_cxx_begin_template_argument_list (cxx_pp);
180390075Sobrien      dump_type (TREE_TYPE (t), flags);
1804169689Skan      pp_cxx_end_template_argument_list (cxx_pp);
1805169689Skan      pp_cxx_left_paren (cxx_pp);
180690075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags);
1807169689Skan      pp_cxx_right_paren (cxx_pp);
180890075Sobrien      break;
180990075Sobrien
181050397Sobrien    case ARROW_EXPR:
181190075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags);
1812169689Skan      pp_cxx_arrow (cxx_pp);
181350397Sobrien      break;
181450397Sobrien
181550397Sobrien    case SIZEOF_EXPR:
181650397Sobrien    case ALIGNOF_EXPR:
181750397Sobrien      if (TREE_CODE (t) == SIZEOF_EXPR)
1818169689Skan	pp_cxx_identifier (cxx_pp, "sizeof");
181990075Sobrien      else
182050397Sobrien	{
1821169689Skan	  gcc_assert (TREE_CODE (t) == ALIGNOF_EXPR);
1822169689Skan	  pp_cxx_identifier (cxx_pp, "__alignof__");
182350397Sobrien	}
1824169689Skan      pp_cxx_whitespace (cxx_pp);
1825169689Skan      pp_cxx_left_paren (cxx_pp);
182690075Sobrien      if (TYPE_P (TREE_OPERAND (t, 0)))
182790075Sobrien	dump_type (TREE_OPERAND (t, 0), flags);
182850397Sobrien      else
1829169689Skan	dump_expr (TREE_OPERAND (t, 0), flags);
1830169689Skan      pp_cxx_right_paren (cxx_pp);
183150397Sobrien      break;
183250397Sobrien
1833132718Skan    case REALPART_EXPR:
1834132718Skan    case IMAGPART_EXPR:
1835169689Skan      pp_cxx_identifier (cxx_pp, operator_name_info[TREE_CODE (t)].name);
1836169689Skan      pp_cxx_whitespace (cxx_pp);
1837132718Skan      dump_expr (TREE_OPERAND (t, 0), flags);
1838132718Skan      break;
1839132718Skan
184050397Sobrien    case DEFAULT_ARG:
1841132718Skan      pp_identifier (cxx_pp, "<unparsed>");
184250397Sobrien      break;
184350397Sobrien
184450397Sobrien    case TRY_CATCH_EXPR:
184550397Sobrien    case WITH_CLEANUP_EXPR:
184650397Sobrien    case CLEANUP_POINT_EXPR:
184790075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags);
184850397Sobrien      break;
184950397Sobrien
185090075Sobrien    case PSEUDO_DTOR_EXPR:
185190075Sobrien      dump_expr (TREE_OPERAND (t, 2), flags);
1852169689Skan      pp_cxx_dot (cxx_pp);
185390075Sobrien      dump_type (TREE_OPERAND (t, 0), flags);
1854169689Skan      pp_cxx_colon_colon (cxx_pp);
1855169689Skan      pp_cxx_complement (cxx_pp);
185690075Sobrien      dump_type (TREE_OPERAND (t, 1), flags);
185790075Sobrien      break;
185890075Sobrien
185952284Sobrien    case TEMPLATE_ID_EXPR:
186090075Sobrien      dump_decl (t, flags);
186152284Sobrien      break;
186252284Sobrien
1863169689Skan    case BIND_EXPR:
186490075Sobrien    case STMT_EXPR:
1865169689Skan    case STATEMENT_LIST:
186690075Sobrien      /* We don't yet have a way of dumping statements in a
186790075Sobrien	 human-readable format.  */
1868132718Skan      pp_string (cxx_pp, "({...})");
186990075Sobrien      break;
187090075Sobrien
187190075Sobrien    case LOOP_EXPR:
1872132718Skan      pp_string (cxx_pp, "while (1) { ");
187390075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
1874169689Skan      pp_cxx_right_brace (cxx_pp);
187590075Sobrien      break;
187690075Sobrien
187790075Sobrien    case EXIT_EXPR:
1878132718Skan      pp_string (cxx_pp, "if (");
187990075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
1880132718Skan      pp_string (cxx_pp, ") break; ");
188190075Sobrien      break;
188290075Sobrien
1883117395Skan    case BASELINK:
1884132718Skan      dump_expr (get_first_fn (t), flags & ~TFF_EXPR_IN_PARENS);
1885117395Skan      break;
1886117395Skan
1887132718Skan    case EMPTY_CLASS_EXPR:
1888132718Skan      dump_type (TREE_TYPE (t), flags);
1889169689Skan      pp_cxx_left_paren (cxx_pp);
1890169689Skan      pp_cxx_right_paren (cxx_pp);
1891132718Skan      break;
189218334Speter
1893132718Skan    case NON_DEPENDENT_EXPR:
1894132718Skan      dump_expr (TREE_OPERAND (t, 0), flags);
1895132718Skan      break;
1896132718Skan
189718334Speter      /*  This list is incomplete, but should suffice for now.
189818334Speter	  It is very important that `sorry' does not call
189918334Speter	  `report_error_function'.  That could cause an infinite loop.  */
190018334Speter    default:
1901132718Skan      pp_unsupported_tree (cxx_pp, t);
190218334Speter      /* fall through to ERROR_MARK...  */
190318334Speter    case ERROR_MARK:
1904132718Skan      pp_identifier (cxx_pp, "<expression error>");
190518334Speter      break;
190618334Speter    }
190718334Speter}
190818334Speter
190918334Speterstatic void
1910132718Skandump_binary_op (const char *opstring, tree t, int flags)
191118334Speter{
1912169689Skan  pp_cxx_left_paren (cxx_pp);
191390075Sobrien  dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1914169689Skan  pp_cxx_whitespace (cxx_pp);
191590075Sobrien  if (opstring)
1916169689Skan    pp_cxx_identifier (cxx_pp, opstring);
191790075Sobrien  else
1918132718Skan    pp_identifier (cxx_pp, "<unknown operator>");
1919169689Skan  pp_cxx_whitespace (cxx_pp);
192090075Sobrien  dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1921169689Skan  pp_cxx_right_paren (cxx_pp);
192218334Speter}
192318334Speter
192418334Speterstatic void
1925132718Skandump_unary_op (const char *opstring, tree t, int flags)
192618334Speter{
192790075Sobrien  if (flags & TFF_EXPR_IN_PARENS)
1928169689Skan    pp_cxx_left_paren (cxx_pp);
1929169689Skan  pp_cxx_identifier (cxx_pp, opstring);
193090075Sobrien  dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
193190075Sobrien  if (flags & TFF_EXPR_IN_PARENS)
1932169689Skan    pp_cxx_right_paren (cxx_pp);
193318334Speter}
193418334Speter
1935169689Skanstatic void
1936169689Skanreinit_cxx_pp (void)
1937169689Skan{
1938169689Skan  pp_clear_output_area (cxx_pp);
1939169689Skan  pp_base (cxx_pp)->padding = pp_none;
1940169689Skan  pp_indentation (cxx_pp) = 0;
1941169689Skan  pp_needs_newline (cxx_pp) = false;
1942169689Skan  cxx_pp->enclosing_scope = 0;
1943169689Skan}
1944169689Skan
1945169689Skan
194690075Sobrien/* Exported interface to stringifying types, exprs and decls under TFF_*
194790075Sobrien   control.  */
194852284Sobrien
194990075Sobrienconst char *
1950132718Skantype_as_string (tree typ, int flags)
195118334Speter{
1952169689Skan  reinit_cxx_pp ();
195390075Sobrien  dump_type (typ, flags);
1954132718Skan  return pp_formatted_text (cxx_pp);
195518334Speter}
195618334Speter
195790075Sobrienconst char *
1958132718Skanexpr_as_string (tree decl, int flags)
195918334Speter{
1960169689Skan  reinit_cxx_pp ();
196190075Sobrien  dump_expr (decl, flags);
1962132718Skan  return pp_formatted_text (cxx_pp);
196318334Speter}
196418334Speter
196590075Sobrienconst char *
1966132718Skandecl_as_string (tree decl, int flags)
196718334Speter{
1968169689Skan  reinit_cxx_pp ();
196990075Sobrien  dump_decl (decl, flags);
1970132718Skan  return pp_formatted_text (cxx_pp);
197118334Speter}
197218334Speter
1973117395Skan/* Generate the three forms of printable names for cxx_printable_name.  */
197450397Sobrien
197590075Sobrienconst char *
1976132718Skanlang_decl_name (tree decl, int v)
197750397Sobrien{
197850397Sobrien  if (v >= 2)
197990075Sobrien    return decl_as_string (decl, TFF_DECL_SPECIFIERS);
198050397Sobrien
1981169689Skan  reinit_cxx_pp ();
198250397Sobrien  if (v == 1 && DECL_CLASS_SCOPE_P (decl))
198350397Sobrien    {
198490075Sobrien      dump_type (CP_DECL_CONTEXT (decl), TFF_PLAIN_IDENTIFIER);
1985169689Skan      pp_cxx_colon_colon (cxx_pp);
198650397Sobrien    }
198750397Sobrien
198850397Sobrien  if (TREE_CODE (decl) == FUNCTION_DECL)
198990075Sobrien    dump_function_name (decl, TFF_PLAIN_IDENTIFIER);
199050397Sobrien  else
199190075Sobrien    dump_decl (DECL_NAME (decl), TFF_PLAIN_IDENTIFIER);
199250397Sobrien
1993132718Skan  return pp_formatted_text (cxx_pp);
199450397Sobrien}
199550397Sobrien
1996169689Skan/* Return the location of a tree passed to %+ formats.  */
1997169689Skan
1998132718Skanstatic location_t
1999132718Skanlocation_of (tree t)
200018334Speter{
200150397Sobrien  if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t))
2002132718Skan    t = DECL_CONTEXT (t);
200390075Sobrien  else if (TYPE_P (t))
2004132718Skan    t = TYPE_MAIN_DECL (t);
200552284Sobrien  else if (TREE_CODE (t) == OVERLOAD)
2006132718Skan    t = OVL_FUNCTION (t);
2007169689Skan
2008132718Skan  return DECL_SOURCE_LOCATION (t);
200918334Speter}
201018334Speter
201190075Sobrien/* Now the interfaces from error et al to dump_type et al. Each takes an
201290075Sobrien   on/off VERBOSE flag and supply the appropriate TFF_ flags to a dump_
201390075Sobrien   function.  */
201490075Sobrien
201590075Sobrienstatic const char *
2016132718Skandecl_to_string (tree decl, int verbose)
201790075Sobrien{
201890075Sobrien  int flags = 0;
201990075Sobrien
202090075Sobrien  if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == RECORD_TYPE
202190075Sobrien      || TREE_CODE (decl) == UNION_TYPE || TREE_CODE (decl) == ENUMERAL_TYPE)
202290075Sobrien    flags = TFF_CLASS_KEY_OR_ENUM;
202390075Sobrien  if (verbose)
2024117395Skan    flags |= TFF_DECL_SPECIFIERS;
202590075Sobrien  else if (TREE_CODE (decl) == FUNCTION_DECL)
202690075Sobrien    flags |= TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE;
202790075Sobrien  flags |= TFF_TEMPLATE_HEADER;
202890075Sobrien
2029169689Skan  reinit_cxx_pp ();
203090075Sobrien  dump_decl (decl, flags);
2031132718Skan  return pp_formatted_text (cxx_pp);
203290075Sobrien}
203390075Sobrien
203490075Sobrienstatic const char *
2035132718Skanexpr_to_string (tree decl)
203690075Sobrien{
2037169689Skan  reinit_cxx_pp ();
203890075Sobrien  dump_expr (decl, 0);
2039132718Skan  return pp_formatted_text (cxx_pp);
204090075Sobrien}
204190075Sobrien
204290075Sobrienstatic const char *
2043132718Skanfndecl_to_string (tree fndecl, int verbose)
204490075Sobrien{
204590075Sobrien  int flags;
204690075Sobrien
2047169689Skan  flags = TFF_EXCEPTION_SPECIFICATION | TFF_DECL_SPECIFIERS
2048169689Skan    | TFF_TEMPLATE_HEADER;
204990075Sobrien  if (verbose)
205090075Sobrien    flags |= TFF_FUNCTION_DEFAULT_ARGUMENTS;
2051169689Skan  reinit_cxx_pp ();
205290075Sobrien  dump_decl (fndecl, flags);
2053132718Skan  return pp_formatted_text (cxx_pp);
205490075Sobrien}
205590075Sobrien
205690075Sobrien
205790075Sobrienstatic const char *
2058132718Skancode_to_string (enum tree_code c)
205918334Speter{
206018334Speter  return tree_code_name [c];
206118334Speter}
206218334Speter
206390075Sobrienconst char *
2064132718Skanlanguage_to_string (enum languages c)
206518334Speter{
206618334Speter  switch (c)
206718334Speter    {
206818334Speter    case lang_c:
206918334Speter      return "C";
207018334Speter
207118334Speter    case lang_cplusplus:
207218334Speter      return "C++";
207318334Speter
207450397Sobrien    case lang_java:
207550397Sobrien      return "Java";
207650397Sobrien
207718334Speter    default:
2078169689Skan      gcc_unreachable ();
207918334Speter    }
2080169689Skan  return NULL;
208118334Speter}
208218334Speter
208318334Speter/* Return the proper printed version of a parameter to a C++ function.  */
208450397Sobrien
208590075Sobrienstatic const char *
2086132718Skanparm_to_string (int p)
208718334Speter{
2088169689Skan  reinit_cxx_pp ();
208918334Speter  if (p < 0)
2090132718Skan    pp_string (cxx_pp, "'this'");
2091132718Skan  else
2092132718Skan    pp_decimal_int (cxx_pp, p + 1);
2093132718Skan  return pp_formatted_text (cxx_pp);
209418334Speter}
209518334Speter
209690075Sobrienstatic const char *
2097132718Skanop_to_string (enum tree_code p)
209818334Speter{
2099132718Skan  tree id = operator_name_info[(int) p].identifier;
2100132718Skan  return id ? IDENTIFIER_POINTER (id) : "<unknown>";
210118334Speter}
210218334Speter
210390075Sobrienstatic const char *
2104132718Skantype_to_string (tree typ, int verbose)
210590075Sobrien{
2106132718Skan  int flags = 0;
210790075Sobrien  if (verbose)
210890075Sobrien    flags |= TFF_CLASS_KEY_OR_ENUM;
210990075Sobrien  flags |= TFF_TEMPLATE_HEADER;
211090075Sobrien
2111169689Skan  reinit_cxx_pp ();
211290075Sobrien  dump_type (typ, flags);
2113132718Skan  return pp_formatted_text (cxx_pp);
211490075Sobrien}
211590075Sobrien
211690075Sobrienstatic const char *
2117132718Skanassop_to_string (enum tree_code p)
211850397Sobrien{
2119132718Skan  tree id = assignment_operator_name_info[(int) p].identifier;
212090075Sobrien  return id ? IDENTIFIER_POINTER (id) : "{unknown}";
212150397Sobrien}
212250397Sobrien
212390075Sobrienstatic const char *
2124132718Skanargs_to_string (tree p, int verbose)
212518334Speter{
212690075Sobrien  int flags = 0;
212790075Sobrien  if (verbose)
212890075Sobrien    flags |= TFF_CLASS_KEY_OR_ENUM;
212990075Sobrien
213018334Speter  if (p == NULL_TREE)
213150397Sobrien    return "";
213218334Speter
213390075Sobrien  if (TYPE_P (TREE_VALUE (p)))
213490075Sobrien    return type_as_string (p, flags);
213550397Sobrien
2136169689Skan  reinit_cxx_pp ();
213750397Sobrien  for (; p; p = TREE_CHAIN (p))
213850397Sobrien    {
213950397Sobrien      if (TREE_VALUE (p) == null_node)
2140169689Skan	pp_cxx_identifier (cxx_pp, "NULL");
214150397Sobrien      else
214290075Sobrien	dump_type (error_type (TREE_VALUE (p)), flags);
214350397Sobrien      if (TREE_CHAIN (p))
2144132718Skan	pp_separate_with_comma (cxx_pp);
214550397Sobrien    }
2146132718Skan  return pp_formatted_text (cxx_pp);
214718334Speter}
214818334Speter
214990075Sobrienstatic const char *
2150132718Skancv_to_string (tree p, int v)
215118334Speter{
2152169689Skan  reinit_cxx_pp ();
2153169689Skan  pp_base (cxx_pp)->padding = v ? pp_before : pp_none;
2154169689Skan  pp_cxx_cv_qualifier_seq (cxx_pp, p);
2155132718Skan  return pp_formatted_text (cxx_pp);
215690075Sobrien}
215718334Speter
2158117395Skan/* Langhook for print_error_function.  */
2159117395Skanvoid
2160132718Skancxx_print_error_function (diagnostic_context *context, const char *file)
216190075Sobrien{
2162117395Skan  lhd_print_error_function (context, file);
2163132718Skan  pp_base_set_prefix (context->printer, file);
2164117395Skan  maybe_print_instantiation_context (context);
216518334Speter}
216690075Sobrien
216790075Sobrienstatic void
2168132718Skancp_diagnostic_starter (diagnostic_context *context,
2169169689Skan		       diagnostic_info *diagnostic)
217090075Sobrien{
2171117395Skan  diagnostic_report_current_module (context);
2172117395Skan  cp_print_error_function (context, diagnostic);
2173117395Skan  maybe_print_instantiation_context (context);
2174132718Skan  pp_base_set_prefix (context->printer, diagnostic_build_prefix (diagnostic));
217590075Sobrien}
217690075Sobrien
217790075Sobrienstatic void
2178132718Skancp_diagnostic_finalizer (diagnostic_context *context,
2179169689Skan			 diagnostic_info *diagnostic ATTRIBUTE_UNUSED)
218090075Sobrien{
2181132718Skan  pp_base_destroy_prefix (context->printer);
218290075Sobrien}
218390075Sobrien
218490075Sobrien/* Print current function onto BUFFER, in the process of reporting
218590075Sobrien   a diagnostic message.  Called from cp_diagnostic_starter.  */
218690075Sobrienstatic void
2187132718Skancp_print_error_function (diagnostic_context *context,
2188169689Skan			 diagnostic_info *diagnostic)
218990075Sobrien{
2190117395Skan  if (diagnostic_last_function_changed (context))
219190075Sobrien    {
2192132718Skan      const char *old_prefix = context->printer->prefix;
2193169689Skan      const char *file = LOCATION_FILE (diagnostic->location);
2194169689Skan      char *new_prefix = file ? file_name_as_prefix (file) : NULL;
219590075Sobrien
2196132718Skan      pp_base_set_prefix (context->printer, new_prefix);
219790075Sobrien
219890075Sobrien      if (current_function_decl == NULL)
2199169689Skan	pp_base_string (context->printer, "At global scope:");
220090075Sobrien      else
2201169689Skan	pp_printf (context->printer, "In %s %qs:",
2202169689Skan		   function_category (current_function_decl),
2203169689Skan		   cxx_printable_name (current_function_decl, 2));
2204132718Skan      pp_base_newline (context->printer);
220590075Sobrien
2206117395Skan      diagnostic_set_last_function (context);
2207132718Skan      pp_base_destroy_prefix (context->printer);
2208132718Skan      context->printer->prefix = old_prefix;
220990075Sobrien    }
221090075Sobrien}
221190075Sobrien
221290075Sobrien/* Returns a description of FUNCTION using standard terminology.  */
221390075Sobrienstatic const char *
2214132718Skanfunction_category (tree fn)
221590075Sobrien{
221690075Sobrien  if (DECL_FUNCTION_MEMBER_P (fn))
221790075Sobrien    {
221890075Sobrien      if (DECL_STATIC_FUNCTION_P (fn))
2219169689Skan	return "static member function";
222090075Sobrien      else if (DECL_COPY_CONSTRUCTOR_P (fn))
2221169689Skan	return "copy constructor";
222290075Sobrien      else if (DECL_CONSTRUCTOR_P (fn))
2223169689Skan	return "constructor";
222490075Sobrien      else if (DECL_DESTRUCTOR_P (fn))
2225169689Skan	return "destructor";
222690075Sobrien      else
2227169689Skan	return "member function";
222890075Sobrien    }
222990075Sobrien  else
223090075Sobrien    return "function";
223190075Sobrien}
223290075Sobrien
223390075Sobrien/* Report the full context of a current template instantiation,
223490075Sobrien   onto BUFFER.  */
223590075Sobrienstatic void
2236132718Skanprint_instantiation_full_context (diagnostic_context *context)
223790075Sobrien{
223890075Sobrien  tree p = current_instantiation ();
2239132718Skan  location_t location = input_location;
2240169689Skan
224190075Sobrien  if (p)
224290075Sobrien    {
224390075Sobrien      if (current_function_decl != TINST_DECL (p)
224490075Sobrien	  && current_function_decl != NULL_TREE)
224590075Sobrien	/* We can get here during the processing of some synthesized
224690075Sobrien	   method.  Then, TINST_DECL (p) will be the function that's causing
224790075Sobrien	   the synthesis.  */
224890075Sobrien	;
224990075Sobrien      else
225090075Sobrien	{
225190075Sobrien	  if (current_function_decl == TINST_DECL (p))
2252169689Skan	    /* Avoid redundancy with the "In function" line.  */;
225390075Sobrien	  else
2254132718Skan	    pp_verbatim (context->printer,
2255169689Skan			 "%s: In instantiation of %qs:\n",
2256169689Skan			 LOCATION_FILE (location),
2257169689Skan			 decl_as_string (TINST_DECL (p),
2258169689Skan					 TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
225990075Sobrien
2260169689Skan	  location = TINST_LOCATION (p);
226190075Sobrien	  p = TREE_CHAIN (p);
226290075Sobrien	}
226390075Sobrien    }
226490075Sobrien
2265132718Skan  print_instantiation_partial_context (context, p, location);
226690075Sobrien}
226790075Sobrien
226890075Sobrien/* Same as above but less verbose.  */
226990075Sobrienstatic void
2270132718Skanprint_instantiation_partial_context (diagnostic_context *context,
2271169689Skan				     tree t, location_t loc)
227290075Sobrien{
2273169689Skan  expanded_location xloc;
2274169689Skan  for (; ; t = TREE_CHAIN (t))
227590075Sobrien    {
2276169689Skan      xloc = expand_location (loc);
2277169689Skan      if (t == NULL_TREE)
2278169689Skan	break;
2279169689Skan      pp_verbatim (context->printer, "%s:%d:   instantiated from %qs\n",
2280169689Skan		   xloc.file, xloc.line,
2281169689Skan		   decl_as_string (TINST_DECL (t),
2282169689Skan				   TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
2283169689Skan      loc = TINST_LOCATION (t);
228490075Sobrien    }
2285169689Skan  pp_verbatim (context->printer, "%s:%d:   instantiated from here",
2286169689Skan	       xloc.file, xloc.line);
2287169689Skan  pp_base_newline (context->printer);
228890075Sobrien}
228990075Sobrien
229090075Sobrien/* Called from cp_thing to print the template context for an error.  */
229190075Sobrienstatic void
2292132718Skanmaybe_print_instantiation_context (diagnostic_context *context)
229390075Sobrien{
229490075Sobrien  if (!problematic_instantiation_changed () || current_instantiation () == 0)
229590075Sobrien    return;
229690075Sobrien
229790075Sobrien  record_last_problematic_instantiation ();
2298117395Skan  print_instantiation_full_context (context);
229990075Sobrien}
230090075Sobrien
230190075Sobrien/* Report the bare minimum context of a template instantiation.  */
230290075Sobrienvoid
2303132718Skanprint_instantiation_context (void)
230490075Sobrien{
230590075Sobrien  print_instantiation_partial_context
2306132718Skan    (global_dc, current_instantiation (), input_location);
2307117395Skan  diagnostic_flush_buffer (global_dc);
230890075Sobrien}
230990075Sobrien
231090075Sobrien/* Called from output_format -- during diagnostic message processing --
231190075Sobrien   to handle C++ specific format specifier with the following meanings:
231290075Sobrien   %A   function argument-list.
231390075Sobrien   %C	tree code.
231490075Sobrien   %D   declaration.
231590075Sobrien   %E   expression.
231690075Sobrien   %F   function declaration.
231790075Sobrien   %L	language as used in extern "lang".
231890075Sobrien   %O	binary operator.
231990075Sobrien   %P   function parameter whose position is indicated by an integer.
232090075Sobrien   %Q	assignment operator.
232190075Sobrien   %T   type.
232290075Sobrien   %V   cv-qualifier.  */
2323117395Skanstatic bool
2324169689Skancp_printer (pretty_printer *pp, text_info *text, const char *spec,
2325169689Skan	    int precision, bool wide, bool set_locus, bool verbose)
232690075Sobrien{
232790075Sobrien  const char *result;
2328169689Skan  tree t = NULL;
2329169689Skan#define next_tree    (t = va_arg (*text->args_ptr, tree))
2330117395Skan#define next_tcode   va_arg (*text->args_ptr, enum tree_code)
2331117395Skan#define next_lang    va_arg (*text->args_ptr, enum languages)
2332117395Skan#define next_int     va_arg (*text->args_ptr, int)
233390075Sobrien
2334169689Skan  if (precision != 0 || wide)
2335169689Skan    return false;
233690075Sobrien
2337169689Skan  if (text->locus == NULL)
2338169689Skan    set_locus = false;
2339169689Skan
2340169689Skan  switch (*spec)
234190075Sobrien    {
234290075Sobrien    case 'A': result = args_to_string (next_tree, verbose);	break;
2343169689Skan    case 'C': result = code_to_string (next_tcode);		break;
2344169689Skan    case 'D':
2345169689Skan      {
2346169689Skan	tree temp = next_tree;
2347169689Skan	if (DECL_P (temp)
2348169689Skan	    && DECL_DEBUG_EXPR_IS_FROM (temp) && DECL_DEBUG_EXPR (temp))
2349169689Skan	  {
2350169689Skan	    temp = DECL_DEBUG_EXPR (temp);
2351169689Skan	    if (!DECL_P (temp))
2352169689Skan	      {
2353169689Skan		result = expr_to_string (temp);
2354169689Skan		break;
2355169689Skan	      }
2356169689Skan	  }
2357169689Skan	result = decl_to_string (temp, verbose);
2358169689Skan      }
2359169689Skan      break;
2360169689Skan    case 'E': result = expr_to_string (next_tree);		break;
236190075Sobrien    case 'F': result = fndecl_to_string (next_tree, verbose);	break;
2362169689Skan    case 'L': result = language_to_string (next_lang);		break;
2363169689Skan    case 'O': result = op_to_string (next_tcode);		break;
2364169689Skan    case 'P': result = parm_to_string (next_int);		break;
2365169689Skan    case 'Q': result = assop_to_string (next_tcode);		break;
236690075Sobrien    case 'T': result = type_to_string (next_tree, verbose);	break;
236790075Sobrien    case 'V': result = cv_to_string (next_tree, verbose);	break;
2368169689Skan
236990075Sobrien    default:
2370117395Skan      return false;
237190075Sobrien    }
237290075Sobrien
2373132718Skan  pp_base_string (pp, result);
2374169689Skan  if (set_locus && t != NULL)
2375169689Skan    *text->locus = location_of (t);
2376117395Skan  return true;
237790075Sobrien#undef next_tree
237890075Sobrien#undef next_tcode
237990075Sobrien#undef next_lang
238090075Sobrien#undef next_int
238190075Sobrien}
2382169689Skan
2383169689Skan/* Callback from cpp_error for PFILE to print diagnostics arising from
2384169689Skan   interpreting strings.  The diagnostic is of type LEVEL; MSG is the
2385169689Skan   translated message and AP the arguments.  */
238690075Sobrien
2387169689Skanvoid
2388169689Skancp_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level,
2389169689Skan	      const char *msg, va_list *ap)
239090075Sobrien{
2391169689Skan  diagnostic_info diagnostic;
2392169689Skan  diagnostic_t dlevel;
2393169689Skan  switch (level)
239490075Sobrien    {
2395169689Skan    case CPP_DL_WARNING:
2396169689Skan    case CPP_DL_WARNING_SYSHDR:
2397169689Skan      dlevel = DK_WARNING;
2398169689Skan      break;
2399169689Skan    case CPP_DL_PEDWARN:
2400169689Skan      dlevel = pedantic_error_kind ();
2401169689Skan      break;
2402169689Skan    case CPP_DL_ERROR:
2403169689Skan      dlevel = DK_ERROR;
2404169689Skan      break;
2405169689Skan    case CPP_DL_ICE:
2406169689Skan      dlevel = DK_ICE;
2407169689Skan      break;
2408169689Skan    default:
2409169689Skan      gcc_unreachable ();
241090075Sobrien    }
2411169689Skan  diagnostic_set_info_translated (&diagnostic, msg, ap,
2412169689Skan				  input_location, dlevel);
2413117395Skan  report_diagnostic (&diagnostic);
241490075Sobrien}
2415