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:
345261188Spfg      /* APPLE LOCAL blocks 6040305 */
346261188Spfg    case BLOCK_POINTER_TYPE:
34718334Speter    case REFERENCE_TYPE:
34818334Speter    case OFFSET_TYPE:
34918334Speter    offset_type:
35018334Speter    case FUNCTION_TYPE:
35118334Speter    case METHOD_TYPE:
35290075Sobrien    {
35390075Sobrien      dump_type_prefix (t, flags);
35490075Sobrien      dump_type_suffix (t, flags);
35518334Speter      break;
35690075Sobrien    }
35750397Sobrien    case TYPENAME_TYPE:
358169689Skan      pp_cxx_cv_qualifier_seq (cxx_pp, t);
359169689Skan      pp_cxx_identifier (cxx_pp,
360169689Skan			 TYPENAME_IS_ENUM_P (t) ? "enum"
361169689Skan			 : TYPENAME_IS_CLASS_P (t) ? "class"
362169689Skan			 : "typename");
36390075Sobrien      dump_typename (t, flags);
36450397Sobrien      break;
36550397Sobrien
36690075Sobrien    case UNBOUND_CLASS_TEMPLATE:
36790075Sobrien      dump_type (TYPE_CONTEXT (t), flags);
368169689Skan      pp_cxx_colon_colon (cxx_pp);
369169689Skan      pp_cxx_identifier (cxx_pp, "template");
37090075Sobrien      dump_type (DECL_NAME (TYPE_NAME (t)), flags);
37190075Sobrien      break;
37290075Sobrien
37352284Sobrien    case TYPEOF_TYPE:
374169689Skan      pp_cxx_identifier (cxx_pp, "__typeof__");
375169689Skan      pp_cxx_whitespace (cxx_pp);
376169689Skan      pp_cxx_left_paren (cxx_pp);
377169689Skan      dump_expr (TYPEOF_TYPE_EXPR (t), flags & ~TFF_EXPR_IN_PARENS);
378169689Skan      pp_cxx_right_paren (cxx_pp);
37952284Sobrien      break;
38052284Sobrien
38118334Speter    default:
382132718Skan      pp_unsupported_tree (cxx_pp, t);
383117395Skan      /* Fall through to error.  */
38490075Sobrien
38590075Sobrien    case ERROR_MARK:
386132718Skan      pp_identifier (cxx_pp, "<type error>");
38790075Sobrien      break;
38818334Speter    }
38918334Speter}
39018334Speter
39190075Sobrien/* Dump a TYPENAME_TYPE. We need to notice when the context is itself
39290075Sobrien   a TYPENAME_TYPE.  */
39390075Sobrien
39490075Sobrienstatic void
395132718Skandump_typename (tree t, int flags)
39618334Speter{
39790075Sobrien  tree ctx = TYPE_CONTEXT (t);
39890075Sobrien
39990075Sobrien  if (TREE_CODE (ctx) == TYPENAME_TYPE)
40090075Sobrien    dump_typename (ctx, flags);
40190075Sobrien  else
40290075Sobrien    dump_type (ctx, flags & ~TFF_CLASS_KEY_OR_ENUM);
403169689Skan  pp_cxx_colon_colon (cxx_pp);
40490075Sobrien  dump_decl (TYPENAME_TYPE_FULLNAME (t), flags);
40590075Sobrien}
40690075Sobrien
40790075Sobrien/* Return the name of the supplied aggregate, or enumeral type.  */
40890075Sobrien
409169689Skanconst char *
410169689Skanclass_key_or_enum_as_string (tree t)
41190075Sobrien{
41218334Speter  if (TREE_CODE (t) == ENUMERAL_TYPE)
41318334Speter    return "enum";
41418334Speter  else if (TREE_CODE (t) == UNION_TYPE)
41518334Speter    return "union";
41618334Speter  else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t))
41718334Speter    return "class";
41818334Speter  else
41918334Speter    return "struct";
42018334Speter}
42118334Speter
42290075Sobrien/* Print out a class declaration T under the control of FLAGS,
42390075Sobrien   in the form `class foo'.  */
42450397Sobrien
42550397Sobrienstatic void
426132718Skandump_aggr_type (tree t, int flags)
42750397Sobrien{
42818334Speter  tree name;
429169689Skan  const char *variety = class_key_or_enum_as_string (t);
43090075Sobrien  int typdef = 0;
43190075Sobrien  int tmplate = 0;
43218334Speter
433169689Skan  pp_cxx_cv_qualifier_seq (cxx_pp, t);
43418334Speter
43590075Sobrien  if (flags & TFF_CLASS_KEY_OR_ENUM)
436169689Skan    pp_cxx_identifier (cxx_pp, variety);
43718334Speter
43890075Sobrien  if (flags & TFF_CHASE_TYPEDEF)
43990075Sobrien    t = TYPE_MAIN_VARIANT (t);
44090075Sobrien
44190075Sobrien  name = TYPE_NAME (t);
44290075Sobrien
44390075Sobrien  if (name)
44418334Speter    {
44590075Sobrien      typdef = !DECL_ARTIFICIAL (name);
44690075Sobrien      tmplate = !typdef && TREE_CODE (t) != ENUMERAL_TYPE
447169689Skan		&& TYPE_LANG_SPECIFIC (t) && CLASSTYPE_TEMPLATE_INFO (t)
448169689Skan		&& (TREE_CODE (CLASSTYPE_TI_TEMPLATE (t)) != TEMPLATE_DECL
449169689Skan		    || PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)));
45090075Sobrien      dump_scope (CP_DECL_CONTEXT (name), flags | TFF_SCOPE);
45190075Sobrien      if (tmplate)
452169689Skan	{
453169689Skan	  /* Because the template names are mangled, we have to locate
454169689Skan	     the most general template, and use that name.  */
455169689Skan	  tree tpl = CLASSTYPE_TI_TEMPLATE (t);
45690075Sobrien
457169689Skan	  while (DECL_TEMPLATE_INFO (tpl))
458169689Skan	    tpl = DECL_TI_TEMPLATE (tpl);
459169689Skan	  name = tpl;
460169689Skan	}
46190075Sobrien      name = DECL_NAME (name);
46218334Speter    }
46318334Speter
46418334Speter  if (name == 0 || ANON_AGGRNAME_P (name))
46518334Speter    {
46690075Sobrien      if (flags & TFF_CLASS_KEY_OR_ENUM)
467169689Skan	pp_identifier (cxx_pp, "<anonymous>");
46890075Sobrien      else
469169689Skan	pp_printf (pp_base (cxx_pp), "<anonymous %s>", variety);
47018334Speter    }
47118334Speter  else
472169689Skan    pp_cxx_tree_identifier (cxx_pp, name);
47390075Sobrien  if (tmplate)
47490075Sobrien    dump_template_parms (TYPE_TEMPLATE_INFO (t),
475169689Skan			 !CLASSTYPE_USE_TEMPLATE (t),
476169689Skan			 flags & ~TFF_TEMPLATE_HEADER);
47718334Speter}
47818334Speter
47918334Speter/* Dump into the obstack the initial part of the output for a given type.
48018334Speter   This is necessary when dealing with things like functions returning
48118334Speter   functions.  Examples:
48218334Speter
48318334Speter   return type of `int (* fee ())()': pointer -> function -> int.  Both
48418334Speter   pointer (and reference and offset) and function (and member) types must
48518334Speter   deal with prefix and suffix.
48618334Speter
48718334Speter   Arrays must also do this for DECL nodes, like int a[], and for things like
488169689Skan   int *[]&.  */
48918334Speter
490169689Skanstatic void
491132718Skandump_type_prefix (tree t, int flags)
49218334Speter{
49318334Speter  if (TYPE_PTRMEMFUNC_P (t))
49418334Speter    {
49518334Speter      t = TYPE_PTRMEMFUNC_FN_TYPE (t);
49618334Speter      goto offset_type;
49718334Speter    }
49890075Sobrien
49918334Speter  switch (TREE_CODE (t))
50018334Speter    {
50118334Speter    case POINTER_TYPE:
502261188Spfg      /* APPLE LOCAL blocks 6040305 */
503261188Spfg    case BLOCK_POINTER_TYPE:
50452284Sobrien    case REFERENCE_TYPE:
50518334Speter      {
50618334Speter	tree sub = TREE_TYPE (t);
50790075Sobrien
508169689Skan	dump_type_prefix (sub, flags);
509132718Skan	if (TREE_CODE (sub) == ARRAY_TYPE)
51018334Speter	  {
511169689Skan	    pp_cxx_whitespace (cxx_pp);
512169689Skan	    pp_cxx_left_paren (cxx_pp);
51318334Speter	  }
514261188Spfg	/* APPLE LOCAL begin blocks 6040305 */
515261188Spfg	pp_character (cxx_pp, "&*^"[(TREE_CODE (t) == POINTER_TYPE)
516261188Spfg				    + (TREE_CODE (t) == BLOCK_POINTER_TYPE)*2]);
517261188Spfg	/* APPLE LOCAL end blocks 6040305 */
518169689Skan	pp_base (cxx_pp)->padding = pp_before;
519169689Skan	pp_cxx_cv_qualifier_seq (cxx_pp, t);
52018334Speter      }
52118334Speter      break;
52218334Speter
52318334Speter    case OFFSET_TYPE:
52418334Speter    offset_type:
525169689Skan      dump_type_prefix (TREE_TYPE (t), flags);
52618334Speter      if (TREE_CODE (t) == OFFSET_TYPE)	/* pmfs deal with this in d_t_p */
52718334Speter	{
528169689Skan	  pp_maybe_space (cxx_pp);
529169689Skan	  if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
530169689Skan	     pp_cxx_left_paren (cxx_pp);
53190075Sobrien	  dump_type (TYPE_OFFSET_BASETYPE (t), flags);
532169689Skan	  pp_cxx_colon_colon (cxx_pp);
53318334Speter	}
534169689Skan      pp_cxx_star (cxx_pp);
535169689Skan      pp_cxx_cv_qualifier_seq (cxx_pp, t);
536169689Skan      pp_base (cxx_pp)->padding = pp_before;
53718334Speter      break;
53818334Speter
53918334Speter      /* Can only be reached through function pointer -- this would not be
540169689Skan	 correct if FUNCTION_DECLs used it.  */
54118334Speter    case FUNCTION_TYPE:
542169689Skan      dump_type_prefix (TREE_TYPE (t), flags);
543169689Skan      pp_maybe_space (cxx_pp);
544169689Skan      pp_cxx_left_paren (cxx_pp);
54518334Speter      break;
54618334Speter
54718334Speter    case METHOD_TYPE:
548169689Skan      dump_type_prefix (TREE_TYPE (t), flags);
549169689Skan      pp_maybe_space (cxx_pp);
550169689Skan      pp_cxx_left_paren (cxx_pp);
55190075Sobrien      dump_aggr_type (TYPE_METHOD_BASETYPE (t), flags);
552169689Skan      pp_cxx_colon_colon (cxx_pp);
55318334Speter      break;
55418334Speter
55518334Speter    case ARRAY_TYPE:
556169689Skan      dump_type_prefix (TREE_TYPE (t), flags);
55718334Speter      break;
55818334Speter
55918334Speter    case ENUMERAL_TYPE:
56018334Speter    case IDENTIFIER_NODE:
56118334Speter    case INTEGER_TYPE:
56218334Speter    case BOOLEAN_TYPE:
56318334Speter    case REAL_TYPE:
56418334Speter    case RECORD_TYPE:
56518334Speter    case TEMPLATE_TYPE_PARM:
56650397Sobrien    case TEMPLATE_TEMPLATE_PARM:
56790075Sobrien    case BOUND_TEMPLATE_TEMPLATE_PARM:
56818334Speter    case TREE_LIST:
56918334Speter    case TYPE_DECL:
57018334Speter    case TREE_VEC:
57118334Speter    case UNION_TYPE:
57218334Speter    case UNKNOWN_TYPE:
57318334Speter    case VOID_TYPE:
57450397Sobrien    case TYPENAME_TYPE:
57550397Sobrien    case COMPLEX_TYPE:
57690075Sobrien    case VECTOR_TYPE:
577117395Skan    case TYPEOF_TYPE:
57890075Sobrien      dump_type (t, flags);
579169689Skan      pp_base (cxx_pp)->padding = pp_before;
58018334Speter      break;
58190075Sobrien
58218334Speter    default:
583132718Skan      pp_unsupported_tree (cxx_pp, t);
58490075Sobrien      /* fall through.  */
58590075Sobrien    case ERROR_MARK:
586132718Skan      pp_identifier (cxx_pp, "<typeprefixerror>");
58790075Sobrien      break;
58818334Speter    }
58918334Speter}
59018334Speter
59190075Sobrien/* Dump the suffix of type T, under control of FLAGS.  This is the part
59290075Sobrien   which appears after the identifier (or function parms).  */
59390075Sobrien
59418334Speterstatic void
595132718Skandump_type_suffix (tree t, int flags)
59618334Speter{
59718334Speter  if (TYPE_PTRMEMFUNC_P (t))
59818334Speter    t = TYPE_PTRMEMFUNC_FN_TYPE (t);
59918334Speter
60018334Speter  switch (TREE_CODE (t))
60118334Speter    {
60218334Speter    case POINTER_TYPE:
603261188Spfg      /* APPLE LOCAL blocks 6040305 */
604261188Spfg    case BLOCK_POINTER_TYPE:
60518334Speter    case REFERENCE_TYPE:
60618334Speter    case OFFSET_TYPE:
60718334Speter      if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
608169689Skan	pp_cxx_right_paren (cxx_pp);
60990075Sobrien      dump_type_suffix (TREE_TYPE (t), flags);
61018334Speter      break;
61118334Speter
612132718Skan      /* Can only be reached through function pointer.  */
61318334Speter    case FUNCTION_TYPE:
61418334Speter    case METHOD_TYPE:
61518334Speter      {
61618334Speter	tree arg;
617169689Skan	pp_cxx_right_paren (cxx_pp);
61818334Speter	arg = TYPE_ARG_TYPES (t);
61918334Speter	if (TREE_CODE (t) == METHOD_TYPE)
62018334Speter	  arg = TREE_CHAIN (arg);
62118334Speter
62252284Sobrien	/* Function pointers don't have default args.  Not in standard C++,
62352284Sobrien	   anyway; they may in g++, but we'll just pretend otherwise.  */
62490075Sobrien	dump_parameters (arg, flags & ~TFF_FUNCTION_DEFAULT_ARGUMENTS);
62552284Sobrien
62618334Speter	if (TREE_CODE (t) == METHOD_TYPE)
627169689Skan	  pp_cxx_cv_qualifier_seq
628169689Skan	    (cxx_pp, TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))));
629169689Skan	else
630169689Skan	  pp_cxx_cv_qualifier_seq(cxx_pp, t);
63190075Sobrien	dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags);
63290075Sobrien	dump_type_suffix (TREE_TYPE (t), flags);
63318334Speter	break;
63418334Speter      }
63518334Speter
63618334Speter    case ARRAY_TYPE:
637169689Skan      pp_maybe_space (cxx_pp);
638169689Skan      pp_cxx_left_bracket (cxx_pp);
63918334Speter      if (TYPE_DOMAIN (t))
64050397Sobrien	{
64190075Sobrien	  if (host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0))
642132718Skan	    pp_wide_integer
643169689Skan	      (cxx_pp, tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0) + 1);
64450397Sobrien	  else if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == MINUS_EXPR)
64590075Sobrien	    dump_expr (TREE_OPERAND (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0),
646169689Skan		       flags & ~TFF_EXPR_IN_PARENS);
64750397Sobrien	  else
64890075Sobrien	    dump_expr (fold (cp_build_binary_op
64950397Sobrien			     (PLUS_EXPR, TYPE_MAX_VALUE (TYPE_DOMAIN (t)),
65090075Sobrien			      integer_one_node)),
651169689Skan		       flags & ~TFF_EXPR_IN_PARENS);
65250397Sobrien	}
653169689Skan      pp_cxx_right_bracket (cxx_pp);
65490075Sobrien      dump_type_suffix (TREE_TYPE (t), flags);
65518334Speter      break;
65690075Sobrien
65718334Speter    case ENUMERAL_TYPE:
65818334Speter    case IDENTIFIER_NODE:
65918334Speter    case INTEGER_TYPE:
66018334Speter    case BOOLEAN_TYPE:
66118334Speter    case REAL_TYPE:
66218334Speter    case RECORD_TYPE:
66318334Speter    case TEMPLATE_TYPE_PARM:
66450397Sobrien    case TEMPLATE_TEMPLATE_PARM:
66590075Sobrien    case BOUND_TEMPLATE_TEMPLATE_PARM:
66618334Speter    case TREE_LIST:
66718334Speter    case TYPE_DECL:
66818334Speter    case TREE_VEC:
66918334Speter    case UNION_TYPE:
67018334Speter    case UNKNOWN_TYPE:
67118334Speter    case VOID_TYPE:
67250397Sobrien    case TYPENAME_TYPE:
67350397Sobrien    case COMPLEX_TYPE:
67490075Sobrien    case VECTOR_TYPE:
675117395Skan    case TYPEOF_TYPE:
67618334Speter      break;
67718334Speter
67818334Speter    default:
679132718Skan      pp_unsupported_tree (cxx_pp, t);
68090075Sobrien    case ERROR_MARK:
68190075Sobrien      /* Don't mark it here, we should have already done in
682169689Skan	 dump_type_prefix.  */
68390075Sobrien      break;
68418334Speter    }
68518334Speter}
68618334Speter
68750397Sobrienstatic void
688132718Skandump_global_iord (tree t)
68918334Speter{
69090075Sobrien  const char *p = NULL;
69118334Speter
69290075Sobrien  if (DECL_GLOBAL_CTOR_P (t))
69390075Sobrien    p = "initializers";
69490075Sobrien  else if (DECL_GLOBAL_DTOR_P (t))
69590075Sobrien    p = "destructors";
69618334Speter  else
697169689Skan    gcc_unreachable ();
69890075Sobrien
699132718Skan  pp_printf (pp_base (cxx_pp), "(static %s for %s)", p, input_filename);
70018334Speter}
70118334Speter
70218334Speterstatic void
703132718Skandump_simple_decl (tree t, tree type, int flags)
70450397Sobrien{
70590075Sobrien  if (flags & TFF_DECL_SPECIFIERS)
70650397Sobrien    {
707169689Skan      dump_type_prefix (type, flags);
708169689Skan      pp_maybe_space (cxx_pp);
70950397Sobrien    }
71090075Sobrien  if (!DECL_INITIAL (t) || TREE_CODE (DECL_INITIAL (t)) != TEMPLATE_PARM_INDEX)
71190075Sobrien    dump_scope (CP_DECL_CONTEXT (t), flags);
71250397Sobrien  if (DECL_NAME (t))
71390075Sobrien    dump_decl (DECL_NAME (t), flags);
71450397Sobrien  else
715132718Skan    pp_identifier (cxx_pp, "<anonymous>");
71690075Sobrien  if (flags & TFF_DECL_SPECIFIERS)
71790075Sobrien    dump_type_suffix (type, flags);
71850397Sobrien}
71950397Sobrien
72090075Sobrien/* Dump a human readable string for the decl T under control of FLAGS.  */
72190075Sobrien
72250397Sobrienstatic void
723132718Skandump_decl (tree t, int flags)
72418334Speter{
72518334Speter  if (t == NULL_TREE)
72618334Speter    return;
72718334Speter
72818334Speter  switch (TREE_CODE (t))
72918334Speter    {
73018334Speter    case TYPE_DECL:
731169689Skan      /* Don't say 'typedef class A' */
732169689Skan      if (DECL_ARTIFICIAL (t))
733169689Skan	{
734169689Skan	  if ((flags & TFF_DECL_SPECIFIERS)
735169689Skan	      && TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
736169689Skan	    /* Say `class T' not just `T'.  */
737169689Skan	    pp_cxx_identifier (cxx_pp, "class");
73850397Sobrien
739169689Skan	  dump_type (TREE_TYPE (t), flags);
740169689Skan	  break;
741169689Skan	}
74290075Sobrien      if (flags & TFF_DECL_SPECIFIERS)
743169689Skan	pp_cxx_identifier (cxx_pp, "typedef");
74490075Sobrien      dump_simple_decl (t, DECL_ORIGINAL_TYPE (t)
74590075Sobrien			? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t),
746169689Skan			flags);
74718334Speter      break;
74890075Sobrien
74918334Speter    case VAR_DECL:
75018334Speter      if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t)))
75118334Speter	{
752132718Skan	  pp_string (cxx_pp, "vtable for ");
753169689Skan	  gcc_assert (TYPE_P (DECL_CONTEXT (t)));
75490075Sobrien	  dump_type (DECL_CONTEXT (t), flags);
75518334Speter	  break;
75618334Speter	}
757132718Skan      /* Else fall through.  */
75818334Speter    case FIELD_DECL:
75918334Speter    case PARM_DECL:
76090075Sobrien      dump_simple_decl (t, TREE_TYPE (t), flags);
76118334Speter      break;
76218334Speter
76390075Sobrien    case RESULT_DECL:
764132718Skan      pp_string (cxx_pp, "<return value> ");
76590075Sobrien      dump_simple_decl (t, TREE_TYPE (t), flags);
76690075Sobrien      break;
76790075Sobrien
76818334Speter    case NAMESPACE_DECL:
769132718Skan      if (flags & TFF_DECL_SPECIFIERS)
770169689Skan	pp_cxx_declaration (cxx_pp, t);
77152284Sobrien      else
772169689Skan	{
773169689Skan	  dump_scope (CP_DECL_CONTEXT (t), flags);
774169689Skan	  if (DECL_NAME (t) == NULL_TREE)
775169689Skan	    pp_identifier (cxx_pp, "<unnamed>");
776169689Skan	  else
777169689Skan	    pp_cxx_tree_identifier (cxx_pp, DECL_NAME (t));
778169689Skan	}
77918334Speter      break;
78018334Speter
78150397Sobrien    case SCOPE_REF:
782146895Skan      pp_expression (cxx_pp, t);
78390075Sobrien      break;
78450397Sobrien
78518334Speter    case ARRAY_REF:
78690075Sobrien      dump_decl (TREE_OPERAND (t, 0), flags);
787169689Skan      pp_cxx_left_bracket (cxx_pp);
78890075Sobrien      dump_decl (TREE_OPERAND (t, 1), flags);
789169689Skan      pp_cxx_right_bracket (cxx_pp);
79018334Speter      break;
79118334Speter
79290075Sobrien      /* So that we can do dump_decl on an aggr type.  */
79318334Speter    case RECORD_TYPE:
79418334Speter    case UNION_TYPE:
79518334Speter    case ENUMERAL_TYPE:
79690075Sobrien      dump_type (t, flags);
79718334Speter      break;
79818334Speter
799132718Skan    case BIT_NOT_EXPR:
800132718Skan      /* This is a pseudo destructor call which has not been folded into
801169689Skan	 a PSEUDO_DTOR_EXPR yet.  */
802169689Skan      pp_cxx_complement (cxx_pp);
803132718Skan      dump_type (TREE_OPERAND (t, 0), flags);
804132718Skan      break;
805132718Skan
80618334Speter    case TYPE_EXPR:
807169689Skan      gcc_unreachable ();
80818334Speter      break;
80918334Speter
81018334Speter      /* These special cases are duplicated here so that other functions
81190075Sobrien	 can feed identifiers to error and get them demangled properly.  */
81218334Speter    case IDENTIFIER_NODE:
81390075Sobrien      if (IDENTIFIER_TYPENAME_P (t))
81490075Sobrien	{
815169689Skan	  pp_cxx_identifier (cxx_pp, "operator");
81690075Sobrien	  /* Not exactly IDENTIFIER_TYPE_VALUE.  */
81790075Sobrien	  dump_type (TREE_TYPE (t), flags);
81890075Sobrien	  break;
81990075Sobrien	}
82090075Sobrien      else
821169689Skan	pp_cxx_tree_identifier (cxx_pp, t);
82218334Speter      break;
82318334Speter
82452284Sobrien    case OVERLOAD:
825110611Skan      if (OVL_CHAIN (t))
826110611Skan	{
827110611Skan	  t = OVL_CURRENT (t);
828110611Skan	  if (DECL_CLASS_SCOPE_P (t))
829110611Skan	    {
830110611Skan	      dump_type (DECL_CONTEXT (t), flags);
831169689Skan	      pp_cxx_colon_colon (cxx_pp);
832110611Skan	    }
833110611Skan	  else if (DECL_CONTEXT (t))
834110611Skan	    {
835110611Skan	      dump_decl (DECL_CONTEXT (t), flags);
836169689Skan	      pp_cxx_colon_colon (cxx_pp);
837110611Skan	    }
838110611Skan	  dump_decl (DECL_NAME (t), flags);
839110611Skan	  break;
840110611Skan	}
841169689Skan
842110611Skan      /* If there's only one function, just treat it like an ordinary
843110611Skan	 FUNCTION_DECL.  */
84452284Sobrien      t = OVL_CURRENT (t);
84552284Sobrien      /* Fall through.  */
84652284Sobrien
84718334Speter    case FUNCTION_DECL:
848169689Skan      if (! DECL_LANG_SPECIFIC (t))
849169689Skan	pp_identifier (cxx_pp, "<built-in>");
850169689Skan      else if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t))
85190075Sobrien	dump_global_iord (t);
85218334Speter      else
853169689Skan	dump_function_decl (t, flags);
85418334Speter      break;
85518334Speter
85618334Speter    case TEMPLATE_DECL:
85790075Sobrien      dump_template_decl (t, flags);
85818334Speter      break;
85918334Speter
86050397Sobrien    case TEMPLATE_ID_EXPR:
86150397Sobrien      {
86250397Sobrien	tree name = TREE_OPERAND (t, 0);
863169689Skan
86450397Sobrien	if (is_overloaded_fn (name))
86550397Sobrien	  name = DECL_NAME (get_first_fn (name));
86690075Sobrien	dump_decl (name, flags);
867169689Skan	pp_cxx_begin_template_argument_list (cxx_pp);
868132718Skan	if (TREE_OPERAND (t, 1))
869132718Skan	  dump_template_argument_list (TREE_OPERAND (t, 1), flags);
870169689Skan	pp_cxx_end_template_argument_list (cxx_pp);
87150397Sobrien      }
87250397Sobrien      break;
87350397Sobrien
87418334Speter    case LABEL_DECL:
875169689Skan      pp_cxx_tree_identifier (cxx_pp, DECL_NAME (t));
87618334Speter      break;
87718334Speter
87818334Speter    case CONST_DECL:
87950397Sobrien      if ((TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == ENUMERAL_TYPE)
88050397Sobrien	  || (DECL_INITIAL (t) &&
88150397Sobrien	      TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_PARM_INDEX))
88290075Sobrien	dump_simple_decl (t, TREE_TYPE (t), flags);
88350397Sobrien      else if (DECL_NAME (t))
88490075Sobrien	dump_decl (DECL_NAME (t), flags);
88550397Sobrien      else if (DECL_INITIAL (t))
88690075Sobrien	dump_expr (DECL_INITIAL (t), flags | TFF_EXPR_IN_PARENS);
88718334Speter      else
888132718Skan	pp_identifier (cxx_pp, "<enumerator>");
88918334Speter      break;
89018334Speter
89150397Sobrien    case USING_DECL:
892169689Skan      pp_cxx_identifier (cxx_pp, "using");
893169689Skan      dump_type (USING_DECL_SCOPE (t), flags);
894169689Skan      pp_cxx_colon_colon (cxx_pp);
895117395Skan      dump_decl (DECL_NAME (t), flags);
89650397Sobrien      break;
89750397Sobrien
898117395Skan    case BASELINK:
899117395Skan      dump_decl (BASELINK_FUNCTIONS (t), flags);
900117395Skan      break;
901117395Skan
902132718Skan    case NON_DEPENDENT_EXPR:
903132718Skan      dump_expr (t, flags);
904132718Skan      break;
905132718Skan
906132718Skan    case TEMPLATE_TYPE_PARM:
907132718Skan      if (flags & TFF_DECL_SPECIFIERS)
908169689Skan	pp_cxx_declaration (cxx_pp, t);
909132718Skan      else
910169689Skan	pp_type_id (cxx_pp, t);
911132718Skan      break;
912132718Skan
913220150Smm    case UNBOUND_CLASS_TEMPLATE:
914220150Smm      dump_type (t, flags);
915220150Smm      break;
916220150Smm
91718334Speter    default:
918132718Skan      pp_unsupported_tree (cxx_pp, t);
919169689Skan      /* Fall through to error.  */
92090075Sobrien
92190075Sobrien    case ERROR_MARK:
922132718Skan      pp_identifier (cxx_pp, "<declaration error>");
92390075Sobrien      break;
92418334Speter    }
92518334Speter}
92618334Speter
92790075Sobrien/* Dump a template declaration T under control of FLAGS. This means the
92890075Sobrien   'template <...> leaders plus the 'class X' or 'void fn(...)' part.  */
92990075Sobrien
93090075Sobrienstatic void
931132718Skandump_template_decl (tree t, int flags)
93290075Sobrien{
93390075Sobrien  tree orig_parms = DECL_TEMPLATE_PARMS (t);
93490075Sobrien  tree parms;
93590075Sobrien  int i;
93690075Sobrien
93790075Sobrien  if (flags & TFF_TEMPLATE_HEADER)
93890075Sobrien    {
93990075Sobrien      for (parms = orig_parms = nreverse (orig_parms);
940169689Skan	   parms;
941169689Skan	   parms = TREE_CHAIN (parms))
942169689Skan	{
94390075Sobrien	  tree inner_parms = INNERMOST_TEMPLATE_PARMS (parms);
944169689Skan	  int len = TREE_VEC_LENGTH (inner_parms);
94590075Sobrien
946169689Skan	  pp_cxx_identifier (cxx_pp, "template");
947169689Skan	  pp_cxx_begin_template_argument_list (cxx_pp);
94890075Sobrien
94990075Sobrien	  /* If we've shown the template prefix, we'd better show the
95090075Sobrien	     parameters' and decl's type too.  */
95190075Sobrien	    flags |= TFF_DECL_SPECIFIERS;
95290075Sobrien
953169689Skan	  for (i = 0; i < len; i++)
954169689Skan	    {
955169689Skan	      if (i)
956169689Skan		pp_separate_with_comma (cxx_pp);
957169689Skan	      dump_template_parameter (TREE_VEC_ELT (inner_parms, i), flags);
958169689Skan	    }
959169689Skan	  pp_cxx_end_template_argument_list (cxx_pp);
960169689Skan	  pp_cxx_whitespace (cxx_pp);
961169689Skan	}
96290075Sobrien      nreverse(orig_parms);
96390075Sobrien
96490075Sobrien      if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
965117395Skan	/* Say `template<arg> class TT' not just `template<arg> TT'.  */
966169689Skan	pp_cxx_identifier (cxx_pp, "class");
96790075Sobrien    }
96890075Sobrien
96990075Sobrien  if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
97090075Sobrien    dump_type (TREE_TYPE (t),
971169689Skan	       ((flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
972169689Skan		| (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0)));
97390075Sobrien  else if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL)
97490075Sobrien    dump_decl (DECL_TEMPLATE_RESULT (t), flags | TFF_TEMPLATE_NAME);
97590075Sobrien  else
97690075Sobrien    {
977169689Skan      gcc_assert (TREE_TYPE (t));
978169689Skan      switch (NEXT_CODE (t))
979169689Skan	{
980169689Skan	case METHOD_TYPE:
981169689Skan	case FUNCTION_TYPE:
982169689Skan	  dump_function_decl (t, flags | TFF_TEMPLATE_NAME);
983169689Skan	  break;
984169689Skan	default:
985169689Skan	  /* This case can occur with some invalid code.  */
986169689Skan	  dump_type (TREE_TYPE (t),
987169689Skan		     (flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
988169689Skan		     | (flags & TFF_DECL_SPECIFIERS
989169689Skan			? TFF_CLASS_KEY_OR_ENUM : 0));
990169689Skan	}
99190075Sobrien    }
99290075Sobrien}
99390075Sobrien
99452284Sobrien/* Pretty print a function decl. There are several ways we want to print a
99590075Sobrien   function declaration. The TFF_ bits in FLAGS tells us how to behave.
99690075Sobrien   As error can only apply the '#' flag once to give 0 and 1 for V, there
997117395Skan   is %D which doesn't print the throw specs, and %F which does.  */
99818334Speter
99918334Speterstatic void
1000132718Skandump_function_decl (tree t, int flags)
100118334Speter{
100250397Sobrien  tree fntype;
100350397Sobrien  tree parmtypes;
100418334Speter  tree cname = NULL_TREE;
100590075Sobrien  tree template_args = NULL_TREE;
100690075Sobrien  tree template_parms = NULL_TREE;
100790075Sobrien  int show_return = flags & TFF_RETURN_TYPE || flags & TFF_DECL_SPECIFIERS;
100818334Speter
100950397Sobrien  if (TREE_CODE (t) == TEMPLATE_DECL)
101050397Sobrien    t = DECL_TEMPLATE_RESULT (t);
101150397Sobrien
101290075Sobrien  /* Pretty print template instantiations only.  */
101390075Sobrien  if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t))
101490075Sobrien    {
101590075Sobrien      tree tmpl;
101690075Sobrien
101790075Sobrien      template_args = DECL_TI_ARGS (t);
101890075Sobrien      tmpl = most_general_template (t);
101990075Sobrien      if (tmpl && TREE_CODE (tmpl) == TEMPLATE_DECL)
102090075Sobrien	{
102190075Sobrien	  template_parms = DECL_TEMPLATE_PARMS (tmpl);
102290075Sobrien	  t = tmpl;
102390075Sobrien	}
102490075Sobrien    }
102590075Sobrien
102650397Sobrien  fntype = TREE_TYPE (t);
102790075Sobrien  parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);
102850397Sobrien
102952284Sobrien  if (DECL_CLASS_SCOPE_P (t))
103090075Sobrien    cname = DECL_CONTEXT (t);
1031132718Skan  /* This is for partially instantiated template methods.  */
103218334Speter  else if (TREE_CODE (fntype) == METHOD_TYPE)
103318334Speter    cname = TREE_TYPE (TREE_VALUE (parmtypes));
103418334Speter
103590075Sobrien  if (!(flags & TFF_DECL_SPECIFIERS))
103690075Sobrien    /* OK */;
103790075Sobrien  else if (DECL_STATIC_FUNCTION_P (t))
1038169689Skan    pp_cxx_identifier (cxx_pp, "static");
103990075Sobrien  else if (DECL_VIRTUAL_P (t))
1040169689Skan    pp_cxx_identifier (cxx_pp, "virtual");
104190075Sobrien
104290075Sobrien  /* Print the return type?  */
104390075Sobrien  if (show_return)
104490075Sobrien    show_return = !DECL_CONV_FN_P (t)  && !DECL_CONSTRUCTOR_P (t)
1045169689Skan		  && !DECL_DESTRUCTOR_P (t);
104690075Sobrien  if (show_return)
1047169689Skan    dump_type_prefix (TREE_TYPE (fntype), flags);
104818334Speter
104952284Sobrien  /* Print the function name.  */
105018334Speter  if (cname)
105118334Speter    {
105290075Sobrien      dump_type (cname, flags);
1053169689Skan      pp_cxx_colon_colon (cxx_pp);
105418334Speter    }
105590075Sobrien  else
105690075Sobrien    dump_scope (CP_DECL_CONTEXT (t), flags);
105790075Sobrien
105890075Sobrien  dump_function_name (t, flags);
105990075Sobrien
1060132718Skan  if (!(flags & TFF_NO_FUNCTION_ARGUMENTS))
106152284Sobrien    {
106290075Sobrien      dump_parameters (parmtypes, flags);
106318334Speter
106490075Sobrien      if (TREE_CODE (fntype) == METHOD_TYPE)
1065169689Skan	{
1066169689Skan	  pp_base (cxx_pp)->padding = pp_before;
1067169689Skan	  pp_cxx_cv_qualifier_seq
1068169689Skan	    (cxx_pp, TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))));
1069169689Skan	}
107018334Speter
107190075Sobrien      if (flags & TFF_EXCEPTION_SPECIFICATION)
1072169689Skan	{
1073169689Skan	  pp_base (cxx_pp)->padding = pp_before;
1074169689Skan	  dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), flags);
1075169689Skan	}
107618334Speter
107790075Sobrien      if (show_return)
107890075Sobrien	dump_type_suffix (TREE_TYPE (fntype), flags);
107990075Sobrien    }
108018334Speter
108190075Sobrien  /* If T is a template instantiation, dump the parameter binding.  */
108290075Sobrien  if (template_parms != NULL_TREE && template_args != NULL_TREE)
108318334Speter    {
1084169689Skan      pp_cxx_whitespace (cxx_pp);
1085169689Skan      pp_cxx_left_bracket (cxx_pp);
1086169689Skan      pp_cxx_identifier (cxx_pp, "with");
1087169689Skan      pp_cxx_whitespace (cxx_pp);
108890075Sobrien      dump_template_bindings (template_parms, template_args);
1089169689Skan      pp_cxx_right_bracket (cxx_pp);
109018334Speter    }
109118334Speter}
109218334Speter
109390075Sobrien/* Print a parameter list. If this is for a member function, the
109490075Sobrien   member object ptr (and any other hidden args) should have
1095117395Skan   already been removed.  */
109652284Sobrien
109752284Sobrienstatic void
1098132718Skandump_parameters (tree parmtypes, int flags)
109952284Sobrien{
110052284Sobrien  int first;
110152284Sobrien
1102169689Skan  pp_cxx_left_paren (cxx_pp);
110390075Sobrien
110452284Sobrien  for (first = 1; parmtypes != void_list_node;
110552284Sobrien       parmtypes = TREE_CHAIN (parmtypes))
110652284Sobrien    {
110752284Sobrien      if (!first)
1108169689Skan	pp_separate_with_comma (cxx_pp);
110952284Sobrien      first = 0;
111052284Sobrien      if (!parmtypes)
1111169689Skan	{
1112169689Skan	  pp_cxx_identifier (cxx_pp, "...");
1113169689Skan	  break;
1114169689Skan	}
111590075Sobrien      dump_type (TREE_VALUE (parmtypes), flags);
111690075Sobrien
111790075Sobrien      if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && TREE_PURPOSE (parmtypes))
1118169689Skan	{
1119169689Skan	  pp_cxx_whitespace (cxx_pp);
1120169689Skan	  pp_equal (cxx_pp);
1121169689Skan	  pp_cxx_whitespace (cxx_pp);
1122169689Skan	  dump_expr (TREE_PURPOSE (parmtypes), flags | TFF_EXPR_IN_PARENS);
1123169689Skan	}
112452284Sobrien    }
112552284Sobrien
1126169689Skan  pp_cxx_right_paren (cxx_pp);
112752284Sobrien}
112852284Sobrien
1129117395Skan/* Print an exception specification. T is the exception specification.  */
113052284Sobrien
113152284Sobrienstatic void
1132132718Skandump_exception_spec (tree t, int flags)
113352284Sobrien{
113452284Sobrien  if (t)
113552284Sobrien    {
1136169689Skan      pp_cxx_identifier (cxx_pp, "throw");
1137169689Skan      pp_cxx_whitespace (cxx_pp);
1138169689Skan      pp_cxx_left_paren (cxx_pp);
113952284Sobrien      if (TREE_VALUE (t) != NULL_TREE)
1140169689Skan	while (1)
1141169689Skan	  {
1142169689Skan	    dump_type (TREE_VALUE (t), flags);
1143169689Skan	    t = TREE_CHAIN (t);
1144169689Skan	    if (!t)
1145169689Skan	      break;
1146169689Skan	    pp_separate_with_comma (cxx_pp);
1147169689Skan	  }
1148169689Skan      pp_cxx_right_paren (cxx_pp);
114952284Sobrien    }
115052284Sobrien}
115152284Sobrien
115218334Speter/* Handle the function name for a FUNCTION_DECL node, grokking operators
115318334Speter   and destructors properly.  */
115450397Sobrien
115518334Speterstatic void
1156132718Skandump_function_name (tree t, int flags)
115718334Speter{
115818334Speter  tree name = DECL_NAME (t);
115918334Speter
1160169689Skan  /* We can get here with a decl that was synthesized by language-
1161169689Skan     independent machinery (e.g. coverage.c) in which case it won't
1162169689Skan     have a lang_specific structure attached and DECL_CONSTRUCTOR_P
1163169689Skan     will crash.  In this case it is safe just to print out the
1164169689Skan     literal name.  */
1165169689Skan  if (!DECL_LANG_SPECIFIC (t))
1166169689Skan    {
1167169689Skan      pp_cxx_tree_identifier (cxx_pp, name);
1168169689Skan      return;
1169169689Skan    }
1170169689Skan
1171117395Skan  if (TREE_CODE (t) == TEMPLATE_DECL)
1172117395Skan    t = DECL_TEMPLATE_RESULT (t);
1173117395Skan
117490075Sobrien  /* Don't let the user see __comp_ctor et al.  */
117590075Sobrien  if (DECL_CONSTRUCTOR_P (t)
117690075Sobrien      || DECL_DESTRUCTOR_P (t))
117790075Sobrien    name = constructor_name (DECL_CONTEXT (t));
117890075Sobrien
117952284Sobrien  if (DECL_DESTRUCTOR_P (t))
118018334Speter    {
1181169689Skan      pp_cxx_complement (cxx_pp);
118290075Sobrien      dump_decl (name, TFF_PLAIN_IDENTIFIER);
118318334Speter    }
118452284Sobrien  else if (DECL_CONV_FN_P (t))
118518334Speter    {
118618334Speter      /* This cannot use the hack that the operator's return
118718334Speter	 type is stashed off of its name because it may be
118818334Speter	 used for error reporting.  In the case of conflicting
118918334Speter	 declarations, both will have the same name, yet
119018334Speter	 the types will be different, hence the TREE_TYPE field
119118334Speter	 of the first name will be clobbered by the second.  */
1192169689Skan      pp_cxx_identifier (cxx_pp, "operator");
119390075Sobrien      dump_type (TREE_TYPE (TREE_TYPE (t)), flags);
119418334Speter    }
119518334Speter  else if (IDENTIFIER_OPNAME_P (name))
1196169689Skan    pp_cxx_tree_identifier (cxx_pp, name);
119718334Speter  else
119890075Sobrien    dump_decl (name, flags);
119950397Sobrien
1200169689Skan  if (DECL_TEMPLATE_INFO (t)
120190075Sobrien      && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t)
1202169689Skan      && (TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL
120352284Sobrien	  || PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t))))
120490075Sobrien    dump_template_parms (DECL_TEMPLATE_INFO (t), !DECL_USE_TEMPLATE (t), flags);
120590075Sobrien}
120690075Sobrien
120790075Sobrien/* Dump the template parameters from the template info INFO under control of
120890075Sobrien   FLAGS. PRIMARY indicates whether this is a primary template decl, or
120990075Sobrien   specialization (partial or complete). For partial specializations we show
121090075Sobrien   the specialized parameter values. For a primary template we show no
121190075Sobrien   decoration.  */
121290075Sobrien
121390075Sobrienstatic void
1214132718Skandump_template_parms (tree info, int primary, int flags)
121590075Sobrien{
121690075Sobrien  tree args = info ? TI_ARGS (info) : NULL_TREE;
121790075Sobrien
121890075Sobrien  if (primary && flags & TFF_TEMPLATE_NAME)
121990075Sobrien    return;
122090075Sobrien  flags &= ~(TFF_CLASS_KEY_OR_ENUM | TFF_TEMPLATE_NAME);
1221169689Skan  pp_cxx_begin_template_argument_list (cxx_pp);
122290075Sobrien
122390075Sobrien  /* Be careful only to print things when we have them, so as not
122490075Sobrien	 to crash producing error messages.  */
122590075Sobrien  if (args && !primary)
122650397Sobrien    {
1227132718Skan      int len, ix;
122850397Sobrien
1229132718Skan      if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
1230132718Skan	args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
1231169689Skan
1232132718Skan      len = TREE_VEC_LENGTH (args);
1233132718Skan
1234132718Skan      for (ix = 0; ix != len; ix++)
1235169689Skan	{
1236169689Skan	  tree arg = TREE_VEC_ELT (args, ix);
123790075Sobrien
1238169689Skan	  if (ix)
1239169689Skan	    pp_separate_with_comma (cxx_pp);
1240169689Skan
1241169689Skan	  if (!arg)
1242169689Skan	    pp_identifier (cxx_pp, "<template parameter error>");
1243169689Skan	  else
1244169689Skan	    dump_template_argument (arg, flags);
1245169689Skan	}
124650397Sobrien    }
124790075Sobrien  else if (primary)
124890075Sobrien    {
124990075Sobrien      tree tpl = TI_TEMPLATE (info);
125090075Sobrien      tree parms = DECL_TEMPLATE_PARMS (tpl);
125190075Sobrien      int len, ix;
125290075Sobrien
125390075Sobrien      parms = TREE_CODE (parms) == TREE_LIST ? TREE_VALUE (parms) : NULL_TREE;
125490075Sobrien      len = parms ? TREE_VEC_LENGTH (parms) : 0;
125590075Sobrien
125690075Sobrien      for (ix = 0; ix != len; ix++)
1257169689Skan	{
1258169689Skan	  tree parm;
125990075Sobrien
1260169689Skan          if (TREE_VEC_ELT (parms, ix) == error_mark_node)
1261169689Skan            {
1262169689Skan              pp_identifier (cxx_pp, "<template parameter error>");
1263169689Skan              continue;
1264169689Skan            }
126590075Sobrien
1266169689Skan          parm = TREE_VALUE (TREE_VEC_ELT (parms, ix));
1267169689Skan
1268169689Skan	  if (ix)
1269169689Skan	    pp_separate_with_comma (cxx_pp);
1270169689Skan
1271169689Skan	  dump_decl (parm, flags & ~TFF_DECL_SPECIFIERS);
1272169689Skan	}
127390075Sobrien    }
1274169689Skan  pp_cxx_end_template_argument_list (cxx_pp);
127518334Speter}
127618334Speter
1277132718Skan/* Print out a list of initializers (subr of dump_expr).  */
127818334Speter
127918334Speterstatic void
1280132718Skandump_expr_list (tree l, int flags)
128118334Speter{
128218334Speter  while (l)
128318334Speter    {
128490075Sobrien      dump_expr (TREE_VALUE (l), flags | TFF_EXPR_IN_PARENS);
128518334Speter      l = TREE_CHAIN (l);
128690075Sobrien      if (l)
1287132718Skan	pp_separate_with_comma (cxx_pp);
128818334Speter    }
128918334Speter}
129018334Speter
1291169689Skan/* Print out a vector of initializers (subr of dump_expr).  */
1292169689Skan
1293169689Skanstatic void
1294169689Skandump_expr_init_vec (VEC(constructor_elt,gc) *v, int flags)
1295169689Skan{
1296169689Skan  unsigned HOST_WIDE_INT idx;
1297169689Skan  tree value;
1298169689Skan
1299169689Skan  FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
1300169689Skan    {
1301169689Skan      dump_expr (value, flags | TFF_EXPR_IN_PARENS);
1302169689Skan      if (idx != VEC_length (constructor_elt, v) - 1)
1303169689Skan	pp_separate_with_comma (cxx_pp);
1304169689Skan    }
1305169689Skan}
1306169689Skan
1307169689Skan
1308169689Skan/* We've gotten an indirect REFERENCE (an OBJ_TYPE_REF) to a virtual
1309169689Skan   function.  Resolve it to a close relative -- in the sense of static
1310169689Skan   type -- variant being overridden.  That is close to what was written in
1311169689Skan   the source code.  Subroutine of dump_expr.  */
1312169689Skan
1313169689Skanstatic tree
1314169689Skanresolve_virtual_fun_from_obj_type_ref (tree ref)
1315169689Skan{
1316169689Skan  tree obj_type = TREE_TYPE (OBJ_TYPE_REF_OBJECT (ref));
1317220150Smm  HOST_WIDE_INT index = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1);
1318169689Skan  tree fun = BINFO_VIRTUALS (TYPE_BINFO (TREE_TYPE (obj_type)));
1319220150Smm  while (index)
1320220150Smm    {
1321169689Skan      fun = TREE_CHAIN (fun);
1322220150Smm      index -= (TARGET_VTABLE_USES_DESCRIPTORS
1323220150Smm		? TARGET_VTABLE_USES_DESCRIPTORS : 1);
1324220150Smm    }
1325169689Skan
1326169689Skan  return BV_FN (fun);
1327169689Skan}
1328169689Skan
1329117395Skan/* Print out an expression E under control of FLAGS.  */
133050397Sobrien
133118334Speterstatic void
1332132718Skandump_expr (tree t, int flags)
133318334Speter{
1334117395Skan  if (t == 0)
1335117395Skan    return;
1336169689Skan
133718334Speter  switch (TREE_CODE (t))
133818334Speter    {
133918334Speter    case VAR_DECL:
134018334Speter    case PARM_DECL:
134118334Speter    case FIELD_DECL:
134218334Speter    case CONST_DECL:
134318334Speter    case FUNCTION_DECL:
134450397Sobrien    case TEMPLATE_DECL:
134550397Sobrien    case NAMESPACE_DECL:
1346161651Skan    case LABEL_DECL:
134790075Sobrien    case OVERLOAD:
1348132718Skan    case IDENTIFIER_NODE:
1349132718Skan      dump_decl (t, (flags & ~TFF_DECL_SPECIFIERS) | TFF_NO_FUNCTION_ARGUMENTS);
135018334Speter      break;
135118334Speter
135218334Speter    case INTEGER_CST:
1353169689Skan    case REAL_CST:
1354132718Skan    case STRING_CST:
1355169689Skan      pp_constant (cxx_pp, t);
135618334Speter      break;
135718334Speter
1358132718Skan    case THROW_EXPR:
1359169689Skan      pp_cxx_identifier (cxx_pp, "throw");
1360132718Skan      dump_expr (TREE_OPERAND (t, 0), flags);
136118334Speter      break;
136218334Speter
136352284Sobrien    case PTRMEM_CST:
1364132718Skan      pp_ampersand (cxx_pp);
136590075Sobrien      dump_type (PTRMEM_CST_CLASS (t), flags);
1366169689Skan      pp_cxx_colon_colon (cxx_pp);
1367169689Skan      pp_cxx_tree_identifier (cxx_pp, DECL_NAME (PTRMEM_CST_MEMBER (t)));
136852284Sobrien      break;
136952284Sobrien
137018334Speter    case COMPOUND_EXPR:
1371169689Skan      pp_cxx_left_paren (cxx_pp);
137290075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1373132718Skan      pp_separate_with_comma (cxx_pp);
137490075Sobrien      dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1375169689Skan      pp_cxx_right_paren (cxx_pp);
137618334Speter      break;
137718334Speter
137818334Speter    case COND_EXPR:
1379169689Skan      pp_cxx_left_paren (cxx_pp);
138090075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1381132718Skan      pp_string (cxx_pp, " ? ");
138290075Sobrien      dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1383132718Skan      pp_string (cxx_pp, " : ");
138490075Sobrien      dump_expr (TREE_OPERAND (t, 2), flags | TFF_EXPR_IN_PARENS);
1385169689Skan      pp_cxx_right_paren (cxx_pp);
138618334Speter      break;
138718334Speter
138818334Speter    case SAVE_EXPR:
138918334Speter      if (TREE_HAS_CONSTRUCTOR (t))
139018334Speter	{
1391169689Skan	  pp_cxx_identifier (cxx_pp, "new");
1392169689Skan	  pp_cxx_whitespace (cxx_pp);
139390075Sobrien	  dump_type (TREE_TYPE (TREE_TYPE (t)), flags);
139418334Speter	}
139518334Speter      else
1396169689Skan	dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
139718334Speter      break;
139818334Speter
139950397Sobrien    case AGGR_INIT_EXPR:
140090075Sobrien      {
140190075Sobrien	tree fn = NULL_TREE;
140290075Sobrien
140390075Sobrien	if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
140490075Sobrien	  fn = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
140590075Sobrien
140690075Sobrien	if (fn && TREE_CODE (fn) == FUNCTION_DECL)
140790075Sobrien	  {
140890075Sobrien	    if (DECL_CONSTRUCTOR_P (fn))
1409169689Skan	      dump_type (DECL_CONTEXT (fn), flags);
141090075Sobrien	    else
141190075Sobrien	      dump_decl (fn, 0);
141290075Sobrien	  }
141390075Sobrien	else
141490075Sobrien	  dump_expr (TREE_OPERAND (t, 0), 0);
141590075Sobrien      }
1416169689Skan      pp_cxx_left_paren (cxx_pp);
141750397Sobrien      if (TREE_OPERAND (t, 1))
141890075Sobrien	dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags);
1419169689Skan      pp_cxx_right_paren (cxx_pp);
142018334Speter      break;
142118334Speter
142218334Speter    case CALL_EXPR:
142318334Speter      {
142418334Speter	tree fn = TREE_OPERAND (t, 0);
142518334Speter	tree args = TREE_OPERAND (t, 1);
142690075Sobrien
142718334Speter	if (TREE_CODE (fn) == ADDR_EXPR)
142818334Speter	  fn = TREE_OPERAND (fn, 0);
142918334Speter
1430169689Skan	/* Nobody is interested in seeing the guts of vcalls.  */
1431169689Skan	if (TREE_CODE (fn) == OBJ_TYPE_REF)
1432169689Skan	  fn = resolve_virtual_fun_from_obj_type_ref (fn);
1433169689Skan
143450397Sobrien	if (TREE_TYPE (fn) != NULL_TREE && NEXT_CODE (fn) == METHOD_TYPE)
143518334Speter	  {
143618334Speter	    tree ob = TREE_VALUE (args);
143718334Speter	    if (TREE_CODE (ob) == ADDR_EXPR)
143818334Speter	      {
143990075Sobrien		dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS);
1440220150Smm		pp_cxx_dot (cxx_pp);
144118334Speter	      }
144218334Speter	    else if (TREE_CODE (ob) != PARM_DECL
144318334Speter		     || strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this"))
144418334Speter	      {
144590075Sobrien		dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
1446220150Smm		pp_cxx_arrow (cxx_pp);
144718334Speter	      }
144818334Speter	    args = TREE_CHAIN (args);
144918334Speter	  }
145090075Sobrien	dump_expr (fn, flags | TFF_EXPR_IN_PARENS);
1451169689Skan	pp_cxx_left_paren (cxx_pp);
145290075Sobrien	dump_expr_list (args, flags);
1453169689Skan	pp_cxx_right_paren (cxx_pp);
145418334Speter      }
145518334Speter      break;
145618334Speter
145750397Sobrien    case NEW_EXPR:
145850397Sobrien      {
145950397Sobrien	tree type = TREE_OPERAND (t, 1);
1460117395Skan	tree init = TREE_OPERAND (t, 2);
146150397Sobrien	if (NEW_EXPR_USE_GLOBAL (t))
1462169689Skan	  pp_cxx_colon_colon (cxx_pp);
1463169689Skan	pp_cxx_identifier (cxx_pp, "new");
146450397Sobrien	if (TREE_OPERAND (t, 0))
146550397Sobrien	  {
1466169689Skan	    pp_cxx_left_paren (cxx_pp);
146790075Sobrien	    dump_expr_list (TREE_OPERAND (t, 0), flags);
1468169689Skan	    pp_cxx_right_paren (cxx_pp);
1469169689Skan	    pp_cxx_whitespace (cxx_pp);
147050397Sobrien	  }
147150397Sobrien	if (TREE_CODE (type) == ARRAY_REF)
147250397Sobrien	  type = build_cplus_array_type
147350397Sobrien	    (TREE_OPERAND (type, 0),
1474169689Skan	     build_index_type (fold_build2 (MINUS_EXPR, integer_type_node,
147590075Sobrien					    TREE_OPERAND (type, 1),
1476169689Skan					    integer_one_node)));
147790075Sobrien	dump_type (type, flags);
1478117395Skan	if (init)
147950397Sobrien	  {
1480169689Skan	    pp_cxx_left_paren (cxx_pp);
1481117395Skan	    if (TREE_CODE (init) == TREE_LIST)
1482117395Skan	      dump_expr_list (init, flags);
1483117395Skan	    else if (init == void_zero_node)
1484117395Skan	      /* This representation indicates an empty initializer,
1485117395Skan		 e.g.: "new int()".  */
1486117395Skan	      ;
1487117395Skan	    else
1488117395Skan	      dump_expr (init, flags);
1489169689Skan	    pp_cxx_right_paren (cxx_pp);
149050397Sobrien	  }
149150397Sobrien      }
149218334Speter      break;
149318334Speter
149418334Speter    case TARGET_EXPR:
149518334Speter      /* Note that this only works for G++ target exprs.  If somebody
149618334Speter	 builds a general TARGET_EXPR, there's no way to represent that
149718334Speter	 it initializes anything other that the parameter slot for the
149818334Speter	 default argument.  Note we may have cleared out the first
149918334Speter	 operand in expand_expr, so don't go killing ourselves.  */
150018334Speter      if (TREE_OPERAND (t, 1))
150190075Sobrien	dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
150218334Speter      break;
150318334Speter
150490075Sobrien    case INIT_EXPR:
150518334Speter    case MODIFY_EXPR:
150618334Speter    case PLUS_EXPR:
150718334Speter    case MINUS_EXPR:
150818334Speter    case MULT_EXPR:
150918334Speter    case TRUNC_DIV_EXPR:
151018334Speter    case TRUNC_MOD_EXPR:
151118334Speter    case MIN_EXPR:
151218334Speter    case MAX_EXPR:
151318334Speter    case LSHIFT_EXPR:
151418334Speter    case RSHIFT_EXPR:
151518334Speter    case BIT_IOR_EXPR:
151618334Speter    case BIT_XOR_EXPR:
151718334Speter    case BIT_AND_EXPR:
151818334Speter    case TRUTH_ANDIF_EXPR:
151918334Speter    case TRUTH_ORIF_EXPR:
152018334Speter    case LT_EXPR:
152118334Speter    case LE_EXPR:
152218334Speter    case GT_EXPR:
152318334Speter    case GE_EXPR:
152418334Speter    case EQ_EXPR:
152518334Speter    case NE_EXPR:
152690075Sobrien    case EXACT_DIV_EXPR:
152790075Sobrien      dump_binary_op (operator_name_info[(int) TREE_CODE (t)].name, t, flags);
152818334Speter      break;
152918334Speter
153018334Speter    case CEIL_DIV_EXPR:
153118334Speter    case FLOOR_DIV_EXPR:
153218334Speter    case ROUND_DIV_EXPR:
1533146895Skan    case RDIV_EXPR:
153490075Sobrien      dump_binary_op ("/", t, flags);
153518334Speter      break;
153618334Speter
153718334Speter    case CEIL_MOD_EXPR:
153818334Speter    case FLOOR_MOD_EXPR:
153918334Speter    case ROUND_MOD_EXPR:
154090075Sobrien      dump_binary_op ("%", t, flags);
154118334Speter      break;
154218334Speter
154318334Speter    case COMPONENT_REF:
154418334Speter      {
154518334Speter	tree ob = TREE_OPERAND (t, 0);
154618334Speter	if (TREE_CODE (ob) == INDIRECT_REF)
154718334Speter	  {
154818334Speter	    ob = TREE_OPERAND (ob, 0);
154918334Speter	    if (TREE_CODE (ob) != PARM_DECL
1550169689Skan		|| (DECL_NAME (ob)
1551169689Skan		    && strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this")))
155218334Speter	      {
155390075Sobrien		dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
1554169689Skan		pp_cxx_arrow (cxx_pp);
155518334Speter	      }
155618334Speter	  }
155718334Speter	else
155818334Speter	  {
155990075Sobrien	    dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
1560169689Skan	    pp_cxx_dot (cxx_pp);
156118334Speter	  }
156290075Sobrien	dump_expr (TREE_OPERAND (t, 1), flags & ~TFF_EXPR_IN_PARENS);
156318334Speter      }
156418334Speter      break;
156518334Speter
156618334Speter    case ARRAY_REF:
156790075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1568169689Skan      pp_cxx_left_bracket (cxx_pp);
156990075Sobrien      dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1570169689Skan      pp_cxx_right_bracket (cxx_pp);
157118334Speter      break;
157218334Speter
1573169689Skan    case UNARY_PLUS_EXPR:
1574169689Skan      dump_unary_op ("+", t, flags);
157518334Speter      break;
157618334Speter
157718334Speter    case ADDR_EXPR:
157818334Speter      if (TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
157990075Sobrien	  || TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST
158090075Sobrien	  /* An ADDR_EXPR can have reference type.  In that case, we
158190075Sobrien	     shouldn't print the `&' doing so indicates to the user
158290075Sobrien	     that the expression has pointer type.  */
158390075Sobrien	  || (TREE_TYPE (t)
158490075Sobrien	      && TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE))
158590075Sobrien	dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1586161651Skan      else if (TREE_CODE (TREE_OPERAND (t, 0)) == LABEL_DECL)
1587161651Skan	dump_unary_op ("&&", t, flags);
158818334Speter      else
158990075Sobrien	dump_unary_op ("&", t, flags);
159018334Speter      break;
159118334Speter
159218334Speter    case INDIRECT_REF:
159318334Speter      if (TREE_HAS_CONSTRUCTOR (t))
159418334Speter	{
159518334Speter	  t = TREE_OPERAND (t, 0);
1596169689Skan	  gcc_assert (TREE_CODE (t) == CALL_EXPR);
159790075Sobrien	  dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1598169689Skan	  pp_cxx_left_paren (cxx_pp);
159990075Sobrien	  dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags);
1600169689Skan	  pp_cxx_right_paren (cxx_pp);
160118334Speter	}
160218334Speter      else
160318334Speter	{
160450397Sobrien	  if (TREE_OPERAND (t,0) != NULL_TREE
160552284Sobrien	      && TREE_TYPE (TREE_OPERAND (t, 0))
160650397Sobrien	      && NEXT_CODE (TREE_OPERAND (t, 0)) == REFERENCE_TYPE)
160790075Sobrien	    dump_expr (TREE_OPERAND (t, 0), flags);
160818334Speter	  else
160990075Sobrien	    dump_unary_op ("*", t, flags);
161018334Speter	}
161118334Speter      break;
161218334Speter
161318334Speter    case NEGATE_EXPR:
161418334Speter    case BIT_NOT_EXPR:
161518334Speter    case TRUTH_NOT_EXPR:
161618334Speter    case PREDECREMENT_EXPR:
161718334Speter    case PREINCREMENT_EXPR:
161890075Sobrien      dump_unary_op (operator_name_info [(int)TREE_CODE (t)].name, t, flags);
161918334Speter      break;
162018334Speter
162118334Speter    case POSTDECREMENT_EXPR:
162218334Speter    case POSTINCREMENT_EXPR:
1623169689Skan      pp_cxx_left_paren (cxx_pp);
162490075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1625169689Skan      pp_cxx_identifier (cxx_pp, operator_name_info[(int)TREE_CODE (t)].name);
1626169689Skan      pp_cxx_right_paren (cxx_pp);
162718334Speter      break;
162818334Speter
162918334Speter    case NON_LVALUE_EXPR:
163018334Speter      /* FIXME: This is a KLUDGE workaround for a parsing problem.  There
163118334Speter	 should be another level of INDIRECT_REF so that I don't have to do
163218334Speter	 this.  */
163350397Sobrien      if (TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == POINTER_TYPE)
163418334Speter	{
163518334Speter	  tree next = TREE_TYPE (TREE_TYPE (t));
163618334Speter
163718334Speter	  while (TREE_CODE (next) == POINTER_TYPE)
163818334Speter	    next = TREE_TYPE (next);
163990075Sobrien
164018334Speter	  if (TREE_CODE (next) == FUNCTION_TYPE)
164118334Speter	    {
164290075Sobrien	      if (flags & TFF_EXPR_IN_PARENS)
1643169689Skan		pp_cxx_left_paren (cxx_pp);
1644169689Skan	      pp_cxx_star (cxx_pp);
164590075Sobrien	      dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
164690075Sobrien	      if (flags & TFF_EXPR_IN_PARENS)
1647169689Skan		pp_cxx_right_paren (cxx_pp);
164818334Speter	      break;
164918334Speter	    }
1650132718Skan	  /* Else fall through.  */
165118334Speter	}
165290075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
165318334Speter      break;
165418334Speter
165518334Speter    case NOP_EXPR:
1656169689Skan    case CONVERT_EXPR:
1657132718Skan      {
1658132718Skan	tree op = TREE_OPERAND (t, 0);
1659169689Skan
1660132718Skan	if (!same_type_p (TREE_TYPE (op), TREE_TYPE (t)))
1661132718Skan	  {
1662132718Skan	    /* It is a cast, but we cannot tell whether it is a
1663132718Skan	       reinterpret or static cast. Use the C style notation.  */
1664132718Skan	    if (flags & TFF_EXPR_IN_PARENS)
1665169689Skan	      pp_cxx_left_paren (cxx_pp);
1666169689Skan	    pp_cxx_left_paren (cxx_pp);
1667132718Skan	    dump_type (TREE_TYPE (t), flags);
1668169689Skan	    pp_cxx_right_paren (cxx_pp);
1669132718Skan	    dump_expr (op, flags | TFF_EXPR_IN_PARENS);
1670132718Skan	    if (flags & TFF_EXPR_IN_PARENS)
1671169689Skan	      pp_cxx_right_paren (cxx_pp);
1672132718Skan	  }
1673132718Skan	else
1674132718Skan	  dump_expr (op, flags);
1675132718Skan	break;
1676132718Skan      }
167790075Sobrien
167818334Speter    case CONSTRUCTOR:
167950397Sobrien      if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
168050397Sobrien	{
1681117395Skan	  tree idx = build_ptrmemfunc_access_expr (t, pfn_identifier);
168250397Sobrien
168390075Sobrien	  if (integer_zerop (idx))
168450397Sobrien	    {
168552284Sobrien	      /* A NULL pointer-to-member constant.  */
1686169689Skan	      pp_cxx_left_paren (cxx_pp);
1687169689Skan	      pp_cxx_left_paren (cxx_pp);
168890075Sobrien	      dump_type (TREE_TYPE (t), flags);
1689169689Skan	      pp_cxx_right_paren (cxx_pp);
1690169689Skan	      pp_character (cxx_pp, '0');
1691169689Skan	      pp_cxx_right_paren (cxx_pp);
169252284Sobrien	      break;
169352284Sobrien	    }
169490075Sobrien	  else if (host_integerp (idx, 0))
169552284Sobrien	    {
169650397Sobrien	      tree virtuals;
169750397Sobrien	      unsigned HOST_WIDE_INT n;
169850397Sobrien
169950397Sobrien	      t = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)));
170050397Sobrien	      t = TYPE_METHOD_BASETYPE (t);
1701169689Skan	      virtuals = BINFO_VIRTUALS (TYPE_BINFO (TYPE_MAIN_VARIANT (t)));
170250397Sobrien
170390075Sobrien	      n = tree_low_cst (idx, 0);
170490075Sobrien
170550397Sobrien	      /* Map vtable index back one, to allow for the null pointer to
170650397Sobrien		 member.  */
170750397Sobrien	      --n;
170850397Sobrien
170950397Sobrien	      while (n > 0 && virtuals)
171050397Sobrien		{
171150397Sobrien		  --n;
171250397Sobrien		  virtuals = TREE_CHAIN (virtuals);
171350397Sobrien		}
171450397Sobrien	      if (virtuals)
171550397Sobrien		{
171690075Sobrien		  dump_expr (BV_FN (virtuals),
1717169689Skan			     flags | TFF_EXPR_IN_PARENS);
171850397Sobrien		  break;
171950397Sobrien		}
172050397Sobrien	    }
172150397Sobrien	}
1722169689Skan      if (TREE_TYPE (t) && EMPTY_CONSTRUCTOR_P (t))
1723132718Skan	{
1724132718Skan	  dump_type (TREE_TYPE (t), 0);
1725169689Skan	  pp_cxx_left_paren (cxx_pp);
1726169689Skan	  pp_cxx_right_paren (cxx_pp);
1727132718Skan	}
1728117395Skan      else
1729132718Skan	{
1730169689Skan	  pp_cxx_left_brace (cxx_pp);
1731169689Skan	  dump_expr_init_vec (CONSTRUCTOR_ELTS (t), flags);
1732169689Skan	  pp_cxx_right_brace (cxx_pp);
1733132718Skan	}
1734169689Skan
173518334Speter      break;
173618334Speter
173718334Speter    case OFFSET_REF:
173818334Speter      {
173918334Speter	tree ob = TREE_OPERAND (t, 0);
174052284Sobrien	if (is_dummy_object (ob))
174152284Sobrien	  {
174252284Sobrien	    t = TREE_OPERAND (t, 1);
174352284Sobrien	    if (TREE_CODE (t) == FUNCTION_DECL)
174452284Sobrien	      /* A::f */
174590075Sobrien	      dump_expr (t, flags | TFF_EXPR_IN_PARENS);
174652284Sobrien	    else if (BASELINK_P (t))
1747169689Skan	      dump_expr (OVL_CURRENT (BASELINK_FUNCTIONS (t)),
1748117395Skan			 flags | TFF_EXPR_IN_PARENS);
174952284Sobrien	    else
175090075Sobrien	      dump_decl (t, flags);
175152284Sobrien	  }
175218334Speter	else
175318334Speter	  {
175452284Sobrien	    if (TREE_CODE (ob) == INDIRECT_REF)
175552284Sobrien	      {
175690075Sobrien		dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS);
1757169689Skan		pp_cxx_arrow (cxx_pp);
1758169689Skan		pp_cxx_star (cxx_pp);
175952284Sobrien	      }
176052284Sobrien	    else
176152284Sobrien	      {
176290075Sobrien		dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
1763169689Skan		pp_cxx_dot (cxx_pp);
1764169689Skan		pp_cxx_star (cxx_pp);
176552284Sobrien	      }
176690075Sobrien	    dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
176718334Speter	  }
176818334Speter	break;
176918334Speter      }
177018334Speter
177150397Sobrien    case TEMPLATE_PARM_INDEX:
177290075Sobrien      dump_decl (TEMPLATE_PARM_DECL (t), flags & ~TFF_DECL_SPECIFIERS);
177350397Sobrien      break;
177450397Sobrien
177550397Sobrien    case SCOPE_REF:
1776146895Skan      pp_expression (cxx_pp, t);
177750397Sobrien      break;
177850397Sobrien
177950397Sobrien    case CAST_EXPR:
178050397Sobrien      if (TREE_OPERAND (t, 0) == NULL_TREE
178150397Sobrien	  || TREE_CHAIN (TREE_OPERAND (t, 0)))
178250397Sobrien	{
178390075Sobrien	  dump_type (TREE_TYPE (t), flags);
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      else
178950397Sobrien	{
1790169689Skan	  pp_cxx_left_paren (cxx_pp);
179190075Sobrien	  dump_type (TREE_TYPE (t), flags);
1792169689Skan	  pp_cxx_right_paren (cxx_pp);
1793169689Skan	  pp_cxx_left_paren (cxx_pp);
179490075Sobrien	  dump_expr_list (TREE_OPERAND (t, 0), flags);
1795169689Skan	  pp_cxx_right_paren (cxx_pp);
179650397Sobrien	}
179750397Sobrien      break;
179850397Sobrien
179990075Sobrien    case STATIC_CAST_EXPR:
1800169689Skan      pp_cxx_identifier (cxx_pp, "static_cast");
180190075Sobrien      goto cast;
180290075Sobrien    case REINTERPRET_CAST_EXPR:
1803169689Skan      pp_cxx_identifier (cxx_pp, "reinterpret_cast");
180490075Sobrien      goto cast;
180590075Sobrien    case CONST_CAST_EXPR:
1806169689Skan      pp_cxx_identifier (cxx_pp, "const_cast");
180790075Sobrien      goto cast;
180890075Sobrien    case DYNAMIC_CAST_EXPR:
1809169689Skan      pp_cxx_identifier (cxx_pp, "dynamic_cast");
181090075Sobrien    cast:
1811169689Skan      pp_cxx_begin_template_argument_list (cxx_pp);
181290075Sobrien      dump_type (TREE_TYPE (t), flags);
1813169689Skan      pp_cxx_end_template_argument_list (cxx_pp);
1814169689Skan      pp_cxx_left_paren (cxx_pp);
181590075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags);
1816169689Skan      pp_cxx_right_paren (cxx_pp);
181790075Sobrien      break;
181890075Sobrien
181950397Sobrien    case ARROW_EXPR:
182090075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags);
1821169689Skan      pp_cxx_arrow (cxx_pp);
182250397Sobrien      break;
182350397Sobrien
182450397Sobrien    case SIZEOF_EXPR:
182550397Sobrien    case ALIGNOF_EXPR:
182650397Sobrien      if (TREE_CODE (t) == SIZEOF_EXPR)
1827169689Skan	pp_cxx_identifier (cxx_pp, "sizeof");
182890075Sobrien      else
182950397Sobrien	{
1830169689Skan	  gcc_assert (TREE_CODE (t) == ALIGNOF_EXPR);
1831169689Skan	  pp_cxx_identifier (cxx_pp, "__alignof__");
183250397Sobrien	}
1833169689Skan      pp_cxx_whitespace (cxx_pp);
1834169689Skan      pp_cxx_left_paren (cxx_pp);
183590075Sobrien      if (TYPE_P (TREE_OPERAND (t, 0)))
183690075Sobrien	dump_type (TREE_OPERAND (t, 0), flags);
183750397Sobrien      else
1838169689Skan	dump_expr (TREE_OPERAND (t, 0), flags);
1839169689Skan      pp_cxx_right_paren (cxx_pp);
184050397Sobrien      break;
184150397Sobrien
1842132718Skan    case REALPART_EXPR:
1843132718Skan    case IMAGPART_EXPR:
1844169689Skan      pp_cxx_identifier (cxx_pp, operator_name_info[TREE_CODE (t)].name);
1845169689Skan      pp_cxx_whitespace (cxx_pp);
1846132718Skan      dump_expr (TREE_OPERAND (t, 0), flags);
1847132718Skan      break;
1848132718Skan
184950397Sobrien    case DEFAULT_ARG:
1850132718Skan      pp_identifier (cxx_pp, "<unparsed>");
185150397Sobrien      break;
185250397Sobrien
185350397Sobrien    case TRY_CATCH_EXPR:
185450397Sobrien    case WITH_CLEANUP_EXPR:
185550397Sobrien    case CLEANUP_POINT_EXPR:
185690075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags);
185750397Sobrien      break;
185850397Sobrien
185990075Sobrien    case PSEUDO_DTOR_EXPR:
186090075Sobrien      dump_expr (TREE_OPERAND (t, 2), flags);
1861169689Skan      pp_cxx_dot (cxx_pp);
186290075Sobrien      dump_type (TREE_OPERAND (t, 0), flags);
1863169689Skan      pp_cxx_colon_colon (cxx_pp);
1864169689Skan      pp_cxx_complement (cxx_pp);
186590075Sobrien      dump_type (TREE_OPERAND (t, 1), flags);
186690075Sobrien      break;
186790075Sobrien
186852284Sobrien    case TEMPLATE_ID_EXPR:
186990075Sobrien      dump_decl (t, flags);
187052284Sobrien      break;
187152284Sobrien
1872169689Skan    case BIND_EXPR:
187390075Sobrien    case STMT_EXPR:
1874169689Skan    case STATEMENT_LIST:
187590075Sobrien      /* We don't yet have a way of dumping statements in a
187690075Sobrien	 human-readable format.  */
1877132718Skan      pp_string (cxx_pp, "({...})");
187890075Sobrien      break;
187990075Sobrien
188090075Sobrien    case LOOP_EXPR:
1881132718Skan      pp_string (cxx_pp, "while (1) { ");
188290075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
1883169689Skan      pp_cxx_right_brace (cxx_pp);
188490075Sobrien      break;
188590075Sobrien
188690075Sobrien    case EXIT_EXPR:
1887132718Skan      pp_string (cxx_pp, "if (");
188890075Sobrien      dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
1889132718Skan      pp_string (cxx_pp, ") break; ");
189090075Sobrien      break;
189190075Sobrien
1892117395Skan    case BASELINK:
1893132718Skan      dump_expr (get_first_fn (t), flags & ~TFF_EXPR_IN_PARENS);
1894117395Skan      break;
1895117395Skan
1896132718Skan    case EMPTY_CLASS_EXPR:
1897132718Skan      dump_type (TREE_TYPE (t), flags);
1898169689Skan      pp_cxx_left_paren (cxx_pp);
1899169689Skan      pp_cxx_right_paren (cxx_pp);
1900132718Skan      break;
190118334Speter
1902132718Skan    case NON_DEPENDENT_EXPR:
1903132718Skan      dump_expr (TREE_OPERAND (t, 0), flags);
1904132718Skan      break;
1905132718Skan
190618334Speter      /*  This list is incomplete, but should suffice for now.
190718334Speter	  It is very important that `sorry' does not call
190818334Speter	  `report_error_function'.  That could cause an infinite loop.  */
190918334Speter    default:
1910132718Skan      pp_unsupported_tree (cxx_pp, t);
191118334Speter      /* fall through to ERROR_MARK...  */
191218334Speter    case ERROR_MARK:
1913132718Skan      pp_identifier (cxx_pp, "<expression error>");
191418334Speter      break;
191518334Speter    }
191618334Speter}
191718334Speter
191818334Speterstatic void
1919132718Skandump_binary_op (const char *opstring, tree t, int flags)
192018334Speter{
1921169689Skan  pp_cxx_left_paren (cxx_pp);
192290075Sobrien  dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1923169689Skan  pp_cxx_whitespace (cxx_pp);
192490075Sobrien  if (opstring)
1925169689Skan    pp_cxx_identifier (cxx_pp, opstring);
192690075Sobrien  else
1927132718Skan    pp_identifier (cxx_pp, "<unknown operator>");
1928169689Skan  pp_cxx_whitespace (cxx_pp);
192990075Sobrien  dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1930169689Skan  pp_cxx_right_paren (cxx_pp);
193118334Speter}
193218334Speter
193318334Speterstatic void
1934132718Skandump_unary_op (const char *opstring, tree t, int flags)
193518334Speter{
193690075Sobrien  if (flags & TFF_EXPR_IN_PARENS)
1937169689Skan    pp_cxx_left_paren (cxx_pp);
1938169689Skan  pp_cxx_identifier (cxx_pp, opstring);
193990075Sobrien  dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
194090075Sobrien  if (flags & TFF_EXPR_IN_PARENS)
1941169689Skan    pp_cxx_right_paren (cxx_pp);
194218334Speter}
194318334Speter
1944169689Skanstatic void
1945169689Skanreinit_cxx_pp (void)
1946169689Skan{
1947169689Skan  pp_clear_output_area (cxx_pp);
1948169689Skan  pp_base (cxx_pp)->padding = pp_none;
1949169689Skan  pp_indentation (cxx_pp) = 0;
1950169689Skan  pp_needs_newline (cxx_pp) = false;
1951169689Skan  cxx_pp->enclosing_scope = 0;
1952169689Skan}
1953169689Skan
1954169689Skan
195590075Sobrien/* Exported interface to stringifying types, exprs and decls under TFF_*
195690075Sobrien   control.  */
195752284Sobrien
195890075Sobrienconst char *
1959132718Skantype_as_string (tree typ, int flags)
196018334Speter{
1961169689Skan  reinit_cxx_pp ();
196290075Sobrien  dump_type (typ, flags);
1963132718Skan  return pp_formatted_text (cxx_pp);
196418334Speter}
196518334Speter
196690075Sobrienconst char *
1967132718Skanexpr_as_string (tree decl, int flags)
196818334Speter{
1969169689Skan  reinit_cxx_pp ();
197090075Sobrien  dump_expr (decl, flags);
1971132718Skan  return pp_formatted_text (cxx_pp);
197218334Speter}
197318334Speter
197490075Sobrienconst char *
1975132718Skandecl_as_string (tree decl, int flags)
197618334Speter{
1977169689Skan  reinit_cxx_pp ();
197890075Sobrien  dump_decl (decl, flags);
1979132718Skan  return pp_formatted_text (cxx_pp);
198018334Speter}
198118334Speter
1982117395Skan/* Generate the three forms of printable names for cxx_printable_name.  */
198350397Sobrien
198490075Sobrienconst char *
1985132718Skanlang_decl_name (tree decl, int v)
198650397Sobrien{
198750397Sobrien  if (v >= 2)
198890075Sobrien    return decl_as_string (decl, TFF_DECL_SPECIFIERS);
198950397Sobrien
1990169689Skan  reinit_cxx_pp ();
199150397Sobrien  if (v == 1 && DECL_CLASS_SCOPE_P (decl))
199250397Sobrien    {
199390075Sobrien      dump_type (CP_DECL_CONTEXT (decl), TFF_PLAIN_IDENTIFIER);
1994169689Skan      pp_cxx_colon_colon (cxx_pp);
199550397Sobrien    }
199650397Sobrien
199750397Sobrien  if (TREE_CODE (decl) == FUNCTION_DECL)
199890075Sobrien    dump_function_name (decl, TFF_PLAIN_IDENTIFIER);
199950397Sobrien  else
200090075Sobrien    dump_decl (DECL_NAME (decl), TFF_PLAIN_IDENTIFIER);
200150397Sobrien
2002132718Skan  return pp_formatted_text (cxx_pp);
200350397Sobrien}
200450397Sobrien
2005169689Skan/* Return the location of a tree passed to %+ formats.  */
2006169689Skan
2007132718Skanstatic location_t
2008132718Skanlocation_of (tree t)
200918334Speter{
201050397Sobrien  if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t))
2011132718Skan    t = DECL_CONTEXT (t);
201290075Sobrien  else if (TYPE_P (t))
2013132718Skan    t = TYPE_MAIN_DECL (t);
201452284Sobrien  else if (TREE_CODE (t) == OVERLOAD)
2015132718Skan    t = OVL_FUNCTION (t);
2016169689Skan
2017132718Skan  return DECL_SOURCE_LOCATION (t);
201818334Speter}
201918334Speter
202090075Sobrien/* Now the interfaces from error et al to dump_type et al. Each takes an
202190075Sobrien   on/off VERBOSE flag and supply the appropriate TFF_ flags to a dump_
202290075Sobrien   function.  */
202390075Sobrien
202490075Sobrienstatic const char *
2025132718Skandecl_to_string (tree decl, int verbose)
202690075Sobrien{
202790075Sobrien  int flags = 0;
202890075Sobrien
202990075Sobrien  if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == RECORD_TYPE
203090075Sobrien      || TREE_CODE (decl) == UNION_TYPE || TREE_CODE (decl) == ENUMERAL_TYPE)
203190075Sobrien    flags = TFF_CLASS_KEY_OR_ENUM;
203290075Sobrien  if (verbose)
2033117395Skan    flags |= TFF_DECL_SPECIFIERS;
203490075Sobrien  else if (TREE_CODE (decl) == FUNCTION_DECL)
203590075Sobrien    flags |= TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE;
203690075Sobrien  flags |= TFF_TEMPLATE_HEADER;
203790075Sobrien
2038169689Skan  reinit_cxx_pp ();
203990075Sobrien  dump_decl (decl, flags);
2040132718Skan  return pp_formatted_text (cxx_pp);
204190075Sobrien}
204290075Sobrien
204390075Sobrienstatic const char *
2044132718Skanexpr_to_string (tree decl)
204590075Sobrien{
2046169689Skan  reinit_cxx_pp ();
204790075Sobrien  dump_expr (decl, 0);
2048132718Skan  return pp_formatted_text (cxx_pp);
204990075Sobrien}
205090075Sobrien
205190075Sobrienstatic const char *
2052132718Skanfndecl_to_string (tree fndecl, int verbose)
205390075Sobrien{
205490075Sobrien  int flags;
205590075Sobrien
2056169689Skan  flags = TFF_EXCEPTION_SPECIFICATION | TFF_DECL_SPECIFIERS
2057169689Skan    | TFF_TEMPLATE_HEADER;
205890075Sobrien  if (verbose)
205990075Sobrien    flags |= TFF_FUNCTION_DEFAULT_ARGUMENTS;
2060169689Skan  reinit_cxx_pp ();
206190075Sobrien  dump_decl (fndecl, flags);
2062132718Skan  return pp_formatted_text (cxx_pp);
206390075Sobrien}
206490075Sobrien
206590075Sobrien
206690075Sobrienstatic const char *
2067132718Skancode_to_string (enum tree_code c)
206818334Speter{
206918334Speter  return tree_code_name [c];
207018334Speter}
207118334Speter
207290075Sobrienconst char *
2073132718Skanlanguage_to_string (enum languages c)
207418334Speter{
207518334Speter  switch (c)
207618334Speter    {
207718334Speter    case lang_c:
207818334Speter      return "C";
207918334Speter
208018334Speter    case lang_cplusplus:
208118334Speter      return "C++";
208218334Speter
208350397Sobrien    case lang_java:
208450397Sobrien      return "Java";
208550397Sobrien
208618334Speter    default:
2087169689Skan      gcc_unreachable ();
208818334Speter    }
2089169689Skan  return NULL;
209018334Speter}
209118334Speter
209218334Speter/* Return the proper printed version of a parameter to a C++ function.  */
209350397Sobrien
209490075Sobrienstatic const char *
2095132718Skanparm_to_string (int p)
209618334Speter{
2097169689Skan  reinit_cxx_pp ();
209818334Speter  if (p < 0)
2099132718Skan    pp_string (cxx_pp, "'this'");
2100132718Skan  else
2101132718Skan    pp_decimal_int (cxx_pp, p + 1);
2102132718Skan  return pp_formatted_text (cxx_pp);
210318334Speter}
210418334Speter
210590075Sobrienstatic const char *
2106132718Skanop_to_string (enum tree_code p)
210718334Speter{
2108132718Skan  tree id = operator_name_info[(int) p].identifier;
2109132718Skan  return id ? IDENTIFIER_POINTER (id) : "<unknown>";
211018334Speter}
211118334Speter
211290075Sobrienstatic const char *
2113132718Skantype_to_string (tree typ, int verbose)
211490075Sobrien{
2115132718Skan  int flags = 0;
211690075Sobrien  if (verbose)
211790075Sobrien    flags |= TFF_CLASS_KEY_OR_ENUM;
211890075Sobrien  flags |= TFF_TEMPLATE_HEADER;
211990075Sobrien
2120169689Skan  reinit_cxx_pp ();
212190075Sobrien  dump_type (typ, flags);
2122132718Skan  return pp_formatted_text (cxx_pp);
212390075Sobrien}
212490075Sobrien
212590075Sobrienstatic const char *
2126132718Skanassop_to_string (enum tree_code p)
212750397Sobrien{
2128132718Skan  tree id = assignment_operator_name_info[(int) p].identifier;
212990075Sobrien  return id ? IDENTIFIER_POINTER (id) : "{unknown}";
213050397Sobrien}
213150397Sobrien
213290075Sobrienstatic const char *
2133132718Skanargs_to_string (tree p, int verbose)
213418334Speter{
213590075Sobrien  int flags = 0;
213690075Sobrien  if (verbose)
213790075Sobrien    flags |= TFF_CLASS_KEY_OR_ENUM;
213890075Sobrien
213918334Speter  if (p == NULL_TREE)
214050397Sobrien    return "";
214118334Speter
214290075Sobrien  if (TYPE_P (TREE_VALUE (p)))
214390075Sobrien    return type_as_string (p, flags);
214450397Sobrien
2145169689Skan  reinit_cxx_pp ();
214650397Sobrien  for (; p; p = TREE_CHAIN (p))
214750397Sobrien    {
214850397Sobrien      if (TREE_VALUE (p) == null_node)
2149169689Skan	pp_cxx_identifier (cxx_pp, "NULL");
215050397Sobrien      else
215190075Sobrien	dump_type (error_type (TREE_VALUE (p)), flags);
215250397Sobrien      if (TREE_CHAIN (p))
2153132718Skan	pp_separate_with_comma (cxx_pp);
215450397Sobrien    }
2155132718Skan  return pp_formatted_text (cxx_pp);
215618334Speter}
215718334Speter
215890075Sobrienstatic const char *
2159132718Skancv_to_string (tree p, int v)
216018334Speter{
2161169689Skan  reinit_cxx_pp ();
2162169689Skan  pp_base (cxx_pp)->padding = v ? pp_before : pp_none;
2163169689Skan  pp_cxx_cv_qualifier_seq (cxx_pp, p);
2164132718Skan  return pp_formatted_text (cxx_pp);
216590075Sobrien}
216618334Speter
2167117395Skan/* Langhook for print_error_function.  */
2168117395Skanvoid
2169132718Skancxx_print_error_function (diagnostic_context *context, const char *file)
217090075Sobrien{
2171117395Skan  lhd_print_error_function (context, file);
2172132718Skan  pp_base_set_prefix (context->printer, file);
2173117395Skan  maybe_print_instantiation_context (context);
217418334Speter}
217590075Sobrien
217690075Sobrienstatic void
2177132718Skancp_diagnostic_starter (diagnostic_context *context,
2178169689Skan		       diagnostic_info *diagnostic)
217990075Sobrien{
2180117395Skan  diagnostic_report_current_module (context);
2181117395Skan  cp_print_error_function (context, diagnostic);
2182117395Skan  maybe_print_instantiation_context (context);
2183132718Skan  pp_base_set_prefix (context->printer, diagnostic_build_prefix (diagnostic));
218490075Sobrien}
218590075Sobrien
218690075Sobrienstatic void
2187132718Skancp_diagnostic_finalizer (diagnostic_context *context,
2188169689Skan			 diagnostic_info *diagnostic ATTRIBUTE_UNUSED)
218990075Sobrien{
2190132718Skan  pp_base_destroy_prefix (context->printer);
219190075Sobrien}
219290075Sobrien
219390075Sobrien/* Print current function onto BUFFER, in the process of reporting
219490075Sobrien   a diagnostic message.  Called from cp_diagnostic_starter.  */
219590075Sobrienstatic void
2196132718Skancp_print_error_function (diagnostic_context *context,
2197169689Skan			 diagnostic_info *diagnostic)
219890075Sobrien{
2199117395Skan  if (diagnostic_last_function_changed (context))
220090075Sobrien    {
2201132718Skan      const char *old_prefix = context->printer->prefix;
2202169689Skan      const char *file = LOCATION_FILE (diagnostic->location);
2203169689Skan      char *new_prefix = file ? file_name_as_prefix (file) : NULL;
220490075Sobrien
2205132718Skan      pp_base_set_prefix (context->printer, new_prefix);
220690075Sobrien
220790075Sobrien      if (current_function_decl == NULL)
2208169689Skan	pp_base_string (context->printer, "At global scope:");
220990075Sobrien      else
2210169689Skan	pp_printf (context->printer, "In %s %qs:",
2211169689Skan		   function_category (current_function_decl),
2212169689Skan		   cxx_printable_name (current_function_decl, 2));
2213132718Skan      pp_base_newline (context->printer);
221490075Sobrien
2215117395Skan      diagnostic_set_last_function (context);
2216132718Skan      pp_base_destroy_prefix (context->printer);
2217132718Skan      context->printer->prefix = old_prefix;
221890075Sobrien    }
221990075Sobrien}
222090075Sobrien
222190075Sobrien/* Returns a description of FUNCTION using standard terminology.  */
222290075Sobrienstatic const char *
2223132718Skanfunction_category (tree fn)
222490075Sobrien{
222590075Sobrien  if (DECL_FUNCTION_MEMBER_P (fn))
222690075Sobrien    {
222790075Sobrien      if (DECL_STATIC_FUNCTION_P (fn))
2228169689Skan	return "static member function";
222990075Sobrien      else if (DECL_COPY_CONSTRUCTOR_P (fn))
2230169689Skan	return "copy constructor";
223190075Sobrien      else if (DECL_CONSTRUCTOR_P (fn))
2232169689Skan	return "constructor";
223390075Sobrien      else if (DECL_DESTRUCTOR_P (fn))
2234169689Skan	return "destructor";
223590075Sobrien      else
2236169689Skan	return "member function";
223790075Sobrien    }
223890075Sobrien  else
223990075Sobrien    return "function";
224090075Sobrien}
224190075Sobrien
224290075Sobrien/* Report the full context of a current template instantiation,
224390075Sobrien   onto BUFFER.  */
224490075Sobrienstatic void
2245132718Skanprint_instantiation_full_context (diagnostic_context *context)
224690075Sobrien{
224790075Sobrien  tree p = current_instantiation ();
2248132718Skan  location_t location = input_location;
2249169689Skan
225090075Sobrien  if (p)
225190075Sobrien    {
225290075Sobrien      if (current_function_decl != TINST_DECL (p)
225390075Sobrien	  && current_function_decl != NULL_TREE)
225490075Sobrien	/* We can get here during the processing of some synthesized
225590075Sobrien	   method.  Then, TINST_DECL (p) will be the function that's causing
225690075Sobrien	   the synthesis.  */
225790075Sobrien	;
225890075Sobrien      else
225990075Sobrien	{
226090075Sobrien	  if (current_function_decl == TINST_DECL (p))
2261169689Skan	    /* Avoid redundancy with the "In function" line.  */;
226290075Sobrien	  else
2263132718Skan	    pp_verbatim (context->printer,
2264169689Skan			 "%s: In instantiation of %qs:\n",
2265169689Skan			 LOCATION_FILE (location),
2266169689Skan			 decl_as_string (TINST_DECL (p),
2267169689Skan					 TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
226890075Sobrien
2269169689Skan	  location = TINST_LOCATION (p);
227090075Sobrien	  p = TREE_CHAIN (p);
227190075Sobrien	}
227290075Sobrien    }
227390075Sobrien
2274132718Skan  print_instantiation_partial_context (context, p, location);
227590075Sobrien}
227690075Sobrien
227790075Sobrien/* Same as above but less verbose.  */
227890075Sobrienstatic void
2279132718Skanprint_instantiation_partial_context (diagnostic_context *context,
2280169689Skan				     tree t, location_t loc)
228190075Sobrien{
2282169689Skan  expanded_location xloc;
2283169689Skan  for (; ; t = TREE_CHAIN (t))
228490075Sobrien    {
2285169689Skan      xloc = expand_location (loc);
2286169689Skan      if (t == NULL_TREE)
2287169689Skan	break;
2288169689Skan      pp_verbatim (context->printer, "%s:%d:   instantiated from %qs\n",
2289169689Skan		   xloc.file, xloc.line,
2290169689Skan		   decl_as_string (TINST_DECL (t),
2291169689Skan				   TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
2292169689Skan      loc = TINST_LOCATION (t);
229390075Sobrien    }
2294169689Skan  pp_verbatim (context->printer, "%s:%d:   instantiated from here",
2295169689Skan	       xloc.file, xloc.line);
2296169689Skan  pp_base_newline (context->printer);
229790075Sobrien}
229890075Sobrien
229990075Sobrien/* Called from cp_thing to print the template context for an error.  */
230090075Sobrienstatic void
2301132718Skanmaybe_print_instantiation_context (diagnostic_context *context)
230290075Sobrien{
230390075Sobrien  if (!problematic_instantiation_changed () || current_instantiation () == 0)
230490075Sobrien    return;
230590075Sobrien
230690075Sobrien  record_last_problematic_instantiation ();
2307117395Skan  print_instantiation_full_context (context);
230890075Sobrien}
230990075Sobrien
231090075Sobrien/* Report the bare minimum context of a template instantiation.  */
231190075Sobrienvoid
2312132718Skanprint_instantiation_context (void)
231390075Sobrien{
231490075Sobrien  print_instantiation_partial_context
2315132718Skan    (global_dc, current_instantiation (), input_location);
2316117395Skan  diagnostic_flush_buffer (global_dc);
231790075Sobrien}
231890075Sobrien
231990075Sobrien/* Called from output_format -- during diagnostic message processing --
232090075Sobrien   to handle C++ specific format specifier with the following meanings:
232190075Sobrien   %A   function argument-list.
232290075Sobrien   %C	tree code.
232390075Sobrien   %D   declaration.
232490075Sobrien   %E   expression.
232590075Sobrien   %F   function declaration.
232690075Sobrien   %L	language as used in extern "lang".
232790075Sobrien   %O	binary operator.
232890075Sobrien   %P   function parameter whose position is indicated by an integer.
232990075Sobrien   %Q	assignment operator.
233090075Sobrien   %T   type.
233190075Sobrien   %V   cv-qualifier.  */
2332117395Skanstatic bool
2333169689Skancp_printer (pretty_printer *pp, text_info *text, const char *spec,
2334169689Skan	    int precision, bool wide, bool set_locus, bool verbose)
233590075Sobrien{
233690075Sobrien  const char *result;
2337169689Skan  tree t = NULL;
2338169689Skan#define next_tree    (t = va_arg (*text->args_ptr, tree))
2339117395Skan#define next_tcode   va_arg (*text->args_ptr, enum tree_code)
2340117395Skan#define next_lang    va_arg (*text->args_ptr, enum languages)
2341117395Skan#define next_int     va_arg (*text->args_ptr, int)
234290075Sobrien
2343169689Skan  if (precision != 0 || wide)
2344169689Skan    return false;
234590075Sobrien
2346169689Skan  if (text->locus == NULL)
2347169689Skan    set_locus = false;
2348169689Skan
2349169689Skan  switch (*spec)
235090075Sobrien    {
235190075Sobrien    case 'A': result = args_to_string (next_tree, verbose);	break;
2352169689Skan    case 'C': result = code_to_string (next_tcode);		break;
2353169689Skan    case 'D':
2354169689Skan      {
2355169689Skan	tree temp = next_tree;
2356169689Skan	if (DECL_P (temp)
2357169689Skan	    && DECL_DEBUG_EXPR_IS_FROM (temp) && DECL_DEBUG_EXPR (temp))
2358169689Skan	  {
2359169689Skan	    temp = DECL_DEBUG_EXPR (temp);
2360169689Skan	    if (!DECL_P (temp))
2361169689Skan	      {
2362169689Skan		result = expr_to_string (temp);
2363169689Skan		break;
2364169689Skan	      }
2365169689Skan	  }
2366169689Skan	result = decl_to_string (temp, verbose);
2367169689Skan      }
2368169689Skan      break;
2369169689Skan    case 'E': result = expr_to_string (next_tree);		break;
237090075Sobrien    case 'F': result = fndecl_to_string (next_tree, verbose);	break;
2371169689Skan    case 'L': result = language_to_string (next_lang);		break;
2372169689Skan    case 'O': result = op_to_string (next_tcode);		break;
2373169689Skan    case 'P': result = parm_to_string (next_int);		break;
2374169689Skan    case 'Q': result = assop_to_string (next_tcode);		break;
237590075Sobrien    case 'T': result = type_to_string (next_tree, verbose);	break;
237690075Sobrien    case 'V': result = cv_to_string (next_tree, verbose);	break;
2377169689Skan
237890075Sobrien    default:
2379117395Skan      return false;
238090075Sobrien    }
238190075Sobrien
2382132718Skan  pp_base_string (pp, result);
2383169689Skan  if (set_locus && t != NULL)
2384169689Skan    *text->locus = location_of (t);
2385117395Skan  return true;
238690075Sobrien#undef next_tree
238790075Sobrien#undef next_tcode
238890075Sobrien#undef next_lang
238990075Sobrien#undef next_int
239090075Sobrien}
2391169689Skan
2392169689Skan/* Callback from cpp_error for PFILE to print diagnostics arising from
2393169689Skan   interpreting strings.  The diagnostic is of type LEVEL; MSG is the
2394169689Skan   translated message and AP the arguments.  */
239590075Sobrien
2396169689Skanvoid
2397169689Skancp_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level,
2398169689Skan	      const char *msg, va_list *ap)
239990075Sobrien{
2400169689Skan  diagnostic_info diagnostic;
2401169689Skan  diagnostic_t dlevel;
2402169689Skan  switch (level)
240390075Sobrien    {
2404169689Skan    case CPP_DL_WARNING:
2405169689Skan    case CPP_DL_WARNING_SYSHDR:
2406169689Skan      dlevel = DK_WARNING;
2407169689Skan      break;
2408169689Skan    case CPP_DL_PEDWARN:
2409169689Skan      dlevel = pedantic_error_kind ();
2410169689Skan      break;
2411169689Skan    case CPP_DL_ERROR:
2412169689Skan      dlevel = DK_ERROR;
2413169689Skan      break;
2414169689Skan    case CPP_DL_ICE:
2415169689Skan      dlevel = DK_ICE;
2416169689Skan      break;
2417169689Skan    default:
2418169689Skan      gcc_unreachable ();
241990075Sobrien    }
2420169689Skan  diagnostic_set_info_translated (&diagnostic, msg, ap,
2421169689Skan				  input_location, dlevel);
2422117395Skan  report_diagnostic (&diagnostic);
242390075Sobrien}
2424