xref: /dflybsd-src/contrib/gcc-8.0/gcc/cp/error.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj /* Call-backs for C++ error reporting.
238fd1498Szrj    This code is non-reentrant.
338fd1498Szrj    Copyright (C) 1993-2018 Free Software Foundation, Inc.
438fd1498Szrj    This file is part of GCC.
538fd1498Szrj 
638fd1498Szrj GCC is free software; you can redistribute it and/or modify
738fd1498Szrj it under the terms of the GNU General Public License as published by
838fd1498Szrj the Free Software Foundation; either version 3, or (at your option)
938fd1498Szrj any later version.
1038fd1498Szrj 
1138fd1498Szrj GCC is distributed in the hope that it will be useful,
1238fd1498Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
1338fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1438fd1498Szrj GNU General Public License for more details.
1538fd1498Szrj 
1638fd1498Szrj You should have received a copy of the GNU General Public License
1738fd1498Szrj along with GCC; see the file COPYING3.  If not see
1838fd1498Szrj <http://www.gnu.org/licenses/>.  */
1938fd1498Szrj 
2038fd1498Szrj #include "config.h"
2138fd1498Szrj #include "system.h"
2238fd1498Szrj #include "coretypes.h"
2338fd1498Szrj #include "cp-tree.h"
2438fd1498Szrj #include "stringpool.h"
2538fd1498Szrj #include "tree-diagnostic.h"
2638fd1498Szrj #include "langhooks-def.h"
2738fd1498Szrj #include "intl.h"
2838fd1498Szrj #include "cxx-pretty-print.h"
2938fd1498Szrj #include "tree-pretty-print.h"
3038fd1498Szrj #include "gimple-pretty-print.h"
3138fd1498Szrj #include "c-family/c-objc.h"
3238fd1498Szrj #include "ubsan.h"
3338fd1498Szrj #include "internal-fn.h"
3438fd1498Szrj 
3538fd1498Szrj #define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',')
3638fd1498Szrj #define pp_separate_with_semicolon(PP) pp_cxx_separate_with (PP, ';')
3738fd1498Szrj 
3838fd1498Szrj /* cxx_pp is a C++ front-end-specific pretty printer: this is where we
3938fd1498Szrj    dump C++ ASTs as strings. It is mostly used only by the various
4038fd1498Szrj    tree -> string functions that are occasionally called from the
4138fd1498Szrj    debugger or by the front-end for things like
4238fd1498Szrj    __PRETTY_FUNCTION__.  */
4338fd1498Szrj static cxx_pretty_printer actual_pretty_printer;
4438fd1498Szrj static cxx_pretty_printer * const cxx_pp = &actual_pretty_printer;
4538fd1498Szrj 
4638fd1498Szrj /* Translate if being used for diagnostics, but not for dump files or
4738fd1498Szrj    __PRETTY_FUNCTION.  */
4838fd1498Szrj #define M_(msgid) (pp_translate_identifiers (cxx_pp) ? _(msgid) : (msgid))
4938fd1498Szrj 
5038fd1498Szrj # define NEXT_CODE(T) (TREE_CODE (TREE_TYPE (T)))
5138fd1498Szrj 
5238fd1498Szrj static const char *args_to_string (tree, int);
5338fd1498Szrj static const char *code_to_string (enum tree_code);
5438fd1498Szrj static const char *cv_to_string (tree, int);
5538fd1498Szrj static const char *decl_to_string (tree, int);
5638fd1498Szrj static const char *expr_to_string (tree);
5738fd1498Szrj static const char *fndecl_to_string (tree, int);
5838fd1498Szrj static const char *op_to_string	(bool, enum tree_code);
5938fd1498Szrj static const char *parm_to_string (int);
6038fd1498Szrj static const char *type_to_string (tree, int, bool, bool *, bool);
6138fd1498Szrj 
6238fd1498Szrj static void dump_alias_template_specialization (cxx_pretty_printer *, tree, int);
6338fd1498Szrj static void dump_type (cxx_pretty_printer *, tree, int);
6438fd1498Szrj static void dump_typename (cxx_pretty_printer *, tree, int);
6538fd1498Szrj static void dump_simple_decl (cxx_pretty_printer *, tree, tree, int);
6638fd1498Szrj static void dump_decl (cxx_pretty_printer *, tree, int);
6738fd1498Szrj static void dump_template_decl (cxx_pretty_printer *, tree, int);
6838fd1498Szrj static void dump_function_decl (cxx_pretty_printer *, tree, int);
6938fd1498Szrj static void dump_expr (cxx_pretty_printer *, tree, int);
7038fd1498Szrj static void dump_unary_op (cxx_pretty_printer *, const char *, tree, int);
7138fd1498Szrj static void dump_binary_op (cxx_pretty_printer *, const char *, tree, int);
7238fd1498Szrj static void dump_aggr_type (cxx_pretty_printer *, tree, int);
7338fd1498Szrj static void dump_type_prefix (cxx_pretty_printer *, tree, int);
7438fd1498Szrj static void dump_type_suffix (cxx_pretty_printer *, tree, int);
7538fd1498Szrj static void dump_function_name (cxx_pretty_printer *, tree, int);
7638fd1498Szrj static void dump_call_expr_args (cxx_pretty_printer *, tree, int, bool);
7738fd1498Szrj static void dump_aggr_init_expr_args (cxx_pretty_printer *, tree, int, bool);
7838fd1498Szrj static void dump_expr_list (cxx_pretty_printer *, tree, int);
7938fd1498Szrj static void dump_global_iord (cxx_pretty_printer *, tree);
8038fd1498Szrj static void dump_parameters (cxx_pretty_printer *, tree, int);
8138fd1498Szrj static void dump_ref_qualifier (cxx_pretty_printer *, tree, int);
8238fd1498Szrj static void dump_exception_spec (cxx_pretty_printer *, tree, int);
8338fd1498Szrj static void dump_template_argument (cxx_pretty_printer *, tree, int);
8438fd1498Szrj static void dump_template_argument_list (cxx_pretty_printer *, tree, int);
8538fd1498Szrj static void dump_template_parameter (cxx_pretty_printer *, tree, int);
8638fd1498Szrj static void dump_template_bindings (cxx_pretty_printer *, tree, tree,
8738fd1498Szrj                                     vec<tree, va_gc> *);
8838fd1498Szrj static void dump_scope (cxx_pretty_printer *, tree, int);
8938fd1498Szrj static void dump_template_parms (cxx_pretty_printer *, tree, int, int);
9038fd1498Szrj static int get_non_default_template_args_count (tree, int);
9138fd1498Szrj static const char *function_category (tree);
9238fd1498Szrj static void maybe_print_constexpr_context (diagnostic_context *);
9338fd1498Szrj static void maybe_print_instantiation_context (diagnostic_context *);
9438fd1498Szrj static void print_instantiation_full_context (diagnostic_context *);
9538fd1498Szrj static void print_instantiation_partial_context (diagnostic_context *,
9638fd1498Szrj 						 struct tinst_level *,
9738fd1498Szrj 						 location_t);
9838fd1498Szrj static void cp_diagnostic_starter (diagnostic_context *, diagnostic_info *);
9938fd1498Szrj static void cp_print_error_function (diagnostic_context *, diagnostic_info *);
10038fd1498Szrj 
10138fd1498Szrj static bool cp_printer (pretty_printer *, text_info *, const char *,
10238fd1498Szrj 			int, bool, bool, bool, bool *, const char **);
10338fd1498Szrj 
10438fd1498Szrj /* Struct for handling %H or %I, which require delaying printing the
10538fd1498Szrj    type until a postprocessing stage.  */
10638fd1498Szrj 
10738fd1498Szrj struct deferred_printed_type
10838fd1498Szrj {
deferred_printed_typedeferred_printed_type10938fd1498Szrj   deferred_printed_type ()
11038fd1498Szrj   : m_tree (NULL_TREE), m_buffer_ptr (NULL), m_verbose (false), m_quote (false)
11138fd1498Szrj   {}
11238fd1498Szrj 
deferred_printed_typedeferred_printed_type11338fd1498Szrj   deferred_printed_type (tree type, const char **buffer_ptr, bool verbose,
11438fd1498Szrj 			 bool quote)
11538fd1498Szrj   : m_tree (type), m_buffer_ptr (buffer_ptr), m_verbose (verbose),
11638fd1498Szrj     m_quote (quote)
11738fd1498Szrj   {
11838fd1498Szrj     gcc_assert (type);
11938fd1498Szrj     gcc_assert (buffer_ptr);
12038fd1498Szrj   }
12138fd1498Szrj 
12238fd1498Szrj   /* The tree is not GTY-marked: they are only non-NULL within a
12338fd1498Szrj      call to pp_format.  */
12438fd1498Szrj   tree m_tree;
12538fd1498Szrj   const char **m_buffer_ptr;
12638fd1498Szrj   bool m_verbose;
12738fd1498Szrj   bool m_quote;
12838fd1498Szrj };
12938fd1498Szrj 
13038fd1498Szrj /* Subclass of format_postprocessor for the C++ frontend.
13138fd1498Szrj    This handles the %H and %I formatting codes, printing them
13238fd1498Szrj    in a postprocessing phase (since they affect each other).  */
13338fd1498Szrj 
13438fd1498Szrj class cxx_format_postprocessor : public format_postprocessor
13538fd1498Szrj {
13638fd1498Szrj  public:
cxx_format_postprocessor()13738fd1498Szrj   cxx_format_postprocessor ()
13838fd1498Szrj   : m_type_a (), m_type_b ()
13938fd1498Szrj   {}
14038fd1498Szrj 
14138fd1498Szrj   void handle (pretty_printer *pp) FINAL OVERRIDE;
14238fd1498Szrj 
14338fd1498Szrj   deferred_printed_type m_type_a;
14438fd1498Szrj   deferred_printed_type m_type_b;
14538fd1498Szrj };
14638fd1498Szrj 
14738fd1498Szrj /* CONTEXT->printer is a basic pretty printer that was constructed
14838fd1498Szrj    presumably by diagnostic_initialize(), called early in the
14938fd1498Szrj    compiler's initialization process (in general_init) Before the FE
15038fd1498Szrj    is initialized.  This (C++) FE-specific diagnostic initializer is
15138fd1498Szrj    thus replacing the basic pretty printer with one that has C++-aware
15238fd1498Szrj    capacities.  */
15338fd1498Szrj 
15438fd1498Szrj void
cxx_initialize_diagnostics(diagnostic_context * context)15538fd1498Szrj cxx_initialize_diagnostics (diagnostic_context *context)
15638fd1498Szrj {
15738fd1498Szrj   pretty_printer *base = context->printer;
15838fd1498Szrj   cxx_pretty_printer *pp = XNEW (cxx_pretty_printer);
15938fd1498Szrj   context->printer = new (pp) cxx_pretty_printer ();
16038fd1498Szrj 
16138fd1498Szrj   /* It is safe to free this object because it was previously XNEW()'d.  */
16238fd1498Szrj   base->~pretty_printer ();
16338fd1498Szrj   XDELETE (base);
16438fd1498Szrj 
16538fd1498Szrj   c_common_diagnostics_set_defaults (context);
16638fd1498Szrj   diagnostic_starter (context) = cp_diagnostic_starter;
16738fd1498Szrj   /* diagnostic_finalizer is already c_diagnostic_finalizer.  */
16838fd1498Szrj   diagnostic_format_decoder (context) = cp_printer;
16938fd1498Szrj   pp->m_format_postprocessor = new cxx_format_postprocessor ();
17038fd1498Szrj }
17138fd1498Szrj 
17238fd1498Szrj /* Dump a scope, if deemed necessary.  */
17338fd1498Szrj 
17438fd1498Szrj static void
dump_scope(cxx_pretty_printer * pp,tree scope,int flags)17538fd1498Szrj dump_scope (cxx_pretty_printer *pp, tree scope, int flags)
17638fd1498Szrj {
17738fd1498Szrj   int f = flags & (TFF_SCOPE | TFF_CHASE_TYPEDEF);
17838fd1498Szrj 
17938fd1498Szrj   if (scope == NULL_TREE)
18038fd1498Szrj     return;
18138fd1498Szrj 
18238fd1498Szrj   if (TREE_CODE (scope) == NAMESPACE_DECL)
18338fd1498Szrj     {
18438fd1498Szrj       if (scope != global_namespace)
18538fd1498Szrj 	{
18638fd1498Szrj           dump_decl (pp, scope, f);
18738fd1498Szrj 	  pp_cxx_colon_colon (pp);
18838fd1498Szrj 	}
18938fd1498Szrj     }
19038fd1498Szrj   else if (AGGREGATE_TYPE_P (scope))
19138fd1498Szrj     {
19238fd1498Szrj       dump_type (pp, scope, f);
19338fd1498Szrj       pp_cxx_colon_colon (pp);
19438fd1498Szrj     }
19538fd1498Szrj   else if ((flags & TFF_SCOPE) && TREE_CODE (scope) == FUNCTION_DECL)
19638fd1498Szrj     {
19738fd1498Szrj       dump_function_decl (pp, scope, f);
19838fd1498Szrj       pp_cxx_colon_colon (pp);
19938fd1498Szrj     }
20038fd1498Szrj }
20138fd1498Szrj 
20238fd1498Szrj /* Dump the template ARGument under control of FLAGS.  */
20338fd1498Szrj 
20438fd1498Szrj static void
dump_template_argument(cxx_pretty_printer * pp,tree arg,int flags)20538fd1498Szrj dump_template_argument (cxx_pretty_printer *pp, tree arg, int flags)
20638fd1498Szrj {
20738fd1498Szrj   if (ARGUMENT_PACK_P (arg))
20838fd1498Szrj     dump_template_argument_list (pp, ARGUMENT_PACK_ARGS (arg),
20938fd1498Szrj 				 /* No default args in argument packs.  */
21038fd1498Szrj 				 flags|TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS);
21138fd1498Szrj   else if (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL)
21238fd1498Szrj     dump_type (pp, arg, flags & ~TFF_CLASS_KEY_OR_ENUM);
21338fd1498Szrj   else
21438fd1498Szrj     {
21538fd1498Szrj       if (TREE_CODE (arg) == TREE_LIST)
21638fd1498Szrj 	arg = TREE_VALUE (arg);
21738fd1498Szrj 
21838fd1498Szrj       /* Strip implicit conversions.  */
21938fd1498Szrj       while (CONVERT_EXPR_P (arg))
22038fd1498Szrj 	arg = TREE_OPERAND (arg, 0);
22138fd1498Szrj 
22238fd1498Szrj       dump_expr (pp, arg, (flags | TFF_EXPR_IN_PARENS) & ~TFF_CLASS_KEY_OR_ENUM);
22338fd1498Szrj     }
22438fd1498Szrj }
22538fd1498Szrj 
22638fd1498Szrj /* Count the number of template arguments ARGS whose value does not
22738fd1498Szrj    match the (optional) default template parameter in PARAMS  */
22838fd1498Szrj 
22938fd1498Szrj static int
get_non_default_template_args_count(tree args,int flags)23038fd1498Szrj get_non_default_template_args_count (tree args, int flags)
23138fd1498Szrj {
23238fd1498Szrj   int n = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_ARGS (args));
23338fd1498Szrj 
23438fd1498Szrj   if (/* We use this flag when generating debug information.  We don't
23538fd1498Szrj 	 want to expand templates at this point, for this may generate
23638fd1498Szrj 	 new decls, which gets decl counts out of sync, which may in
23738fd1498Szrj 	 turn cause codegen differences between compilations with and
23838fd1498Szrj 	 without -g.  */
23938fd1498Szrj       (flags & TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS) != 0
24038fd1498Szrj       || !flag_pretty_templates)
24138fd1498Szrj     return n;
24238fd1498Szrj 
24338fd1498Szrj   return GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (INNERMOST_TEMPLATE_ARGS (args));
24438fd1498Szrj }
24538fd1498Szrj 
24638fd1498Szrj /* Dump a template-argument-list ARGS (always a TREE_VEC) under control
24738fd1498Szrj    of FLAGS.  */
24838fd1498Szrj 
24938fd1498Szrj static void
dump_template_argument_list(cxx_pretty_printer * pp,tree args,int flags)25038fd1498Szrj dump_template_argument_list (cxx_pretty_printer *pp, tree args, int flags)
25138fd1498Szrj {
25238fd1498Szrj   int n = get_non_default_template_args_count (args, flags);
25338fd1498Szrj   int need_comma = 0;
25438fd1498Szrj   int i;
25538fd1498Szrj 
25638fd1498Szrj   for (i = 0; i < n; ++i)
25738fd1498Szrj     {
25838fd1498Szrj       tree arg = TREE_VEC_ELT (args, i);
25938fd1498Szrj 
26038fd1498Szrj       /* Only print a comma if we know there is an argument coming. In
26138fd1498Szrj          the case of an empty template argument pack, no actual
26238fd1498Szrj          argument will be printed.  */
26338fd1498Szrj       if (need_comma
26438fd1498Szrj           && (!ARGUMENT_PACK_P (arg)
26538fd1498Szrj               || TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg)) > 0))
26638fd1498Szrj 	pp_separate_with_comma (pp);
26738fd1498Szrj 
26838fd1498Szrj       dump_template_argument (pp, arg, flags);
26938fd1498Szrj       need_comma = 1;
27038fd1498Szrj     }
27138fd1498Szrj }
27238fd1498Szrj 
27338fd1498Szrj /* Dump a template parameter PARM (a TREE_LIST) under control of FLAGS.  */
27438fd1498Szrj 
27538fd1498Szrj static void
dump_template_parameter(cxx_pretty_printer * pp,tree parm,int flags)27638fd1498Szrj dump_template_parameter (cxx_pretty_printer *pp, tree parm, int flags)
27738fd1498Szrj {
27838fd1498Szrj   tree p;
27938fd1498Szrj   tree a;
28038fd1498Szrj 
28138fd1498Szrj   if (parm == error_mark_node)
28238fd1498Szrj    return;
28338fd1498Szrj 
28438fd1498Szrj   p = TREE_VALUE (parm);
28538fd1498Szrj   a = TREE_PURPOSE (parm);
28638fd1498Szrj 
28738fd1498Szrj   if (TREE_CODE (p) == TYPE_DECL)
28838fd1498Szrj     {
28938fd1498Szrj       if (flags & TFF_DECL_SPECIFIERS)
29038fd1498Szrj 	{
29138fd1498Szrj 	  pp_cxx_ws_string (pp, "class");
29238fd1498Szrj           if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (p)))
29338fd1498Szrj             pp_cxx_ws_string (pp, "...");
29438fd1498Szrj 	  if (DECL_NAME (p))
29538fd1498Szrj 	    pp_cxx_tree_identifier (pp, DECL_NAME (p));
29638fd1498Szrj 	}
29738fd1498Szrj       else if (DECL_NAME (p))
29838fd1498Szrj 	pp_cxx_tree_identifier (pp, DECL_NAME (p));
29938fd1498Szrj       else
30038fd1498Szrj 	pp_cxx_canonical_template_parameter (pp, TREE_TYPE (p));
30138fd1498Szrj     }
30238fd1498Szrj   else
30338fd1498Szrj     dump_decl (pp, p, flags | TFF_DECL_SPECIFIERS);
30438fd1498Szrj 
30538fd1498Szrj   if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && a != NULL_TREE)
30638fd1498Szrj     {
30738fd1498Szrj       pp_cxx_whitespace (pp);
30838fd1498Szrj       pp_equal (pp);
30938fd1498Szrj       pp_cxx_whitespace (pp);
31038fd1498Szrj       if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL)
31138fd1498Szrj 	dump_type (pp, a, flags & ~TFF_CHASE_TYPEDEF);
31238fd1498Szrj       else
31338fd1498Szrj 	dump_expr (pp, a, flags | TFF_EXPR_IN_PARENS);
31438fd1498Szrj     }
31538fd1498Szrj }
31638fd1498Szrj 
31738fd1498Szrj /* Dump, under control of FLAGS, a template-parameter-list binding.
31838fd1498Szrj    PARMS is a TREE_LIST of TREE_VEC of TREE_LIST and ARGS is a
31938fd1498Szrj    TREE_VEC.  */
32038fd1498Szrj 
32138fd1498Szrj static void
dump_template_bindings(cxx_pretty_printer * pp,tree parms,tree args,vec<tree,va_gc> * typenames)32238fd1498Szrj dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args,
32338fd1498Szrj                         vec<tree, va_gc> *typenames)
32438fd1498Szrj {
32538fd1498Szrj   bool need_semicolon = false;
32638fd1498Szrj   int i;
32738fd1498Szrj   tree t;
32838fd1498Szrj 
32938fd1498Szrj   while (parms)
33038fd1498Szrj     {
33138fd1498Szrj       tree p = TREE_VALUE (parms);
33238fd1498Szrj       int lvl = TMPL_PARMS_DEPTH (parms);
33338fd1498Szrj       int arg_idx = 0;
33438fd1498Szrj       int i;
33538fd1498Szrj       tree lvl_args = NULL_TREE;
33638fd1498Szrj 
33738fd1498Szrj       /* Don't crash if we had an invalid argument list.  */
33838fd1498Szrj       if (TMPL_ARGS_DEPTH (args) >= lvl)
33938fd1498Szrj 	lvl_args = TMPL_ARGS_LEVEL (args, lvl);
34038fd1498Szrj 
34138fd1498Szrj       for (i = 0; i < TREE_VEC_LENGTH (p); ++i)
34238fd1498Szrj 	{
34338fd1498Szrj 	  tree arg = NULL_TREE;
34438fd1498Szrj 
34538fd1498Szrj 	  /* Don't crash if we had an invalid argument list.  */
34638fd1498Szrj 	  if (lvl_args && NUM_TMPL_ARGS (lvl_args) > arg_idx)
34738fd1498Szrj 	    arg = TREE_VEC_ELT (lvl_args, arg_idx);
34838fd1498Szrj 
34938fd1498Szrj 	  if (need_semicolon)
35038fd1498Szrj 	    pp_separate_with_semicolon (pp);
35138fd1498Szrj 	  dump_template_parameter (pp, TREE_VEC_ELT (p, i),
35238fd1498Szrj                                    TFF_PLAIN_IDENTIFIER);
35338fd1498Szrj 	  pp_cxx_whitespace (pp);
35438fd1498Szrj 	  pp_equal (pp);
35538fd1498Szrj 	  pp_cxx_whitespace (pp);
35638fd1498Szrj 	  if (arg)
35738fd1498Szrj 	    {
35838fd1498Szrj 	      if (ARGUMENT_PACK_P (arg))
35938fd1498Szrj 		pp_cxx_left_brace (pp);
36038fd1498Szrj 	      dump_template_argument (pp, arg, TFF_PLAIN_IDENTIFIER);
36138fd1498Szrj 	      if (ARGUMENT_PACK_P (arg))
36238fd1498Szrj 		pp_cxx_right_brace (pp);
36338fd1498Szrj 	    }
36438fd1498Szrj 	  else
36538fd1498Szrj 	    pp_string (pp, M_("<missing>"));
36638fd1498Szrj 
36738fd1498Szrj 	  ++arg_idx;
36838fd1498Szrj 	  need_semicolon = true;
36938fd1498Szrj 	}
37038fd1498Szrj 
37138fd1498Szrj       parms = TREE_CHAIN (parms);
37238fd1498Szrj     }
37338fd1498Szrj 
37438fd1498Szrj   /* Don't bother with typenames for a partial instantiation.  */
37538fd1498Szrj   if (vec_safe_is_empty (typenames) || uses_template_parms (args))
37638fd1498Szrj     return;
37738fd1498Szrj 
37838fd1498Szrj   /* Don't try to print typenames when we're processing a clone.  */
37938fd1498Szrj   if (current_function_decl
38038fd1498Szrj       && !DECL_LANG_SPECIFIC (current_function_decl))
38138fd1498Szrj     return;
38238fd1498Szrj 
38338fd1498Szrj   /* Don't try to do this once cgraph starts throwing away front-end
38438fd1498Szrj      information.  */
38538fd1498Szrj   if (at_eof >= 2)
38638fd1498Szrj     return;
38738fd1498Szrj 
38838fd1498Szrj   FOR_EACH_VEC_SAFE_ELT (typenames, i, t)
38938fd1498Szrj     {
39038fd1498Szrj       if (need_semicolon)
39138fd1498Szrj 	pp_separate_with_semicolon (pp);
39238fd1498Szrj       dump_type (pp, t, TFF_PLAIN_IDENTIFIER);
39338fd1498Szrj       pp_cxx_whitespace (pp);
39438fd1498Szrj       pp_equal (pp);
39538fd1498Szrj       pp_cxx_whitespace (pp);
39638fd1498Szrj       push_deferring_access_checks (dk_no_check);
39738fd1498Szrj       t = tsubst (t, args, tf_none, NULL_TREE);
39838fd1498Szrj       pop_deferring_access_checks ();
39938fd1498Szrj       /* Strip typedefs.  We can't just use TFF_CHASE_TYPEDEF because
40038fd1498Szrj 	 pp_simple_type_specifier doesn't know about it.  */
40138fd1498Szrj       t = strip_typedefs (t);
40238fd1498Szrj       dump_type (pp, t, TFF_PLAIN_IDENTIFIER);
40338fd1498Szrj     }
40438fd1498Szrj }
40538fd1498Szrj 
40638fd1498Szrj /* Dump a human-readable equivalent of the alias template
40738fd1498Szrj    specialization of T.  */
40838fd1498Szrj 
40938fd1498Szrj static void
dump_alias_template_specialization(cxx_pretty_printer * pp,tree t,int flags)41038fd1498Szrj dump_alias_template_specialization (cxx_pretty_printer *pp, tree t, int flags)
41138fd1498Szrj {
41238fd1498Szrj   gcc_assert (alias_template_specialization_p (t));
41338fd1498Szrj 
41438fd1498Szrj   tree decl = TYPE_NAME (t);
41538fd1498Szrj   if (!(flags & TFF_UNQUALIFIED_NAME))
41638fd1498Szrj     dump_scope (pp, CP_DECL_CONTEXT (decl), flags);
41738fd1498Szrj   pp_cxx_tree_identifier (pp, DECL_NAME (decl));
41838fd1498Szrj   dump_template_parms (pp, DECL_TEMPLATE_INFO (decl),
41938fd1498Szrj 		       /*primary=*/false,
42038fd1498Szrj 		       flags & ~TFF_TEMPLATE_HEADER);
42138fd1498Szrj }
42238fd1498Szrj 
42338fd1498Szrj /* Dump a human-readable equivalent of TYPE.  FLAGS controls the
42438fd1498Szrj    format.  */
42538fd1498Szrj 
42638fd1498Szrj static void
dump_type(cxx_pretty_printer * pp,tree t,int flags)42738fd1498Szrj dump_type (cxx_pretty_printer *pp, tree t, int flags)
42838fd1498Szrj {
42938fd1498Szrj   if (t == NULL_TREE)
43038fd1498Szrj     return;
43138fd1498Szrj 
43238fd1498Szrj   /* Don't print e.g. "struct mytypedef".  */
43338fd1498Szrj   if (TYPE_P (t) && typedef_variant_p (t))
43438fd1498Szrj     {
43538fd1498Szrj       tree decl = TYPE_NAME (t);
43638fd1498Szrj       if ((flags & TFF_CHASE_TYPEDEF)
43738fd1498Szrj 	       || DECL_SELF_REFERENCE_P (decl)
43838fd1498Szrj 	       || (!flag_pretty_templates
43938fd1498Szrj 		   && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)))
44038fd1498Szrj 	t = strip_typedefs (t);
44138fd1498Szrj       else if (alias_template_specialization_p (t))
44238fd1498Szrj 	{
44338fd1498Szrj 	  dump_alias_template_specialization (pp, t, flags);
44438fd1498Szrj 	  return;
44538fd1498Szrj 	}
44638fd1498Szrj       else if (same_type_p (t, TREE_TYPE (decl)))
44738fd1498Szrj 	t = decl;
44838fd1498Szrj       else
44938fd1498Szrj 	{
45038fd1498Szrj 	  pp_cxx_cv_qualifier_seq (pp, t);
45138fd1498Szrj 	  pp_cxx_tree_identifier (pp, TYPE_IDENTIFIER (t));
45238fd1498Szrj 	  return;
45338fd1498Szrj 	}
45438fd1498Szrj     }
45538fd1498Szrj 
45638fd1498Szrj   if (TYPE_PTRMEMFUNC_P (t))
45738fd1498Szrj     goto offset_type;
45838fd1498Szrj 
45938fd1498Szrj   switch (TREE_CODE (t))
46038fd1498Szrj     {
46138fd1498Szrj     case LANG_TYPE:
46238fd1498Szrj       if (t == init_list_type_node)
46338fd1498Szrj 	pp_string (pp, M_("<brace-enclosed initializer list>"));
46438fd1498Szrj       else if (t == unknown_type_node)
46538fd1498Szrj 	pp_string (pp, M_("<unresolved overloaded function type>"));
46638fd1498Szrj       else
46738fd1498Szrj 	{
46838fd1498Szrj 	  pp_cxx_cv_qualifier_seq (pp, t);
46938fd1498Szrj 	  pp_cxx_tree_identifier (pp, TYPE_IDENTIFIER (t));
47038fd1498Szrj 	}
47138fd1498Szrj       break;
47238fd1498Szrj 
47338fd1498Szrj     case TREE_LIST:
47438fd1498Szrj       /* A list of function parms.  */
47538fd1498Szrj       dump_parameters (pp, t, flags);
47638fd1498Szrj       break;
47738fd1498Szrj 
47838fd1498Szrj     case IDENTIFIER_NODE:
47938fd1498Szrj       pp_cxx_tree_identifier (pp, t);
48038fd1498Szrj       break;
48138fd1498Szrj 
48238fd1498Szrj     case TREE_BINFO:
48338fd1498Szrj       dump_type (pp, BINFO_TYPE (t), flags);
48438fd1498Szrj       break;
48538fd1498Szrj 
48638fd1498Szrj     case RECORD_TYPE:
48738fd1498Szrj     case UNION_TYPE:
48838fd1498Szrj     case ENUMERAL_TYPE:
48938fd1498Szrj       dump_aggr_type (pp, t, flags);
49038fd1498Szrj       break;
49138fd1498Szrj 
49238fd1498Szrj     case TYPE_DECL:
49338fd1498Szrj       if (flags & TFF_CHASE_TYPEDEF)
49438fd1498Szrj 	{
49538fd1498Szrj 	  dump_type (pp, DECL_ORIGINAL_TYPE (t)
49638fd1498Szrj 		     ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t), flags);
49738fd1498Szrj 	  break;
49838fd1498Szrj 	}
49938fd1498Szrj       /* Fall through.  */
50038fd1498Szrj 
50138fd1498Szrj     case TEMPLATE_DECL:
50238fd1498Szrj     case NAMESPACE_DECL:
50338fd1498Szrj       dump_decl (pp, t, flags & ~TFF_DECL_SPECIFIERS);
50438fd1498Szrj       break;
50538fd1498Szrj 
50638fd1498Szrj     case INTEGER_TYPE:
50738fd1498Szrj     case REAL_TYPE:
50838fd1498Szrj     case VOID_TYPE:
50938fd1498Szrj     case BOOLEAN_TYPE:
51038fd1498Szrj     case COMPLEX_TYPE:
51138fd1498Szrj     case VECTOR_TYPE:
51238fd1498Szrj     case FIXED_POINT_TYPE:
51338fd1498Szrj       pp_type_specifier_seq (pp, t);
51438fd1498Szrj       break;
51538fd1498Szrj 
51638fd1498Szrj     case TEMPLATE_TEMPLATE_PARM:
51738fd1498Szrj       /* For parameters inside template signature.  */
51838fd1498Szrj       if (TYPE_IDENTIFIER (t))
51938fd1498Szrj 	pp_cxx_tree_identifier (pp, TYPE_IDENTIFIER (t));
52038fd1498Szrj       else
52138fd1498Szrj 	pp_cxx_canonical_template_parameter (pp, t);
52238fd1498Szrj       break;
52338fd1498Szrj 
52438fd1498Szrj     case BOUND_TEMPLATE_TEMPLATE_PARM:
52538fd1498Szrj       {
52638fd1498Szrj 	tree args = TYPE_TI_ARGS (t);
52738fd1498Szrj 	pp_cxx_cv_qualifier_seq (pp, t);
52838fd1498Szrj 	pp_cxx_tree_identifier (pp, TYPE_IDENTIFIER (t));
52938fd1498Szrj 	pp_cxx_begin_template_argument_list (pp);
53038fd1498Szrj 	dump_template_argument_list (pp, args, flags);
53138fd1498Szrj 	pp_cxx_end_template_argument_list (pp);
53238fd1498Szrj       }
53338fd1498Szrj       break;
53438fd1498Szrj 
53538fd1498Szrj     case TEMPLATE_TYPE_PARM:
53638fd1498Szrj       pp_cxx_cv_qualifier_seq (pp, t);
53738fd1498Szrj       if (tree c = PLACEHOLDER_TYPE_CONSTRAINTS (t))
53838fd1498Szrj 	pp_cxx_constrained_type_spec (pp, c);
53938fd1498Szrj       else if (TYPE_IDENTIFIER (t))
54038fd1498Szrj 	pp_cxx_tree_identifier (pp, TYPE_IDENTIFIER (t));
54138fd1498Szrj       else
54238fd1498Szrj 	pp_cxx_canonical_template_parameter
54338fd1498Szrj 	  (pp, TEMPLATE_TYPE_PARM_INDEX (t));
54438fd1498Szrj       break;
54538fd1498Szrj 
54638fd1498Szrj       /* This is not always necessary for pointers and such, but doing this
54738fd1498Szrj 	 reduces code size.  */
54838fd1498Szrj     case ARRAY_TYPE:
54938fd1498Szrj     case POINTER_TYPE:
55038fd1498Szrj     case REFERENCE_TYPE:
55138fd1498Szrj     case OFFSET_TYPE:
55238fd1498Szrj     offset_type:
55338fd1498Szrj     case FUNCTION_TYPE:
55438fd1498Szrj     case METHOD_TYPE:
55538fd1498Szrj     {
55638fd1498Szrj       dump_type_prefix (pp, t, flags);
55738fd1498Szrj       dump_type_suffix (pp, t, flags);
55838fd1498Szrj       break;
55938fd1498Szrj     }
56038fd1498Szrj     case TYPENAME_TYPE:
56138fd1498Szrj       if (! (flags & TFF_CHASE_TYPEDEF)
56238fd1498Szrj 	  && DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
56338fd1498Szrj 	{
56438fd1498Szrj 	  dump_decl (pp, TYPE_NAME (t), TFF_PLAIN_IDENTIFIER);
56538fd1498Szrj 	  break;
56638fd1498Szrj 	}
56738fd1498Szrj       pp_cxx_cv_qualifier_seq (pp, t);
56838fd1498Szrj       pp_cxx_ws_string (pp,
56938fd1498Szrj 			 TYPENAME_IS_ENUM_P (t) ? "enum"
57038fd1498Szrj 			 : TYPENAME_IS_CLASS_P (t) ? "class"
57138fd1498Szrj 			 : "typename");
57238fd1498Szrj       dump_typename (pp, t, flags);
57338fd1498Szrj       break;
57438fd1498Szrj 
57538fd1498Szrj     case UNBOUND_CLASS_TEMPLATE:
57638fd1498Szrj       if (! (flags & TFF_UNQUALIFIED_NAME))
57738fd1498Szrj 	{
57838fd1498Szrj 	  dump_type (pp, TYPE_CONTEXT (t), flags);
57938fd1498Szrj 	  pp_cxx_colon_colon (pp);
58038fd1498Szrj 	}
58138fd1498Szrj       pp_cxx_ws_string (pp, "template");
58238fd1498Szrj       dump_type (pp, TYPE_IDENTIFIER (t), flags);
58338fd1498Szrj       break;
58438fd1498Szrj 
58538fd1498Szrj     case TYPEOF_TYPE:
58638fd1498Szrj       pp_cxx_ws_string (pp, "__typeof__");
58738fd1498Szrj       pp_cxx_whitespace (pp);
58838fd1498Szrj       pp_cxx_left_paren (pp);
58938fd1498Szrj       dump_expr (pp, TYPEOF_TYPE_EXPR (t), flags & ~TFF_EXPR_IN_PARENS);
59038fd1498Szrj       pp_cxx_right_paren (pp);
59138fd1498Szrj       break;
59238fd1498Szrj 
59338fd1498Szrj     case UNDERLYING_TYPE:
59438fd1498Szrj       pp_cxx_ws_string (pp, "__underlying_type");
59538fd1498Szrj       pp_cxx_whitespace (pp);
59638fd1498Szrj       pp_cxx_left_paren (pp);
59738fd1498Szrj       dump_expr (pp, UNDERLYING_TYPE_TYPE (t), flags & ~TFF_EXPR_IN_PARENS);
59838fd1498Szrj       pp_cxx_right_paren (pp);
59938fd1498Szrj       break;
60038fd1498Szrj 
60138fd1498Szrj     case TYPE_PACK_EXPANSION:
60238fd1498Szrj       dump_type (pp, PACK_EXPANSION_PATTERN (t), flags);
60338fd1498Szrj       pp_cxx_ws_string (pp, "...");
60438fd1498Szrj       break;
60538fd1498Szrj 
60638fd1498Szrj     case TYPE_ARGUMENT_PACK:
60738fd1498Szrj       dump_template_argument (pp, t, flags);
60838fd1498Szrj       break;
60938fd1498Szrj 
61038fd1498Szrj     case DECLTYPE_TYPE:
61138fd1498Szrj       pp_cxx_ws_string (pp, "decltype");
61238fd1498Szrj       pp_cxx_whitespace (pp);
61338fd1498Szrj       pp_cxx_left_paren (pp);
61438fd1498Szrj       dump_expr (pp, DECLTYPE_TYPE_EXPR (t), flags & ~TFF_EXPR_IN_PARENS);
61538fd1498Szrj       pp_cxx_right_paren (pp);
61638fd1498Szrj       break;
61738fd1498Szrj 
61838fd1498Szrj     case NULLPTR_TYPE:
61938fd1498Szrj       pp_string (pp, "std::nullptr_t");
62038fd1498Szrj       break;
62138fd1498Szrj 
62238fd1498Szrj     default:
62338fd1498Szrj       pp_unsupported_tree (pp, t);
62438fd1498Szrj       /* Fall through.  */
62538fd1498Szrj 
62638fd1498Szrj     case ERROR_MARK:
62738fd1498Szrj       pp_string (pp, M_("<type error>"));
62838fd1498Szrj       break;
62938fd1498Szrj     }
63038fd1498Szrj }
63138fd1498Szrj 
63238fd1498Szrj /* Dump a TYPENAME_TYPE. We need to notice when the context is itself
63338fd1498Szrj    a TYPENAME_TYPE.  */
63438fd1498Szrj 
63538fd1498Szrj static void
dump_typename(cxx_pretty_printer * pp,tree t,int flags)63638fd1498Szrj dump_typename (cxx_pretty_printer *pp, tree t, int flags)
63738fd1498Szrj {
63838fd1498Szrj   tree ctx = TYPE_CONTEXT (t);
63938fd1498Szrj 
64038fd1498Szrj   if (TREE_CODE (ctx) == TYPENAME_TYPE)
64138fd1498Szrj     dump_typename (pp, ctx, flags);
64238fd1498Szrj   else
64338fd1498Szrj     dump_type (pp, ctx, flags & ~TFF_CLASS_KEY_OR_ENUM);
64438fd1498Szrj   pp_cxx_colon_colon (pp);
64538fd1498Szrj   dump_decl (pp, TYPENAME_TYPE_FULLNAME (t), flags);
64638fd1498Szrj }
64738fd1498Szrj 
64838fd1498Szrj /* Return the name of the supplied aggregate, or enumeral type.  */
64938fd1498Szrj 
65038fd1498Szrj const char *
class_key_or_enum_as_string(tree t)65138fd1498Szrj class_key_or_enum_as_string (tree t)
65238fd1498Szrj {
65338fd1498Szrj   if (TREE_CODE (t) == ENUMERAL_TYPE)
65438fd1498Szrj     {
65538fd1498Szrj       if (SCOPED_ENUM_P (t))
65638fd1498Szrj         return "enum class";
65738fd1498Szrj       else
65838fd1498Szrj         return "enum";
65938fd1498Szrj     }
66038fd1498Szrj   else if (TREE_CODE (t) == UNION_TYPE)
66138fd1498Szrj     return "union";
66238fd1498Szrj   else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t))
66338fd1498Szrj     return "class";
66438fd1498Szrj   else
66538fd1498Szrj     return "struct";
66638fd1498Szrj }
66738fd1498Szrj 
66838fd1498Szrj /* Print out a class declaration T under the control of FLAGS,
66938fd1498Szrj    in the form `class foo'.  */
67038fd1498Szrj 
67138fd1498Szrj static void
dump_aggr_type(cxx_pretty_printer * pp,tree t,int flags)67238fd1498Szrj dump_aggr_type (cxx_pretty_printer *pp, tree t, int flags)
67338fd1498Szrj {
67438fd1498Szrj   tree name;
67538fd1498Szrj   const char *variety = class_key_or_enum_as_string (t);
67638fd1498Szrj   int typdef = 0;
67738fd1498Szrj   int tmplate = 0;
67838fd1498Szrj 
67938fd1498Szrj   pp_cxx_cv_qualifier_seq (pp, t);
68038fd1498Szrj 
68138fd1498Szrj   if (flags & TFF_CLASS_KEY_OR_ENUM)
68238fd1498Szrj     pp_cxx_ws_string (pp, variety);
68338fd1498Szrj 
68438fd1498Szrj   name = TYPE_NAME (t);
68538fd1498Szrj 
68638fd1498Szrj   if (name)
68738fd1498Szrj     {
68838fd1498Szrj       typdef = (!DECL_ARTIFICIAL (name)
68938fd1498Szrj 		/* An alias specialization is not considered to be a
69038fd1498Szrj 		   typedef.  */
69138fd1498Szrj 		&& !alias_template_specialization_p (t));
69238fd1498Szrj 
69338fd1498Szrj       if ((typdef
69438fd1498Szrj 	   && ((flags & TFF_CHASE_TYPEDEF)
69538fd1498Szrj 	       || (!flag_pretty_templates && DECL_LANG_SPECIFIC (name)
69638fd1498Szrj 		   && DECL_TEMPLATE_INFO (name))))
69738fd1498Szrj 	  || DECL_SELF_REFERENCE_P (name))
69838fd1498Szrj 	{
69938fd1498Szrj 	  t = TYPE_MAIN_VARIANT (t);
70038fd1498Szrj 	  name = TYPE_NAME (t);
70138fd1498Szrj 	  typdef = 0;
70238fd1498Szrj 	}
70338fd1498Szrj 
70438fd1498Szrj       tmplate = !typdef && TREE_CODE (t) != ENUMERAL_TYPE
70538fd1498Szrj 		&& TYPE_LANG_SPECIFIC (t) && CLASSTYPE_TEMPLATE_INFO (t)
70638fd1498Szrj 		&& (TREE_CODE (CLASSTYPE_TI_TEMPLATE (t)) != TEMPLATE_DECL
70738fd1498Szrj 		    || PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)));
70838fd1498Szrj 
70938fd1498Szrj       if (! (flags & TFF_UNQUALIFIED_NAME))
71038fd1498Szrj 	dump_scope (pp, CP_DECL_CONTEXT (name), flags | TFF_SCOPE);
71138fd1498Szrj       flags &= ~TFF_UNQUALIFIED_NAME;
71238fd1498Szrj       if (tmplate)
71338fd1498Szrj 	{
71438fd1498Szrj 	  /* Because the template names are mangled, we have to locate
71538fd1498Szrj 	     the most general template, and use that name.  */
71638fd1498Szrj 	  tree tpl = TYPE_TI_TEMPLATE (t);
71738fd1498Szrj 
71838fd1498Szrj 	  while (DECL_TEMPLATE_INFO (tpl))
71938fd1498Szrj 	    tpl = DECL_TI_TEMPLATE (tpl);
72038fd1498Szrj 	  name = tpl;
72138fd1498Szrj 	}
72238fd1498Szrj       name = DECL_NAME (name);
72338fd1498Szrj     }
72438fd1498Szrj 
72538fd1498Szrj   if (name == 0 || anon_aggrname_p (name))
72638fd1498Szrj     {
72738fd1498Szrj       if (flags & TFF_CLASS_KEY_OR_ENUM)
72838fd1498Szrj 	pp_string (pp, M_("<unnamed>"));
72938fd1498Szrj       else
73038fd1498Szrj 	pp_printf (pp, M_("<unnamed %s>"), variety);
73138fd1498Szrj     }
73238fd1498Szrj   else if (LAMBDA_TYPE_P (t))
73338fd1498Szrj     {
73438fd1498Szrj       /* A lambda's "type" is essentially its signature.  */
73538fd1498Szrj       pp_string (pp, M_("<lambda"));
73638fd1498Szrj       if (lambda_function (t))
73738fd1498Szrj 	dump_parameters (pp,
73838fd1498Szrj                          FUNCTION_FIRST_USER_PARMTYPE (lambda_function (t)),
73938fd1498Szrj 			 flags);
74038fd1498Szrj       pp_greater (pp);
74138fd1498Szrj     }
74238fd1498Szrj   else
74338fd1498Szrj     pp_cxx_tree_identifier (pp, name);
74438fd1498Szrj   if (tmplate)
74538fd1498Szrj     dump_template_parms (pp, TYPE_TEMPLATE_INFO (t),
74638fd1498Szrj 			 !CLASSTYPE_USE_TEMPLATE (t),
74738fd1498Szrj 			 flags & ~TFF_TEMPLATE_HEADER);
74838fd1498Szrj }
74938fd1498Szrj 
75038fd1498Szrj /* Dump into the obstack the initial part of the output for a given type.
75138fd1498Szrj    This is necessary when dealing with things like functions returning
75238fd1498Szrj    functions.  Examples:
75338fd1498Szrj 
75438fd1498Szrj    return type of `int (* fee ())()': pointer -> function -> int.  Both
75538fd1498Szrj    pointer (and reference and offset) and function (and member) types must
75638fd1498Szrj    deal with prefix and suffix.
75738fd1498Szrj 
75838fd1498Szrj    Arrays must also do this for DECL nodes, like int a[], and for things like
75938fd1498Szrj    int *[]&.  */
76038fd1498Szrj 
76138fd1498Szrj static void
dump_type_prefix(cxx_pretty_printer * pp,tree t,int flags)76238fd1498Szrj dump_type_prefix (cxx_pretty_printer *pp, tree t, int flags)
76338fd1498Szrj {
76438fd1498Szrj   if (TYPE_PTRMEMFUNC_P (t))
76538fd1498Szrj     {
76638fd1498Szrj       t = TYPE_PTRMEMFUNC_FN_TYPE (t);
76738fd1498Szrj       goto offset_type;
76838fd1498Szrj     }
76938fd1498Szrj 
77038fd1498Szrj   switch (TREE_CODE (t))
77138fd1498Szrj     {
77238fd1498Szrj     case POINTER_TYPE:
77338fd1498Szrj     case REFERENCE_TYPE:
77438fd1498Szrj       {
77538fd1498Szrj 	tree sub = TREE_TYPE (t);
77638fd1498Szrj 
77738fd1498Szrj 	dump_type_prefix (pp, sub, flags);
77838fd1498Szrj 	if (TREE_CODE (sub) == ARRAY_TYPE
77938fd1498Szrj 	    || TREE_CODE (sub) == FUNCTION_TYPE)
78038fd1498Szrj 	  {
78138fd1498Szrj 	    pp_cxx_whitespace (pp);
78238fd1498Szrj 	    pp_cxx_left_paren (pp);
78338fd1498Szrj 	    pp_c_attributes_display (pp, TYPE_ATTRIBUTES (sub));
78438fd1498Szrj 	  }
78538fd1498Szrj 	if (TYPE_PTR_P (t))
78638fd1498Szrj 	  pp_star (pp);
78738fd1498Szrj 	else if (TREE_CODE (t) == REFERENCE_TYPE)
78838fd1498Szrj 	{
78938fd1498Szrj 	  if (TYPE_REF_IS_RVALUE (t))
79038fd1498Szrj 	    pp_ampersand_ampersand (pp);
79138fd1498Szrj 	  else
79238fd1498Szrj 	    pp_ampersand (pp);
79338fd1498Szrj 	}
79438fd1498Szrj 	pp->padding = pp_before;
79538fd1498Szrj 	pp_cxx_cv_qualifier_seq (pp, t);
79638fd1498Szrj       }
79738fd1498Szrj       break;
79838fd1498Szrj 
79938fd1498Szrj     case OFFSET_TYPE:
80038fd1498Szrj     offset_type:
80138fd1498Szrj       dump_type_prefix (pp, TREE_TYPE (t), flags);
80238fd1498Szrj       if (TREE_CODE (t) == OFFSET_TYPE)	/* pmfs deal with this in d_t_p */
80338fd1498Szrj 	{
80438fd1498Szrj 	  pp_maybe_space (pp);
80538fd1498Szrj 	  if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
80638fd1498Szrj 	     pp_cxx_left_paren (pp);
80738fd1498Szrj 	  dump_type (pp, TYPE_OFFSET_BASETYPE (t), flags);
80838fd1498Szrj 	  pp_cxx_colon_colon (pp);
80938fd1498Szrj 	}
81038fd1498Szrj       pp_cxx_star (pp);
81138fd1498Szrj       pp_cxx_cv_qualifier_seq (pp, t);
81238fd1498Szrj       pp->padding = pp_before;
81338fd1498Szrj       break;
81438fd1498Szrj 
81538fd1498Szrj       /* This can be reached without a pointer when dealing with
81638fd1498Szrj 	 templates, e.g. std::is_function.  */
81738fd1498Szrj     case FUNCTION_TYPE:
81838fd1498Szrj       dump_type_prefix (pp, TREE_TYPE (t), flags);
81938fd1498Szrj       break;
82038fd1498Szrj 
82138fd1498Szrj     case METHOD_TYPE:
82238fd1498Szrj       dump_type_prefix (pp, TREE_TYPE (t), flags);
82338fd1498Szrj       pp_maybe_space (pp);
82438fd1498Szrj       pp_cxx_left_paren (pp);
82538fd1498Szrj       dump_aggr_type (pp, TYPE_METHOD_BASETYPE (t), flags);
82638fd1498Szrj       pp_cxx_colon_colon (pp);
82738fd1498Szrj       break;
82838fd1498Szrj 
82938fd1498Szrj     case ARRAY_TYPE:
83038fd1498Szrj       dump_type_prefix (pp, TREE_TYPE (t), flags);
83138fd1498Szrj       break;
83238fd1498Szrj 
83338fd1498Szrj     case ENUMERAL_TYPE:
83438fd1498Szrj     case IDENTIFIER_NODE:
83538fd1498Szrj     case INTEGER_TYPE:
83638fd1498Szrj     case BOOLEAN_TYPE:
83738fd1498Szrj     case REAL_TYPE:
83838fd1498Szrj     case RECORD_TYPE:
83938fd1498Szrj     case TEMPLATE_TYPE_PARM:
84038fd1498Szrj     case TEMPLATE_TEMPLATE_PARM:
84138fd1498Szrj     case BOUND_TEMPLATE_TEMPLATE_PARM:
84238fd1498Szrj     case TREE_LIST:
84338fd1498Szrj     case TYPE_DECL:
84438fd1498Szrj     case TREE_VEC:
84538fd1498Szrj     case UNION_TYPE:
84638fd1498Szrj     case LANG_TYPE:
84738fd1498Szrj     case VOID_TYPE:
84838fd1498Szrj     case TYPENAME_TYPE:
84938fd1498Szrj     case COMPLEX_TYPE:
85038fd1498Szrj     case VECTOR_TYPE:
85138fd1498Szrj     case TYPEOF_TYPE:
85238fd1498Szrj     case UNDERLYING_TYPE:
85338fd1498Szrj     case DECLTYPE_TYPE:
85438fd1498Szrj     case TYPE_PACK_EXPANSION:
85538fd1498Szrj     case FIXED_POINT_TYPE:
85638fd1498Szrj     case NULLPTR_TYPE:
85738fd1498Szrj       dump_type (pp, t, flags);
85838fd1498Szrj       pp->padding = pp_before;
85938fd1498Szrj       break;
86038fd1498Szrj 
86138fd1498Szrj     default:
86238fd1498Szrj       pp_unsupported_tree (pp, t);
86338fd1498Szrj       /* fall through.  */
86438fd1498Szrj     case ERROR_MARK:
86538fd1498Szrj       pp_string (pp, M_("<typeprefixerror>"));
86638fd1498Szrj       break;
86738fd1498Szrj     }
86838fd1498Szrj }
86938fd1498Szrj 
87038fd1498Szrj /* Dump the suffix of type T, under control of FLAGS.  This is the part
87138fd1498Szrj    which appears after the identifier (or function parms).  */
87238fd1498Szrj 
87338fd1498Szrj static void
dump_type_suffix(cxx_pretty_printer * pp,tree t,int flags)87438fd1498Szrj dump_type_suffix (cxx_pretty_printer *pp, tree t, int flags)
87538fd1498Szrj {
87638fd1498Szrj   if (TYPE_PTRMEMFUNC_P (t))
87738fd1498Szrj     t = TYPE_PTRMEMFUNC_FN_TYPE (t);
87838fd1498Szrj 
87938fd1498Szrj   switch (TREE_CODE (t))
88038fd1498Szrj     {
88138fd1498Szrj     case POINTER_TYPE:
88238fd1498Szrj     case REFERENCE_TYPE:
88338fd1498Szrj     case OFFSET_TYPE:
88438fd1498Szrj       if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE
88538fd1498Szrj 	  || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
88638fd1498Szrj 	pp_cxx_right_paren (pp);
88738fd1498Szrj       if (TREE_CODE (t) == POINTER_TYPE)
88838fd1498Szrj 	flags |= TFF_POINTER;
88938fd1498Szrj       dump_type_suffix (pp, TREE_TYPE (t), flags);
89038fd1498Szrj       break;
89138fd1498Szrj 
89238fd1498Szrj     case FUNCTION_TYPE:
89338fd1498Szrj     case METHOD_TYPE:
89438fd1498Szrj       {
89538fd1498Szrj 	tree arg;
89638fd1498Szrj 	if (TREE_CODE (t) == METHOD_TYPE)
89738fd1498Szrj 	  /* Can only be reached through a pointer.  */
89838fd1498Szrj 	  pp_cxx_right_paren (pp);
89938fd1498Szrj 	arg = TYPE_ARG_TYPES (t);
90038fd1498Szrj 	if (TREE_CODE (t) == METHOD_TYPE)
90138fd1498Szrj 	  arg = TREE_CHAIN (arg);
90238fd1498Szrj 
90338fd1498Szrj 	/* Function pointers don't have default args.  Not in standard C++,
90438fd1498Szrj 	   anyway; they may in g++, but we'll just pretend otherwise.  */
90538fd1498Szrj 	dump_parameters (pp, arg, flags & ~TFF_FUNCTION_DEFAULT_ARGUMENTS);
90638fd1498Szrj 
90738fd1498Szrj 	pp->padding = pp_before;
90838fd1498Szrj 	pp_cxx_cv_qualifiers (pp, type_memfn_quals (t),
90938fd1498Szrj 			      TREE_CODE (t) == FUNCTION_TYPE
91038fd1498Szrj 			      && (flags & TFF_POINTER));
91138fd1498Szrj 	dump_ref_qualifier (pp, t, flags);
91238fd1498Szrj 	if (tx_safe_fn_type_p (t))
91338fd1498Szrj 	  pp_cxx_ws_string (pp, "transaction_safe");
91438fd1498Szrj 	dump_exception_spec (pp, TYPE_RAISES_EXCEPTIONS (t), flags);
91538fd1498Szrj 	dump_type_suffix (pp, TREE_TYPE (t), flags);
91638fd1498Szrj 	break;
91738fd1498Szrj       }
91838fd1498Szrj 
91938fd1498Szrj     case ARRAY_TYPE:
92038fd1498Szrj       pp_maybe_space (pp);
92138fd1498Szrj       pp_cxx_left_bracket (pp);
92238fd1498Szrj       if (tree dtype = TYPE_DOMAIN (t))
92338fd1498Szrj 	{
92438fd1498Szrj 	  tree max = TYPE_MAX_VALUE (dtype);
92538fd1498Szrj 	  /* Zero-length arrays have an upper bound of SIZE_MAX.  */
92638fd1498Szrj 	  if (integer_all_onesp (max))
92738fd1498Szrj 	    pp_character (pp, '0');
92838fd1498Szrj 	  else if (tree_fits_shwi_p (max))
92938fd1498Szrj 	    pp_wide_integer (pp, tree_to_shwi (max) + 1);
93038fd1498Szrj 	  else
93138fd1498Szrj 	    {
93238fd1498Szrj 	      STRIP_NOPS (max);
93338fd1498Szrj 	      if (TREE_CODE (max) == SAVE_EXPR)
93438fd1498Szrj 		max = TREE_OPERAND (max, 0);
93538fd1498Szrj 	      if (TREE_CODE (max) == MINUS_EXPR
93638fd1498Szrj 		  || TREE_CODE (max) == PLUS_EXPR)
93738fd1498Szrj 		{
93838fd1498Szrj 		  max = TREE_OPERAND (max, 0);
93938fd1498Szrj 		  while (CONVERT_EXPR_P (max))
94038fd1498Szrj 		    max = TREE_OPERAND (max, 0);
94138fd1498Szrj 		}
94238fd1498Szrj 	      else
94338fd1498Szrj 		max = fold_build2_loc (input_location,
94438fd1498Szrj 				       PLUS_EXPR, dtype, max,
94538fd1498Szrj 				       build_int_cst (dtype, 1));
94638fd1498Szrj 	      dump_expr (pp, max, flags & ~TFF_EXPR_IN_PARENS);
94738fd1498Szrj 	    }
94838fd1498Szrj 	}
94938fd1498Szrj       pp_cxx_right_bracket (pp);
95038fd1498Szrj       dump_type_suffix (pp, TREE_TYPE (t), flags);
95138fd1498Szrj       break;
95238fd1498Szrj 
95338fd1498Szrj     case ENUMERAL_TYPE:
95438fd1498Szrj     case IDENTIFIER_NODE:
95538fd1498Szrj     case INTEGER_TYPE:
95638fd1498Szrj     case BOOLEAN_TYPE:
95738fd1498Szrj     case REAL_TYPE:
95838fd1498Szrj     case RECORD_TYPE:
95938fd1498Szrj     case TEMPLATE_TYPE_PARM:
96038fd1498Szrj     case TEMPLATE_TEMPLATE_PARM:
96138fd1498Szrj     case BOUND_TEMPLATE_TEMPLATE_PARM:
96238fd1498Szrj     case TREE_LIST:
96338fd1498Szrj     case TYPE_DECL:
96438fd1498Szrj     case TREE_VEC:
96538fd1498Szrj     case UNION_TYPE:
96638fd1498Szrj     case LANG_TYPE:
96738fd1498Szrj     case VOID_TYPE:
96838fd1498Szrj     case TYPENAME_TYPE:
96938fd1498Szrj     case COMPLEX_TYPE:
97038fd1498Szrj     case VECTOR_TYPE:
97138fd1498Szrj     case TYPEOF_TYPE:
97238fd1498Szrj     case UNDERLYING_TYPE:
97338fd1498Szrj     case DECLTYPE_TYPE:
97438fd1498Szrj     case TYPE_PACK_EXPANSION:
97538fd1498Szrj     case FIXED_POINT_TYPE:
97638fd1498Szrj     case NULLPTR_TYPE:
97738fd1498Szrj       break;
97838fd1498Szrj 
97938fd1498Szrj     default:
98038fd1498Szrj       pp_unsupported_tree (pp, t);
98138fd1498Szrj     case ERROR_MARK:
98238fd1498Szrj       /* Don't mark it here, we should have already done in
98338fd1498Szrj 	 dump_type_prefix.  */
98438fd1498Szrj       break;
98538fd1498Szrj     }
98638fd1498Szrj }
98738fd1498Szrj 
98838fd1498Szrj static void
dump_global_iord(cxx_pretty_printer * pp,tree t)98938fd1498Szrj dump_global_iord (cxx_pretty_printer *pp, tree t)
99038fd1498Szrj {
99138fd1498Szrj   const char *p = NULL;
99238fd1498Szrj 
99338fd1498Szrj   if (DECL_GLOBAL_CTOR_P (t))
99438fd1498Szrj     p = M_("(static initializers for %s)");
99538fd1498Szrj   else if (DECL_GLOBAL_DTOR_P (t))
99638fd1498Szrj     p = M_("(static destructors for %s)");
99738fd1498Szrj   else
99838fd1498Szrj     gcc_unreachable ();
99938fd1498Szrj 
100038fd1498Szrj   pp_printf (pp, p, DECL_SOURCE_FILE (t));
100138fd1498Szrj }
100238fd1498Szrj 
100338fd1498Szrj static void
dump_simple_decl(cxx_pretty_printer * pp,tree t,tree type,int flags)100438fd1498Szrj dump_simple_decl (cxx_pretty_printer *pp, tree t, tree type, int flags)
100538fd1498Szrj {
100638fd1498Szrj   if (flags & TFF_DECL_SPECIFIERS)
100738fd1498Szrj     {
100838fd1498Szrj       if (VAR_P (t) && DECL_DECLARED_CONSTEXPR_P (t))
100938fd1498Szrj         {
101038fd1498Szrj 	  if (DECL_LANG_SPECIFIC (t) && DECL_DECLARED_CONCEPT_P (t))
101138fd1498Szrj 	    pp_cxx_ws_string (pp, "concept");
101238fd1498Szrj 	  else
101338fd1498Szrj 	    pp_cxx_ws_string (pp, "constexpr");
101438fd1498Szrj 	}
101538fd1498Szrj       dump_type_prefix (pp, type, flags & ~TFF_UNQUALIFIED_NAME);
101638fd1498Szrj       pp_maybe_space (pp);
101738fd1498Szrj     }
101838fd1498Szrj   if (! (flags & TFF_UNQUALIFIED_NAME)
101938fd1498Szrj       && TREE_CODE (t) != PARM_DECL
102038fd1498Szrj       && (!DECL_INITIAL (t)
102138fd1498Szrj 	  || TREE_CODE (DECL_INITIAL (t)) != TEMPLATE_PARM_INDEX))
102238fd1498Szrj     dump_scope (pp, CP_DECL_CONTEXT (t), flags);
102338fd1498Szrj   flags &= ~TFF_UNQUALIFIED_NAME;
102438fd1498Szrj   if ((flags & TFF_DECL_SPECIFIERS)
102538fd1498Szrj       && DECL_TEMPLATE_PARM_P (t)
102638fd1498Szrj       && TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (t)))
102738fd1498Szrj     pp_string (pp, "...");
102838fd1498Szrj   if (DECL_NAME (t))
102938fd1498Szrj     {
103038fd1498Szrj       if (TREE_CODE (t) == FIELD_DECL && DECL_NORMAL_CAPTURE_P (t))
103138fd1498Szrj 	{
103238fd1498Szrj 	  pp_less (pp);
103338fd1498Szrj 	  pp_string (pp, IDENTIFIER_POINTER (DECL_NAME (t)) + 2);
103438fd1498Szrj 	  pp_string (pp, " capture>");
103538fd1498Szrj 	}
103638fd1498Szrj       else
103738fd1498Szrj 	dump_decl (pp, DECL_NAME (t), flags);
103838fd1498Szrj     }
103938fd1498Szrj   else if (DECL_DECOMPOSITION_P (t))
104038fd1498Szrj     pp_string (pp, M_("<structured bindings>"));
104138fd1498Szrj   else
104238fd1498Szrj     pp_string (pp, M_("<anonymous>"));
104338fd1498Szrj   if (flags & TFF_DECL_SPECIFIERS)
104438fd1498Szrj     dump_type_suffix (pp, type, flags);
104538fd1498Szrj }
104638fd1498Szrj 
104738fd1498Szrj /* Print an IDENTIFIER_NODE that is the name of a declaration.  */
104838fd1498Szrj 
104938fd1498Szrj static void
dump_decl_name(cxx_pretty_printer * pp,tree t,int flags)105038fd1498Szrj dump_decl_name (cxx_pretty_printer *pp, tree t, int flags)
105138fd1498Szrj {
105238fd1498Szrj   /* These special cases are duplicated here so that other functions
105338fd1498Szrj      can feed identifiers to error and get them demangled properly.  */
105438fd1498Szrj   if (IDENTIFIER_CONV_OP_P (t))
105538fd1498Szrj     {
105638fd1498Szrj       pp_cxx_ws_string (pp, "operator");
105738fd1498Szrj       /* Not exactly IDENTIFIER_TYPE_VALUE.  */
105838fd1498Szrj       dump_type (pp, TREE_TYPE (t), flags);
105938fd1498Szrj       return;
106038fd1498Szrj     }
106138fd1498Szrj   if (dguide_name_p (t))
106238fd1498Szrj     {
106338fd1498Szrj       dump_decl (pp, CLASSTYPE_TI_TEMPLATE (TREE_TYPE (t)),
106438fd1498Szrj 		 TFF_UNQUALIFIED_NAME);
106538fd1498Szrj       return;
106638fd1498Szrj     }
106738fd1498Szrj 
106838fd1498Szrj   const char *str = IDENTIFIER_POINTER (t);
106938fd1498Szrj   if (!strncmp (str, "_ZGR", 3))
107038fd1498Szrj     {
107138fd1498Szrj       pp_cxx_ws_string (pp, "<temporary>");
107238fd1498Szrj       return;
107338fd1498Szrj     }
107438fd1498Szrj 
107538fd1498Szrj   pp_cxx_tree_identifier (pp, t);
107638fd1498Szrj }
107738fd1498Szrj 
107838fd1498Szrj /* Dump a human readable string for the decl T under control of FLAGS.  */
107938fd1498Szrj 
108038fd1498Szrj static void
dump_decl(cxx_pretty_printer * pp,tree t,int flags)108138fd1498Szrj dump_decl (cxx_pretty_printer *pp, tree t, int flags)
108238fd1498Szrj {
108338fd1498Szrj   if (t == NULL_TREE)
108438fd1498Szrj     return;
108538fd1498Szrj 
108638fd1498Szrj   /* If doing Objective-C++, give Objective-C a chance to demangle
108738fd1498Szrj      Objective-C method names.  */
108838fd1498Szrj   if (c_dialect_objc ())
108938fd1498Szrj     {
109038fd1498Szrj       const char *demangled = objc_maybe_printable_name (t, flags);
109138fd1498Szrj       if (demangled)
109238fd1498Szrj 	{
109338fd1498Szrj 	  pp_string (pp, demangled);
109438fd1498Szrj 	  return;
109538fd1498Szrj 	}
109638fd1498Szrj     }
109738fd1498Szrj 
109838fd1498Szrj   switch (TREE_CODE (t))
109938fd1498Szrj     {
110038fd1498Szrj     case TYPE_DECL:
110138fd1498Szrj       /* Don't say 'typedef class A' */
110238fd1498Szrj       if (DECL_ARTIFICIAL (t) && !DECL_SELF_REFERENCE_P (t))
110338fd1498Szrj 	{
110438fd1498Szrj 	  if ((flags & TFF_DECL_SPECIFIERS)
110538fd1498Szrj 	      && TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
110638fd1498Szrj 	    {
110738fd1498Szrj 	      /* Say `class T' not just `T'.  */
110838fd1498Szrj 	      pp_cxx_ws_string (pp, "class");
110938fd1498Szrj 
111038fd1498Szrj 	      /* Emit the `...' for a parameter pack.  */
111138fd1498Szrj 	      if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (t)))
111238fd1498Szrj 		pp_cxx_ws_string (pp, "...");
111338fd1498Szrj 	    }
111438fd1498Szrj 
111538fd1498Szrj 	  dump_type (pp, TREE_TYPE (t), flags);
111638fd1498Szrj 	  break;
111738fd1498Szrj 	}
111838fd1498Szrj       if (TYPE_DECL_ALIAS_P (t)
111938fd1498Szrj 	  && (flags & TFF_DECL_SPECIFIERS
112038fd1498Szrj 	      || flags & TFF_CLASS_KEY_OR_ENUM))
112138fd1498Szrj 	{
112238fd1498Szrj 	  pp_cxx_ws_string (pp, "using");
112338fd1498Szrj 	  dump_decl (pp, DECL_NAME (t), flags);
112438fd1498Szrj 	  pp_cxx_whitespace (pp);
112538fd1498Szrj 	  pp_cxx_ws_string (pp, "=");
112638fd1498Szrj 	  pp_cxx_whitespace (pp);
112738fd1498Szrj 	  dump_type (pp, (DECL_ORIGINAL_TYPE (t)
112838fd1498Szrj 			  ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t)),
112938fd1498Szrj 		     flags);
113038fd1498Szrj 	  break;
113138fd1498Szrj 	}
113238fd1498Szrj       if ((flags & TFF_DECL_SPECIFIERS)
113338fd1498Szrj 	  && !DECL_SELF_REFERENCE_P (t))
113438fd1498Szrj 	pp_cxx_ws_string (pp, "typedef");
113538fd1498Szrj       dump_simple_decl (pp, t, DECL_ORIGINAL_TYPE (t)
113638fd1498Szrj 			? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t),
113738fd1498Szrj 			flags);
113838fd1498Szrj       break;
113938fd1498Szrj 
114038fd1498Szrj     case VAR_DECL:
114138fd1498Szrj       if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t)))
114238fd1498Szrj 	{
114338fd1498Szrj 	  pp_string (pp, M_("vtable for "));
114438fd1498Szrj 	  gcc_assert (TYPE_P (DECL_CONTEXT (t)));
114538fd1498Szrj 	  dump_type (pp, DECL_CONTEXT (t), flags);
114638fd1498Szrj 	  break;
114738fd1498Szrj 	}
114838fd1498Szrj       /* Fall through.  */
114938fd1498Szrj     case FIELD_DECL:
115038fd1498Szrj     case PARM_DECL:
115138fd1498Szrj       dump_simple_decl (pp, t, TREE_TYPE (t), flags);
115238fd1498Szrj 
115338fd1498Szrj       /* Handle variable template specializations.  */
115438fd1498Szrj       if (VAR_P (t)
115538fd1498Szrj 	  && DECL_LANG_SPECIFIC (t)
115638fd1498Szrj 	  && DECL_TEMPLATE_INFO (t)
115738fd1498Szrj 	  && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t)))
115838fd1498Szrj 	{
115938fd1498Szrj 	  pp_cxx_begin_template_argument_list (pp);
116038fd1498Szrj 	  tree args = INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (t));
116138fd1498Szrj 	  dump_template_argument_list (pp, args, flags);
116238fd1498Szrj 	  pp_cxx_end_template_argument_list (pp);
116338fd1498Szrj 	}
116438fd1498Szrj       break;
116538fd1498Szrj 
116638fd1498Szrj     case RESULT_DECL:
116738fd1498Szrj       pp_string (pp, M_("<return value> "));
116838fd1498Szrj       dump_simple_decl (pp, t, TREE_TYPE (t), flags);
116938fd1498Szrj       break;
117038fd1498Szrj 
117138fd1498Szrj     case NAMESPACE_DECL:
117238fd1498Szrj       if (flags & TFF_DECL_SPECIFIERS)
117338fd1498Szrj 	pp->declaration (t);
117438fd1498Szrj       else
117538fd1498Szrj 	{
117638fd1498Szrj 	  if (! (flags & TFF_UNQUALIFIED_NAME))
117738fd1498Szrj 	    dump_scope (pp, CP_DECL_CONTEXT (t), flags);
117838fd1498Szrj 	  flags &= ~TFF_UNQUALIFIED_NAME;
117938fd1498Szrj 	  if (DECL_NAME (t) == NULL_TREE)
118038fd1498Szrj             {
118138fd1498Szrj               if (!(pp->flags & pp_c_flag_gnu_v3))
118238fd1498Szrj                 pp_cxx_ws_string (pp, M_("{anonymous}"));
118338fd1498Szrj               else
118438fd1498Szrj                 pp_cxx_ws_string (pp, M_("(anonymous namespace)"));
118538fd1498Szrj             }
118638fd1498Szrj 	  else
118738fd1498Szrj 	    pp_cxx_tree_identifier (pp, DECL_NAME (t));
118838fd1498Szrj 	}
118938fd1498Szrj       break;
119038fd1498Szrj 
119138fd1498Szrj     case SCOPE_REF:
119238fd1498Szrj       dump_type (pp, TREE_OPERAND (t, 0), flags);
119338fd1498Szrj       pp_cxx_colon_colon (pp);
119438fd1498Szrj       dump_decl (pp, TREE_OPERAND (t, 1), TFF_UNQUALIFIED_NAME);
119538fd1498Szrj       break;
119638fd1498Szrj 
119738fd1498Szrj     case ARRAY_REF:
119838fd1498Szrj       dump_decl (pp, TREE_OPERAND (t, 0), flags);
119938fd1498Szrj       pp_cxx_left_bracket (pp);
120038fd1498Szrj       dump_decl (pp, TREE_OPERAND (t, 1), flags);
120138fd1498Szrj       pp_cxx_right_bracket (pp);
120238fd1498Szrj       break;
120338fd1498Szrj 
120438fd1498Szrj       /* So that we can do dump_decl on an aggr type.  */
120538fd1498Szrj     case RECORD_TYPE:
120638fd1498Szrj     case UNION_TYPE:
120738fd1498Szrj     case ENUMERAL_TYPE:
120838fd1498Szrj       dump_type (pp, t, flags);
120938fd1498Szrj       break;
121038fd1498Szrj 
121138fd1498Szrj     case BIT_NOT_EXPR:
121238fd1498Szrj       /* This is a pseudo destructor call which has not been folded into
121338fd1498Szrj 	 a PSEUDO_DTOR_EXPR yet.  */
121438fd1498Szrj       pp_cxx_complement (pp);
121538fd1498Szrj       dump_type (pp, TREE_OPERAND (t, 0), flags);
121638fd1498Szrj       break;
121738fd1498Szrj 
121838fd1498Szrj     case TYPE_EXPR:
121938fd1498Szrj       gcc_unreachable ();
122038fd1498Szrj       break;
122138fd1498Szrj 
122238fd1498Szrj     case IDENTIFIER_NODE:
122338fd1498Szrj       dump_decl_name (pp, t, flags);
122438fd1498Szrj       break;
122538fd1498Szrj 
122638fd1498Szrj     case OVERLOAD:
122738fd1498Szrj       if (!OVL_SINGLE_P (t))
122838fd1498Szrj 	{
122938fd1498Szrj 	  tree ctx = ovl_scope (t);
123038fd1498Szrj 	  if (ctx != global_namespace)
123138fd1498Szrj 	    {
123238fd1498Szrj 	      if (TYPE_P (ctx))
123338fd1498Szrj 		dump_type (pp, ctx, flags);
123438fd1498Szrj 	      else
123538fd1498Szrj 		dump_decl (pp, ctx, flags);
123638fd1498Szrj 	      pp_cxx_colon_colon (pp);
123738fd1498Szrj 	    }
123838fd1498Szrj 	  dump_decl (pp, OVL_NAME (t), flags);
123938fd1498Szrj 	  break;
124038fd1498Szrj 	}
124138fd1498Szrj 
124238fd1498Szrj       /* If there's only one function, just treat it like an ordinary
124338fd1498Szrj 	 FUNCTION_DECL.  */
124438fd1498Szrj       t = OVL_FIRST (t);
124538fd1498Szrj       /* Fall through.  */
124638fd1498Szrj 
124738fd1498Szrj     case FUNCTION_DECL:
124838fd1498Szrj       if (! DECL_LANG_SPECIFIC (t))
124938fd1498Szrj 	{
125038fd1498Szrj 	  if (DECL_ABSTRACT_ORIGIN (t)
125138fd1498Szrj 	      && DECL_ABSTRACT_ORIGIN (t) != t)
125238fd1498Szrj 	    dump_decl (pp, DECL_ABSTRACT_ORIGIN (t), flags);
125338fd1498Szrj 	  else
125438fd1498Szrj 	    dump_function_name (pp, t, flags);
125538fd1498Szrj 	}
125638fd1498Szrj       else if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t))
125738fd1498Szrj 	dump_global_iord (pp, t);
125838fd1498Szrj       else
125938fd1498Szrj 	dump_function_decl (pp, t, flags);
126038fd1498Szrj       break;
126138fd1498Szrj 
126238fd1498Szrj     case TEMPLATE_DECL:
126338fd1498Szrj       dump_template_decl (pp, t, flags);
126438fd1498Szrj       break;
126538fd1498Szrj 
126638fd1498Szrj     case TEMPLATE_ID_EXPR:
126738fd1498Szrj       {
126838fd1498Szrj 	tree name = TREE_OPERAND (t, 0);
126938fd1498Szrj 	tree args = TREE_OPERAND (t, 1);
127038fd1498Szrj 
127138fd1498Szrj 	if (!identifier_p (name))
127238fd1498Szrj 	  name = OVL_NAME (name);
127338fd1498Szrj 	dump_decl (pp, name, flags);
127438fd1498Szrj 	pp_cxx_begin_template_argument_list (pp);
127538fd1498Szrj 	if (args == error_mark_node)
127638fd1498Szrj 	  pp_string (pp, M_("<template arguments error>"));
127738fd1498Szrj 	else if (args)
127838fd1498Szrj 	  dump_template_argument_list
127938fd1498Szrj 	    (pp, args, flags|TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS);
128038fd1498Szrj       	pp_cxx_end_template_argument_list (pp);
128138fd1498Szrj       }
128238fd1498Szrj       break;
128338fd1498Szrj 
128438fd1498Szrj     case LABEL_DECL:
128538fd1498Szrj       pp_cxx_tree_identifier (pp, DECL_NAME (t));
128638fd1498Szrj       break;
128738fd1498Szrj 
128838fd1498Szrj     case CONST_DECL:
128938fd1498Szrj       if ((TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == ENUMERAL_TYPE)
129038fd1498Szrj 	  || (DECL_INITIAL (t) &&
129138fd1498Szrj 	      TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_PARM_INDEX))
129238fd1498Szrj 	dump_simple_decl (pp, t, TREE_TYPE (t), flags);
129338fd1498Szrj       else if (DECL_NAME (t))
129438fd1498Szrj 	dump_decl (pp, DECL_NAME (t), flags);
129538fd1498Szrj       else if (DECL_INITIAL (t))
129638fd1498Szrj 	dump_expr (pp, DECL_INITIAL (t), flags | TFF_EXPR_IN_PARENS);
129738fd1498Szrj       else
129838fd1498Szrj 	pp_string (pp, M_("<enumerator>"));
129938fd1498Szrj       break;
130038fd1498Szrj 
130138fd1498Szrj     case USING_DECL:
130238fd1498Szrj       {
130338fd1498Szrj 	pp_cxx_ws_string (pp, "using");
130438fd1498Szrj 	tree scope = USING_DECL_SCOPE (t);
130538fd1498Szrj 	bool variadic = false;
130638fd1498Szrj 	if (PACK_EXPANSION_P (scope))
130738fd1498Szrj 	  {
130838fd1498Szrj 	    scope = PACK_EXPANSION_PATTERN (scope);
130938fd1498Szrj 	    variadic = true;
131038fd1498Szrj 	  }
131138fd1498Szrj 	dump_type (pp, scope, flags);
131238fd1498Szrj 	pp_cxx_colon_colon (pp);
131338fd1498Szrj 	dump_decl (pp, DECL_NAME (t), flags);
131438fd1498Szrj 	if (variadic)
131538fd1498Szrj 	  pp_cxx_ws_string (pp, "...");
131638fd1498Szrj       }
131738fd1498Szrj       break;
131838fd1498Szrj 
131938fd1498Szrj     case STATIC_ASSERT:
132038fd1498Szrj       pp->declaration (t);
132138fd1498Szrj       break;
132238fd1498Szrj 
132338fd1498Szrj     case BASELINK:
132438fd1498Szrj       dump_decl (pp, BASELINK_FUNCTIONS (t), flags);
132538fd1498Szrj       break;
132638fd1498Szrj 
132738fd1498Szrj     case NON_DEPENDENT_EXPR:
132838fd1498Szrj       dump_expr (pp, t, flags);
132938fd1498Szrj       break;
133038fd1498Szrj 
133138fd1498Szrj     case TEMPLATE_TYPE_PARM:
133238fd1498Szrj       if (flags & TFF_DECL_SPECIFIERS)
133338fd1498Szrj 	pp->declaration (t);
133438fd1498Szrj       else
133538fd1498Szrj 	pp->type_id (t);
133638fd1498Szrj       break;
133738fd1498Szrj 
133838fd1498Szrj     case UNBOUND_CLASS_TEMPLATE:
133938fd1498Szrj     case TYPE_PACK_EXPANSION:
134038fd1498Szrj     case TREE_BINFO:
134138fd1498Szrj       dump_type (pp, t, flags);
134238fd1498Szrj       break;
134338fd1498Szrj 
134438fd1498Szrj     default:
134538fd1498Szrj       pp_unsupported_tree (pp, t);
134638fd1498Szrj       /* Fall through.  */
134738fd1498Szrj 
134838fd1498Szrj     case ERROR_MARK:
134938fd1498Szrj       pp_string (pp, M_("<declaration error>"));
135038fd1498Szrj       break;
135138fd1498Szrj     }
135238fd1498Szrj }
135338fd1498Szrj 
135438fd1498Szrj /* Dump a template declaration T under control of FLAGS. This means the
135538fd1498Szrj    'template <...> leaders plus the 'class X' or 'void fn(...)' part.  */
135638fd1498Szrj 
135738fd1498Szrj static void
dump_template_decl(cxx_pretty_printer * pp,tree t,int flags)135838fd1498Szrj dump_template_decl (cxx_pretty_printer *pp, tree t, int flags)
135938fd1498Szrj {
136038fd1498Szrj   tree orig_parms = DECL_TEMPLATE_PARMS (t);
136138fd1498Szrj   tree parms;
136238fd1498Szrj   int i;
136338fd1498Szrj 
136438fd1498Szrj   if (flags & TFF_TEMPLATE_HEADER)
136538fd1498Szrj     {
136638fd1498Szrj       for (parms = orig_parms = nreverse (orig_parms);
136738fd1498Szrj 	   parms;
136838fd1498Szrj 	   parms = TREE_CHAIN (parms))
136938fd1498Szrj 	{
137038fd1498Szrj 	  tree inner_parms = INNERMOST_TEMPLATE_PARMS (parms);
137138fd1498Szrj 	  int len = TREE_VEC_LENGTH (inner_parms);
137238fd1498Szrj 
137338fd1498Szrj 	  if (len == 0)
137438fd1498Szrj 	    {
137538fd1498Szrj 	      /* Skip over the dummy template levels of a template template
137638fd1498Szrj 		 parm.  */
137738fd1498Szrj 	      gcc_assert (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TEMPLATE_PARM);
137838fd1498Szrj 	      continue;
137938fd1498Szrj 	    }
138038fd1498Szrj 
138138fd1498Szrj 	  pp_cxx_ws_string (pp, "template");
138238fd1498Szrj 	  pp_cxx_begin_template_argument_list (pp);
138338fd1498Szrj 
138438fd1498Szrj 	  /* If we've shown the template prefix, we'd better show the
138538fd1498Szrj 	     parameters' and decl's type too.  */
138638fd1498Szrj 	    flags |= TFF_DECL_SPECIFIERS;
138738fd1498Szrj 
138838fd1498Szrj 	  for (i = 0; i < len; i++)
138938fd1498Szrj 	    {
139038fd1498Szrj 	      if (i)
139138fd1498Szrj 		pp_separate_with_comma (pp);
139238fd1498Szrj 	      dump_template_parameter (pp, TREE_VEC_ELT (inner_parms, i),
139338fd1498Szrj                                        flags);
139438fd1498Szrj 	    }
139538fd1498Szrj 	  pp_cxx_end_template_argument_list (pp);
139638fd1498Szrj 	  pp_cxx_whitespace (pp);
139738fd1498Szrj 	}
139838fd1498Szrj       nreverse(orig_parms);
139938fd1498Szrj 
140038fd1498Szrj       if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
140138fd1498Szrj 	{
140238fd1498Szrj 	  /* Say `template<arg> class TT' not just `template<arg> TT'.  */
140338fd1498Szrj 	  pp_cxx_ws_string (pp, "class");
140438fd1498Szrj 
140538fd1498Szrj 	  /* If this is a parameter pack, print the ellipsis.  */
140638fd1498Szrj 	  if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (t)))
140738fd1498Szrj 	    pp_cxx_ws_string (pp, "...");
140838fd1498Szrj 	}
140938fd1498Szrj 
141038fd1498Szrj       /* Only print the requirements if we're also printing
141138fd1498Szrj          the template header.  */
141238fd1498Szrj       if (flag_concepts)
141338fd1498Szrj 	if (tree ci = get_constraints (t))
141438fd1498Szrj 	  if (check_constraint_info (ci))
141538fd1498Szrj 	    if (tree reqs = CI_TEMPLATE_REQS (ci))
141638fd1498Szrj 	      {
141738fd1498Szrj 		pp_cxx_requires_clause (pp, reqs);
141838fd1498Szrj 		pp_cxx_whitespace (pp);
141938fd1498Szrj 	      }
142038fd1498Szrj     }
142138fd1498Szrj 
142238fd1498Szrj 
142338fd1498Szrj   if (DECL_CLASS_TEMPLATE_P (t))
142438fd1498Szrj     dump_type (pp, TREE_TYPE (t),
142538fd1498Szrj 	       ((flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
142638fd1498Szrj 		| (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0)));
142738fd1498Szrj   else if (DECL_TEMPLATE_RESULT (t)
142838fd1498Szrj            && (VAR_P (DECL_TEMPLATE_RESULT (t))
142938fd1498Szrj 	       /* Alias template.  */
143038fd1498Szrj 	       || DECL_TYPE_TEMPLATE_P (t)))
143138fd1498Szrj     dump_decl (pp, DECL_TEMPLATE_RESULT (t), flags | TFF_TEMPLATE_NAME);
143238fd1498Szrj   else
143338fd1498Szrj     {
143438fd1498Szrj       gcc_assert (TREE_TYPE (t));
143538fd1498Szrj       switch (NEXT_CODE (t))
143638fd1498Szrj 	{
143738fd1498Szrj 	case METHOD_TYPE:
143838fd1498Szrj 	case FUNCTION_TYPE:
143938fd1498Szrj 	  dump_function_decl (pp, t, flags | TFF_TEMPLATE_NAME);
144038fd1498Szrj 	  break;
144138fd1498Szrj 	default:
144238fd1498Szrj 	  /* This case can occur with some invalid code.  */
144338fd1498Szrj 	  dump_type (pp, TREE_TYPE (t),
144438fd1498Szrj 		     (flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
144538fd1498Szrj 		     | (flags & TFF_DECL_SPECIFIERS
144638fd1498Szrj 			? TFF_CLASS_KEY_OR_ENUM : 0));
144738fd1498Szrj 	}
144838fd1498Szrj     }
144938fd1498Szrj }
145038fd1498Szrj 
145138fd1498Szrj /* find_typenames looks through the type of the function template T
145238fd1498Szrj    and returns a vec containing any typedefs, decltypes or TYPENAME_TYPEs
145338fd1498Szrj    it finds.  */
145438fd1498Szrj 
145538fd1498Szrj struct find_typenames_t
145638fd1498Szrj {
145738fd1498Szrj   hash_set<tree> *p_set;
145838fd1498Szrj   vec<tree, va_gc> *typenames;
145938fd1498Szrj };
146038fd1498Szrj 
146138fd1498Szrj static tree
find_typenames_r(tree * tp,int * walk_subtrees,void * data)146238fd1498Szrj find_typenames_r (tree *tp, int *walk_subtrees, void *data)
146338fd1498Szrj {
146438fd1498Szrj   struct find_typenames_t *d = (struct find_typenames_t *)data;
146538fd1498Szrj   tree mv = NULL_TREE;
146638fd1498Szrj 
146738fd1498Szrj   if (TYPE_P (*tp) && is_typedef_decl (TYPE_NAME (*tp)))
146838fd1498Szrj     /* Add the type of the typedef without any additional cv-quals.  */
146938fd1498Szrj     mv = TREE_TYPE (TYPE_NAME (*tp));
147038fd1498Szrj   else if (TREE_CODE (*tp) == TYPENAME_TYPE
147138fd1498Szrj 	   || TREE_CODE (*tp) == DECLTYPE_TYPE)
147238fd1498Szrj     /* Add the typename without any cv-qualifiers.  */
147338fd1498Szrj     mv = TYPE_MAIN_VARIANT (*tp);
147438fd1498Szrj 
147538fd1498Szrj   if (PACK_EXPANSION_P (*tp))
147638fd1498Szrj     {
147738fd1498Szrj       /* Don't mess with parameter packs since we don't remember
147838fd1498Szrj 	 the pack expansion context for a particular typename.  */
147938fd1498Szrj       *walk_subtrees = false;
148038fd1498Szrj       return NULL_TREE;
148138fd1498Szrj     }
148238fd1498Szrj 
148338fd1498Szrj   if (mv && (mv == *tp || !d->p_set->add (mv)))
148438fd1498Szrj     vec_safe_push (d->typenames, mv);
148538fd1498Szrj 
148638fd1498Szrj   /* Search into class template arguments, which cp_walk_subtrees
148738fd1498Szrj      doesn't do.  */
148838fd1498Szrj   if (CLASS_TYPE_P (*tp) && CLASSTYPE_TEMPLATE_INFO (*tp))
148938fd1498Szrj     cp_walk_tree (&CLASSTYPE_TI_ARGS (*tp), find_typenames_r,
149038fd1498Szrj 		  data, d->p_set);
149138fd1498Szrj 
149238fd1498Szrj   return NULL_TREE;
149338fd1498Szrj }
149438fd1498Szrj 
149538fd1498Szrj static vec<tree, va_gc> *
find_typenames(tree t)149638fd1498Szrj find_typenames (tree t)
149738fd1498Szrj {
149838fd1498Szrj   struct find_typenames_t ft;
149938fd1498Szrj   ft.p_set = new hash_set<tree>;
150038fd1498Szrj   ft.typenames = NULL;
150138fd1498Szrj   cp_walk_tree (&TREE_TYPE (DECL_TEMPLATE_RESULT (t)),
150238fd1498Szrj 		find_typenames_r, &ft, ft.p_set);
150338fd1498Szrj   delete ft.p_set;
150438fd1498Szrj   return ft.typenames;
150538fd1498Szrj }
150638fd1498Szrj 
150738fd1498Szrj /* Output the "[with ...]" clause for a template instantiation T iff
150838fd1498Szrj    TEMPLATE_PARMS, TEMPLATE_ARGS and FLAGS are suitable.  T may be NULL if
150938fd1498Szrj    formatting a deduction/substitution diagnostic rather than an
151038fd1498Szrj    instantiation.  */
151138fd1498Szrj 
151238fd1498Szrj static void
dump_substitution(cxx_pretty_printer * pp,tree t,tree template_parms,tree template_args,int flags)151338fd1498Szrj dump_substitution (cxx_pretty_printer *pp,
151438fd1498Szrj                    tree t, tree template_parms, tree template_args,
151538fd1498Szrj                    int flags)
151638fd1498Szrj {
151738fd1498Szrj   if (template_parms != NULL_TREE && template_args != NULL_TREE
151838fd1498Szrj       && !(flags & TFF_NO_TEMPLATE_BINDINGS))
151938fd1498Szrj     {
152038fd1498Szrj       vec<tree, va_gc> *typenames = t ? find_typenames (t) : NULL;
152138fd1498Szrj       pp_cxx_whitespace (pp);
152238fd1498Szrj       pp_cxx_left_bracket (pp);
152338fd1498Szrj       pp->translate_string ("with");
152438fd1498Szrj       pp_cxx_whitespace (pp);
152538fd1498Szrj       dump_template_bindings (pp, template_parms, template_args, typenames);
152638fd1498Szrj       pp_cxx_right_bracket (pp);
152738fd1498Szrj     }
152838fd1498Szrj }
152938fd1498Szrj 
153038fd1498Szrj /* Dump the lambda function FN including its 'mutable' qualifier and any
153138fd1498Szrj    template bindings.  */
153238fd1498Szrj 
153338fd1498Szrj static void
dump_lambda_function(cxx_pretty_printer * pp,tree fn,tree template_parms,tree template_args,int flags)153438fd1498Szrj dump_lambda_function (cxx_pretty_printer *pp,
153538fd1498Szrj 		      tree fn, tree template_parms, tree template_args,
153638fd1498Szrj 		      int flags)
153738fd1498Szrj {
153838fd1498Szrj   /* A lambda's signature is essentially its "type".  */
153938fd1498Szrj   dump_type (pp, DECL_CONTEXT (fn), flags);
154038fd1498Szrj   if (!(TYPE_QUALS (class_of_this_parm (TREE_TYPE (fn))) & TYPE_QUAL_CONST))
154138fd1498Szrj     {
154238fd1498Szrj       pp->padding = pp_before;
154338fd1498Szrj       pp_c_ws_string (pp, "mutable");
154438fd1498Szrj     }
154538fd1498Szrj   dump_substitution (pp, fn, template_parms, template_args, flags);
154638fd1498Szrj }
154738fd1498Szrj 
154838fd1498Szrj /* Pretty print a function decl. There are several ways we want to print a
154938fd1498Szrj    function declaration. The TFF_ bits in FLAGS tells us how to behave.
155038fd1498Szrj    As error can only apply the '#' flag once to give 0 and 1 for V, there
155138fd1498Szrj    is %D which doesn't print the throw specs, and %F which does.  */
155238fd1498Szrj 
155338fd1498Szrj static void
dump_function_decl(cxx_pretty_printer * pp,tree t,int flags)155438fd1498Szrj dump_function_decl (cxx_pretty_printer *pp, tree t, int flags)
155538fd1498Szrj {
155638fd1498Szrj   tree fntype;
155738fd1498Szrj   tree parmtypes;
155838fd1498Szrj   tree cname = NULL_TREE;
155938fd1498Szrj   tree template_args = NULL_TREE;
156038fd1498Szrj   tree template_parms = NULL_TREE;
156138fd1498Szrj   int show_return = flags & TFF_RETURN_TYPE || flags & TFF_DECL_SPECIFIERS;
156238fd1498Szrj   int do_outer_scope = ! (flags & TFF_UNQUALIFIED_NAME);
156338fd1498Szrj   tree exceptions;
156438fd1498Szrj   bool constexpr_p;
156538fd1498Szrj   tree ret = NULL_TREE;
156638fd1498Szrj 
156738fd1498Szrj   flags &= ~(TFF_UNQUALIFIED_NAME | TFF_TEMPLATE_NAME);
156838fd1498Szrj   if (TREE_CODE (t) == TEMPLATE_DECL)
156938fd1498Szrj     t = DECL_TEMPLATE_RESULT (t);
157038fd1498Szrj 
157138fd1498Szrj   /* Save the exceptions, in case t is a specialization and we are
157238fd1498Szrj      emitting an error about incompatible specifications.  */
157338fd1498Szrj   exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (t));
157438fd1498Szrj 
157538fd1498Szrj   /* Likewise for the constexpr specifier, in case t is a specialization.  */
157638fd1498Szrj   constexpr_p = DECL_DECLARED_CONSTEXPR_P (t);
157738fd1498Szrj 
157838fd1498Szrj   /* Pretty print template instantiations only.  */
157938fd1498Szrj   if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t)
158038fd1498Szrj       && !(flags & TFF_NO_TEMPLATE_BINDINGS)
158138fd1498Szrj       && flag_pretty_templates)
158238fd1498Szrj     {
158338fd1498Szrj       tree tmpl;
158438fd1498Szrj 
158538fd1498Szrj       template_args = DECL_TI_ARGS (t);
158638fd1498Szrj       tmpl = most_general_template (t);
158738fd1498Szrj       if (tmpl && TREE_CODE (tmpl) == TEMPLATE_DECL)
158838fd1498Szrj 	{
158938fd1498Szrj 	  template_parms = DECL_TEMPLATE_PARMS (tmpl);
159038fd1498Szrj 	  t = tmpl;
159138fd1498Szrj 	}
159238fd1498Szrj     }
159338fd1498Szrj 
159438fd1498Szrj   if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
159538fd1498Szrj     return dump_lambda_function (pp, t, template_parms, template_args, flags);
159638fd1498Szrj 
159738fd1498Szrj   fntype = TREE_TYPE (t);
159838fd1498Szrj   parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);
159938fd1498Szrj 
160038fd1498Szrj   if (DECL_CLASS_SCOPE_P (t))
160138fd1498Szrj     cname = DECL_CONTEXT (t);
160238fd1498Szrj   /* This is for partially instantiated template methods.  */
160338fd1498Szrj   else if (TREE_CODE (fntype) == METHOD_TYPE)
160438fd1498Szrj     cname = TREE_TYPE (TREE_VALUE (parmtypes));
160538fd1498Szrj 
160638fd1498Szrj   if (flags & TFF_DECL_SPECIFIERS)
160738fd1498Szrj     {
160838fd1498Szrj       if (DECL_STATIC_FUNCTION_P (t))
160938fd1498Szrj 	pp_cxx_ws_string (pp, "static");
161038fd1498Szrj       else if (DECL_VIRTUAL_P (t))
161138fd1498Szrj 	pp_cxx_ws_string (pp, "virtual");
161238fd1498Szrj 
161338fd1498Szrj       if (constexpr_p)
161438fd1498Szrj         {
161538fd1498Szrj           if (DECL_DECLARED_CONCEPT_P (t))
161638fd1498Szrj             pp_cxx_ws_string (pp, "concept");
161738fd1498Szrj           else
161838fd1498Szrj 	    pp_cxx_ws_string (pp, "constexpr");
161938fd1498Szrj 	}
162038fd1498Szrj     }
162138fd1498Szrj 
162238fd1498Szrj   /* Print the return type?  */
162338fd1498Szrj   if (show_return)
162438fd1498Szrj     show_return = (!DECL_CONV_FN_P (t)  && !DECL_CONSTRUCTOR_P (t)
162538fd1498Szrj 		   && !DECL_DESTRUCTOR_P (t) && !deduction_guide_p (t));
162638fd1498Szrj   if (show_return)
162738fd1498Szrj     {
162838fd1498Szrj       ret = fndecl_declared_return_type (t);
162938fd1498Szrj       dump_type_prefix (pp, ret, flags);
163038fd1498Szrj     }
163138fd1498Szrj 
163238fd1498Szrj   /* Print the function name.  */
163338fd1498Szrj   if (!do_outer_scope)
163438fd1498Szrj     /* Nothing.  */;
163538fd1498Szrj   else if (cname)
163638fd1498Szrj     {
163738fd1498Szrj       dump_type (pp, cname, flags);
163838fd1498Szrj       pp_cxx_colon_colon (pp);
163938fd1498Szrj     }
164038fd1498Szrj   else
164138fd1498Szrj     dump_scope (pp, CP_DECL_CONTEXT (t), flags);
164238fd1498Szrj 
164338fd1498Szrj   dump_function_name (pp, t, flags);
164438fd1498Szrj 
164538fd1498Szrj   if (!(flags & TFF_NO_FUNCTION_ARGUMENTS))
164638fd1498Szrj     {
164738fd1498Szrj       dump_parameters (pp, parmtypes, flags);
164838fd1498Szrj 
164938fd1498Szrj       if (TREE_CODE (fntype) == METHOD_TYPE)
165038fd1498Szrj 	{
165138fd1498Szrj 	  pp->padding = pp_before;
165238fd1498Szrj 	  pp_cxx_cv_qualifier_seq (pp, class_of_this_parm (fntype));
165338fd1498Szrj 	  dump_ref_qualifier (pp, fntype, flags);
165438fd1498Szrj 	}
165538fd1498Szrj 
165638fd1498Szrj       if (tx_safe_fn_type_p (fntype))
165738fd1498Szrj 	{
165838fd1498Szrj 	  pp->padding = pp_before;
165938fd1498Szrj 	  pp_cxx_ws_string (pp, "transaction_safe");
166038fd1498Szrj 	}
166138fd1498Szrj 
166238fd1498Szrj       if (flags & TFF_EXCEPTION_SPECIFICATION)
166338fd1498Szrj 	{
166438fd1498Szrj 	  pp->padding = pp_before;
166538fd1498Szrj 	  dump_exception_spec (pp, exceptions, flags);
166638fd1498Szrj 	}
166738fd1498Szrj 
166838fd1498Szrj       if (show_return)
166938fd1498Szrj 	dump_type_suffix (pp, ret, flags);
167038fd1498Szrj       else if (deduction_guide_p (t))
167138fd1498Szrj 	{
167238fd1498Szrj 	  pp_cxx_ws_string (pp, "->");
167338fd1498Szrj 	  dump_type (pp, TREE_TYPE (TREE_TYPE (t)), flags);
167438fd1498Szrj 	}
167538fd1498Szrj 
167638fd1498Szrj       if (flag_concepts)
167738fd1498Szrj         if (tree ci = get_constraints (t))
167838fd1498Szrj           if (tree reqs = CI_DECLARATOR_REQS (ci))
167938fd1498Szrj             pp_cxx_requires_clause (pp, reqs);
168038fd1498Szrj 
168138fd1498Szrj       dump_substitution (pp, t, template_parms, template_args, flags);
168238fd1498Szrj 
168338fd1498Szrj       if (tree base = DECL_INHERITED_CTOR_BASE (t))
168438fd1498Szrj 	{
168538fd1498Szrj 	  pp_cxx_ws_string (pp, "[inherited from");
168638fd1498Szrj 	  dump_type (pp, base, TFF_PLAIN_IDENTIFIER);
168738fd1498Szrj 	  pp_character (pp, ']');
168838fd1498Szrj 	}
168938fd1498Szrj     }
169038fd1498Szrj   else if (template_args)
169138fd1498Szrj     {
169238fd1498Szrj       bool need_comma = false;
169338fd1498Szrj       int i;
169438fd1498Szrj       pp_cxx_begin_template_argument_list (pp);
169538fd1498Szrj       template_args = INNERMOST_TEMPLATE_ARGS (template_args);
169638fd1498Szrj       for (i = 0; i < TREE_VEC_LENGTH (template_args); ++i)
169738fd1498Szrj 	{
169838fd1498Szrj 	  tree arg = TREE_VEC_ELT (template_args, i);
169938fd1498Szrj 	  if (need_comma)
170038fd1498Szrj 	    pp_separate_with_comma (pp);
170138fd1498Szrj 	  if (ARGUMENT_PACK_P (arg))
170238fd1498Szrj 	    pp_cxx_left_brace (pp);
170338fd1498Szrj 	  dump_template_argument (pp, arg, TFF_PLAIN_IDENTIFIER);
170438fd1498Szrj 	  if (ARGUMENT_PACK_P (arg))
170538fd1498Szrj 	    pp_cxx_right_brace (pp);
170638fd1498Szrj 	  need_comma = true;
170738fd1498Szrj 	}
170838fd1498Szrj       pp_cxx_end_template_argument_list (pp);
170938fd1498Szrj     }
171038fd1498Szrj }
171138fd1498Szrj 
171238fd1498Szrj /* Print a parameter list. If this is for a member function, the
171338fd1498Szrj    member object ptr (and any other hidden args) should have
171438fd1498Szrj    already been removed.  */
171538fd1498Szrj 
171638fd1498Szrj static void
dump_parameters(cxx_pretty_printer * pp,tree parmtypes,int flags)171738fd1498Szrj dump_parameters (cxx_pretty_printer *pp, tree parmtypes, int flags)
171838fd1498Szrj {
171938fd1498Szrj   int first = 1;
172038fd1498Szrj   flags &= ~TFF_SCOPE;
172138fd1498Szrj   pp_cxx_left_paren (pp);
172238fd1498Szrj 
172338fd1498Szrj   for (first = 1; parmtypes != void_list_node;
172438fd1498Szrj        parmtypes = TREE_CHAIN (parmtypes))
172538fd1498Szrj     {
172638fd1498Szrj       if (!first)
172738fd1498Szrj 	pp_separate_with_comma (pp);
172838fd1498Szrj       first = 0;
172938fd1498Szrj       if (!parmtypes)
173038fd1498Szrj 	{
173138fd1498Szrj 	  pp_cxx_ws_string (pp, "...");
173238fd1498Szrj 	  break;
173338fd1498Szrj 	}
173438fd1498Szrj 
173538fd1498Szrj       dump_type (pp, TREE_VALUE (parmtypes), flags);
173638fd1498Szrj 
173738fd1498Szrj       if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && TREE_PURPOSE (parmtypes))
173838fd1498Szrj 	{
173938fd1498Szrj 	  pp_cxx_whitespace (pp);
174038fd1498Szrj 	  pp_equal (pp);
174138fd1498Szrj 	  pp_cxx_whitespace (pp);
174238fd1498Szrj 	  dump_expr (pp, TREE_PURPOSE (parmtypes), flags | TFF_EXPR_IN_PARENS);
174338fd1498Szrj 	}
174438fd1498Szrj     }
174538fd1498Szrj 
174638fd1498Szrj   pp_cxx_right_paren (pp);
174738fd1498Szrj }
174838fd1498Szrj 
174938fd1498Szrj /* Print ref-qualifier of a FUNCTION_TYPE or METHOD_TYPE. FLAGS are ignored. */
175038fd1498Szrj 
175138fd1498Szrj static void
dump_ref_qualifier(cxx_pretty_printer * pp,tree t,int flags ATTRIBUTE_UNUSED)175238fd1498Szrj dump_ref_qualifier (cxx_pretty_printer *pp, tree t, int flags ATTRIBUTE_UNUSED)
175338fd1498Szrj {
175438fd1498Szrj   if (FUNCTION_REF_QUALIFIED (t))
175538fd1498Szrj     {
175638fd1498Szrj       pp->padding = pp_before;
175738fd1498Szrj       if (FUNCTION_RVALUE_QUALIFIED (t))
175838fd1498Szrj         pp_cxx_ws_string (pp, "&&");
175938fd1498Szrj       else
176038fd1498Szrj         pp_cxx_ws_string (pp, "&");
176138fd1498Szrj     }
176238fd1498Szrj }
176338fd1498Szrj 
176438fd1498Szrj /* Print an exception specification. T is the exception specification.  */
176538fd1498Szrj 
176638fd1498Szrj static void
dump_exception_spec(cxx_pretty_printer * pp,tree t,int flags)176738fd1498Szrj dump_exception_spec (cxx_pretty_printer *pp, tree t, int flags)
176838fd1498Szrj {
176938fd1498Szrj   if (t && TREE_PURPOSE (t))
177038fd1498Szrj     {
177138fd1498Szrj       pp_cxx_ws_string (pp, "noexcept");
177238fd1498Szrj       if (!integer_onep (TREE_PURPOSE (t)))
177338fd1498Szrj 	{
177438fd1498Szrj 	  pp_cxx_whitespace (pp);
177538fd1498Szrj 	  pp_cxx_left_paren (pp);
177638fd1498Szrj 	  if (DEFERRED_NOEXCEPT_SPEC_P (t))
177738fd1498Szrj 	    pp_cxx_ws_string (pp, "<uninstantiated>");
177838fd1498Szrj 	  else
177938fd1498Szrj 	    dump_expr (pp, TREE_PURPOSE (t), flags);
178038fd1498Szrj 	  pp_cxx_right_paren (pp);
178138fd1498Szrj 	}
178238fd1498Szrj     }
178338fd1498Szrj   else if (t)
178438fd1498Szrj     {
178538fd1498Szrj       pp_cxx_ws_string (pp, "throw");
178638fd1498Szrj       pp_cxx_whitespace (pp);
178738fd1498Szrj       pp_cxx_left_paren (pp);
178838fd1498Szrj       if (TREE_VALUE (t) != NULL_TREE)
178938fd1498Szrj 	while (1)
179038fd1498Szrj 	  {
179138fd1498Szrj 	    dump_type (pp, TREE_VALUE (t), flags);
179238fd1498Szrj 	    t = TREE_CHAIN (t);
179338fd1498Szrj 	    if (!t)
179438fd1498Szrj 	      break;
179538fd1498Szrj 	    pp_separate_with_comma (pp);
179638fd1498Szrj 	  }
179738fd1498Szrj       pp_cxx_right_paren (pp);
179838fd1498Szrj     }
179938fd1498Szrj }
180038fd1498Szrj 
180138fd1498Szrj /* Handle the function name for a FUNCTION_DECL node, grokking operators
180238fd1498Szrj    and destructors properly.  */
180338fd1498Szrj 
180438fd1498Szrj static void
dump_function_name(cxx_pretty_printer * pp,tree t,int flags)180538fd1498Szrj dump_function_name (cxx_pretty_printer *pp, tree t, int flags)
180638fd1498Szrj {
180738fd1498Szrj   tree name = DECL_NAME (t);
180838fd1498Szrj 
180938fd1498Szrj   /* We can get here with a decl that was synthesized by language-
181038fd1498Szrj      independent machinery (e.g. coverage.c) in which case it won't
181138fd1498Szrj      have a lang_specific structure attached and DECL_CONSTRUCTOR_P
181238fd1498Szrj      will crash.  In this case it is safe just to print out the
181338fd1498Szrj      literal name.  */
181438fd1498Szrj   if (!DECL_LANG_SPECIFIC (t))
181538fd1498Szrj     {
181638fd1498Szrj       pp_cxx_tree_identifier (pp, name);
181738fd1498Szrj       return;
181838fd1498Szrj     }
181938fd1498Szrj 
182038fd1498Szrj   if (TREE_CODE (t) == TEMPLATE_DECL)
182138fd1498Szrj     t = DECL_TEMPLATE_RESULT (t);
182238fd1498Szrj 
182338fd1498Szrj   /* Don't let the user see __comp_ctor et al.  */
182438fd1498Szrj   if (DECL_CONSTRUCTOR_P (t)
182538fd1498Szrj       || DECL_DESTRUCTOR_P (t))
182638fd1498Szrj     {
182738fd1498Szrj       if (LAMBDA_TYPE_P (DECL_CONTEXT (t)))
182838fd1498Szrj 	name = get_identifier ("<lambda>");
182938fd1498Szrj       else if (TYPE_UNNAMED_P (DECL_CONTEXT (t)))
183038fd1498Szrj 	name = get_identifier ("<constructor>");
183138fd1498Szrj       else
183238fd1498Szrj 	name = constructor_name (DECL_CONTEXT (t));
183338fd1498Szrj     }
183438fd1498Szrj 
183538fd1498Szrj   if (DECL_DESTRUCTOR_P (t))
183638fd1498Szrj     {
183738fd1498Szrj       pp_cxx_complement (pp);
183838fd1498Szrj       dump_decl (pp, name, TFF_PLAIN_IDENTIFIER);
183938fd1498Szrj     }
184038fd1498Szrj   else if (DECL_CONV_FN_P (t))
184138fd1498Szrj     {
184238fd1498Szrj       /* This cannot use the hack that the operator's return
184338fd1498Szrj 	 type is stashed off of its name because it may be
184438fd1498Szrj 	 used for error reporting.  In the case of conflicting
184538fd1498Szrj 	 declarations, both will have the same name, yet
184638fd1498Szrj 	 the types will be different, hence the TREE_TYPE field
184738fd1498Szrj 	 of the first name will be clobbered by the second.  */
184838fd1498Szrj       pp_cxx_ws_string (pp, "operator");
184938fd1498Szrj       dump_type (pp, TREE_TYPE (TREE_TYPE (t)), flags);
185038fd1498Szrj     }
185138fd1498Szrj   else
185238fd1498Szrj     dump_decl (pp, name, flags);
185338fd1498Szrj 
185438fd1498Szrj   if (DECL_TEMPLATE_INFO (t)
185538fd1498Szrj       && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t)
185638fd1498Szrj       && (TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL
185738fd1498Szrj 	  || PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t))))
185838fd1498Szrj     dump_template_parms (pp, DECL_TEMPLATE_INFO (t), !DECL_USE_TEMPLATE (t),
185938fd1498Szrj                          flags);
186038fd1498Szrj }
186138fd1498Szrj 
186238fd1498Szrj /* Dump the template parameters from the template info INFO under control of
186338fd1498Szrj    FLAGS. PRIMARY indicates whether this is a primary template decl, or
186438fd1498Szrj    specialization (partial or complete). For partial specializations we show
186538fd1498Szrj    the specialized parameter values. For a primary template we show no
186638fd1498Szrj    decoration.  */
186738fd1498Szrj 
186838fd1498Szrj static void
dump_template_parms(cxx_pretty_printer * pp,tree info,int primary,int flags)186938fd1498Szrj dump_template_parms (cxx_pretty_printer *pp, tree info,
187038fd1498Szrj                      int primary, int flags)
187138fd1498Szrj {
187238fd1498Szrj   tree args = info ? TI_ARGS (info) : NULL_TREE;
187338fd1498Szrj 
187438fd1498Szrj   if (primary && flags & TFF_TEMPLATE_NAME)
187538fd1498Szrj     return;
187638fd1498Szrj   flags &= ~(TFF_CLASS_KEY_OR_ENUM | TFF_TEMPLATE_NAME);
187738fd1498Szrj   pp_cxx_begin_template_argument_list (pp);
187838fd1498Szrj 
187938fd1498Szrj   /* Be careful only to print things when we have them, so as not
188038fd1498Szrj      to crash producing error messages.  */
188138fd1498Szrj   if (args && !primary)
188238fd1498Szrj     {
188338fd1498Szrj       int len, ix;
188438fd1498Szrj       len = get_non_default_template_args_count (args, flags);
188538fd1498Szrj 
188638fd1498Szrj       args = INNERMOST_TEMPLATE_ARGS (args);
188738fd1498Szrj       for (ix = 0; ix != len; ix++)
188838fd1498Szrj 	{
188938fd1498Szrj 	  tree arg = TREE_VEC_ELT (args, ix);
189038fd1498Szrj 
189138fd1498Szrj           /* Only print a comma if we know there is an argument coming. In
189238fd1498Szrj              the case of an empty template argument pack, no actual
189338fd1498Szrj              argument will be printed.  */
189438fd1498Szrj           if (ix
189538fd1498Szrj               && (!ARGUMENT_PACK_P (arg)
189638fd1498Szrj                   || TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg)) > 0))
189738fd1498Szrj             pp_separate_with_comma (pp);
189838fd1498Szrj 
189938fd1498Szrj           if (!arg)
190038fd1498Szrj             pp_string (pp, M_("<template parameter error>"));
190138fd1498Szrj           else
190238fd1498Szrj             dump_template_argument (pp, arg, flags);
190338fd1498Szrj         }
190438fd1498Szrj     }
190538fd1498Szrj   else if (primary)
190638fd1498Szrj     {
190738fd1498Szrj       tree tpl = TI_TEMPLATE (info);
190838fd1498Szrj       tree parms = DECL_TEMPLATE_PARMS (tpl);
190938fd1498Szrj       int len, ix;
191038fd1498Szrj 
191138fd1498Szrj       parms = TREE_CODE (parms) == TREE_LIST ? TREE_VALUE (parms) : NULL_TREE;
191238fd1498Szrj       len = parms ? TREE_VEC_LENGTH (parms) : 0;
191338fd1498Szrj 
191438fd1498Szrj       for (ix = 0; ix != len; ix++)
191538fd1498Szrj 	{
191638fd1498Szrj 	  tree parm;
191738fd1498Szrj 
191838fd1498Szrj           if (TREE_VEC_ELT (parms, ix) == error_mark_node)
191938fd1498Szrj             {
192038fd1498Szrj               pp_string (pp, M_("<template parameter error>"));
192138fd1498Szrj               continue;
192238fd1498Szrj             }
192338fd1498Szrj 
192438fd1498Szrj           parm = TREE_VALUE (TREE_VEC_ELT (parms, ix));
192538fd1498Szrj 
192638fd1498Szrj 	  if (ix)
192738fd1498Szrj 	    pp_separate_with_comma (pp);
192838fd1498Szrj 
192938fd1498Szrj 	  dump_decl (pp, parm, flags & ~TFF_DECL_SPECIFIERS);
193038fd1498Szrj 	}
193138fd1498Szrj     }
193238fd1498Szrj   pp_cxx_end_template_argument_list (pp);
193338fd1498Szrj }
193438fd1498Szrj 
193538fd1498Szrj /* Print out the arguments of CALL_EXPR T as a parenthesized list using
193638fd1498Szrj    flags FLAGS.  Skip over the first argument if SKIPFIRST is true.  */
193738fd1498Szrj 
193838fd1498Szrj static void
dump_call_expr_args(cxx_pretty_printer * pp,tree t,int flags,bool skipfirst)193938fd1498Szrj dump_call_expr_args (cxx_pretty_printer *pp, tree t, int flags, bool skipfirst)
194038fd1498Szrj {
194138fd1498Szrj   tree arg;
194238fd1498Szrj   call_expr_arg_iterator iter;
194338fd1498Szrj 
194438fd1498Szrj   pp_cxx_left_paren (pp);
194538fd1498Szrj   FOR_EACH_CALL_EXPR_ARG (arg, iter, t)
194638fd1498Szrj     {
194738fd1498Szrj       if (skipfirst)
194838fd1498Szrj 	skipfirst = false;
194938fd1498Szrj       else
195038fd1498Szrj 	{
195138fd1498Szrj 	  dump_expr (pp, arg, flags | TFF_EXPR_IN_PARENS);
195238fd1498Szrj 	  if (more_call_expr_args_p (&iter))
195338fd1498Szrj 	    pp_separate_with_comma (pp);
195438fd1498Szrj 	}
195538fd1498Szrj     }
195638fd1498Szrj   pp_cxx_right_paren (pp);
195738fd1498Szrj }
195838fd1498Szrj 
195938fd1498Szrj /* Print out the arguments of AGGR_INIT_EXPR T as a parenthesized list
196038fd1498Szrj    using flags FLAGS.  Skip over the first argument if SKIPFIRST is
196138fd1498Szrj    true.  */
196238fd1498Szrj 
196338fd1498Szrj static void
dump_aggr_init_expr_args(cxx_pretty_printer * pp,tree t,int flags,bool skipfirst)196438fd1498Szrj dump_aggr_init_expr_args (cxx_pretty_printer *pp, tree t, int flags,
196538fd1498Szrj                           bool skipfirst)
196638fd1498Szrj {
196738fd1498Szrj   tree arg;
196838fd1498Szrj   aggr_init_expr_arg_iterator iter;
196938fd1498Szrj 
197038fd1498Szrj   pp_cxx_left_paren (pp);
197138fd1498Szrj   FOR_EACH_AGGR_INIT_EXPR_ARG (arg, iter, t)
197238fd1498Szrj     {
197338fd1498Szrj       if (skipfirst)
197438fd1498Szrj 	skipfirst = false;
197538fd1498Szrj       else
197638fd1498Szrj 	{
197738fd1498Szrj 	  dump_expr (pp, arg, flags | TFF_EXPR_IN_PARENS);
197838fd1498Szrj 	  if (more_aggr_init_expr_args_p (&iter))
197938fd1498Szrj 	    pp_separate_with_comma (pp);
198038fd1498Szrj 	}
198138fd1498Szrj     }
198238fd1498Szrj   pp_cxx_right_paren (pp);
198338fd1498Szrj }
198438fd1498Szrj 
198538fd1498Szrj /* Print out a list of initializers (subr of dump_expr).  */
198638fd1498Szrj 
198738fd1498Szrj static void
dump_expr_list(cxx_pretty_printer * pp,tree l,int flags)198838fd1498Szrj dump_expr_list (cxx_pretty_printer *pp, tree l, int flags)
198938fd1498Szrj {
199038fd1498Szrj   while (l)
199138fd1498Szrj     {
199238fd1498Szrj       dump_expr (pp, TREE_VALUE (l), flags | TFF_EXPR_IN_PARENS);
199338fd1498Szrj       l = TREE_CHAIN (l);
199438fd1498Szrj       if (l)
199538fd1498Szrj 	pp_separate_with_comma (pp);
199638fd1498Szrj     }
199738fd1498Szrj }
199838fd1498Szrj 
199938fd1498Szrj /* Print out a vector of initializers (subr of dump_expr).  */
200038fd1498Szrj 
200138fd1498Szrj static void
dump_expr_init_vec(cxx_pretty_printer * pp,vec<constructor_elt,va_gc> * v,int flags)200238fd1498Szrj dump_expr_init_vec (cxx_pretty_printer *pp, vec<constructor_elt, va_gc> *v,
200338fd1498Szrj                     int flags)
200438fd1498Szrj {
200538fd1498Szrj   unsigned HOST_WIDE_INT idx;
200638fd1498Szrj   tree value;
200738fd1498Szrj 
200838fd1498Szrj   FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
200938fd1498Szrj     {
201038fd1498Szrj       dump_expr (pp, value, flags | TFF_EXPR_IN_PARENS);
201138fd1498Szrj       if (idx != v->length () - 1)
201238fd1498Szrj 	pp_separate_with_comma (pp);
201338fd1498Szrj     }
201438fd1498Szrj }
201538fd1498Szrj 
201638fd1498Szrj 
201738fd1498Szrj /* We've gotten an indirect REFERENCE (an OBJ_TYPE_REF) to a virtual
201838fd1498Szrj    function.  Resolve it to a close relative -- in the sense of static
201938fd1498Szrj    type -- variant being overridden.  That is close to what was written in
202038fd1498Szrj    the source code.  Subroutine of dump_expr.  */
202138fd1498Szrj 
202238fd1498Szrj static tree
resolve_virtual_fun_from_obj_type_ref(tree ref)202338fd1498Szrj resolve_virtual_fun_from_obj_type_ref (tree ref)
202438fd1498Szrj {
202538fd1498Szrj   tree obj_type = TREE_TYPE (OBJ_TYPE_REF_OBJECT (ref));
202638fd1498Szrj   HOST_WIDE_INT index = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (ref));
202738fd1498Szrj   tree fun = BINFO_VIRTUALS (TYPE_BINFO (TREE_TYPE (obj_type)));
202838fd1498Szrj   while (index)
202938fd1498Szrj     {
203038fd1498Szrj       fun = TREE_CHAIN (fun);
203138fd1498Szrj       index -= (TARGET_VTABLE_USES_DESCRIPTORS
203238fd1498Szrj 		? TARGET_VTABLE_USES_DESCRIPTORS : 1);
203338fd1498Szrj     }
203438fd1498Szrj 
203538fd1498Szrj   return BV_FN (fun);
203638fd1498Szrj }
203738fd1498Szrj 
203838fd1498Szrj /* Print out an expression E under control of FLAGS.  */
203938fd1498Szrj 
204038fd1498Szrj static void
dump_expr(cxx_pretty_printer * pp,tree t,int flags)204138fd1498Szrj dump_expr (cxx_pretty_printer *pp, tree t, int flags)
204238fd1498Szrj {
204338fd1498Szrj   tree op;
204438fd1498Szrj 
204538fd1498Szrj   if (t == 0)
204638fd1498Szrj     return;
204738fd1498Szrj 
204838fd1498Szrj   if (STATEMENT_CLASS_P (t))
204938fd1498Szrj     {
205038fd1498Szrj       pp_cxx_ws_string (pp, M_("<statement>"));
205138fd1498Szrj       return;
205238fd1498Szrj     }
205338fd1498Szrj 
205438fd1498Szrj   switch (TREE_CODE (t))
205538fd1498Szrj     {
205638fd1498Szrj     case VAR_DECL:
205738fd1498Szrj     case PARM_DECL:
205838fd1498Szrj     case FIELD_DECL:
205938fd1498Szrj     case CONST_DECL:
206038fd1498Szrj     case FUNCTION_DECL:
206138fd1498Szrj     case TEMPLATE_DECL:
206238fd1498Szrj     case NAMESPACE_DECL:
206338fd1498Szrj     case LABEL_DECL:
206438fd1498Szrj     case OVERLOAD:
206538fd1498Szrj     case TYPE_DECL:
206638fd1498Szrj     case IDENTIFIER_NODE:
206738fd1498Szrj       dump_decl (pp, t, ((flags & ~(TFF_DECL_SPECIFIERS|TFF_RETURN_TYPE
206838fd1498Szrj                                     |TFF_TEMPLATE_HEADER))
206938fd1498Szrj 			 | TFF_NO_TEMPLATE_BINDINGS
207038fd1498Szrj                          | TFF_NO_FUNCTION_ARGUMENTS));
207138fd1498Szrj       break;
207238fd1498Szrj 
207338fd1498Szrj     case SSA_NAME:
207438fd1498Szrj       if (SSA_NAME_VAR (t)
207538fd1498Szrj 	  && !DECL_ARTIFICIAL (SSA_NAME_VAR (t)))
207638fd1498Szrj 	dump_expr (pp, SSA_NAME_VAR (t), flags);
207738fd1498Szrj       else
207838fd1498Szrj 	pp_cxx_ws_string (pp, M_("<unknown>"));
207938fd1498Szrj       break;
208038fd1498Szrj 
208138fd1498Szrj     case VOID_CST:
208238fd1498Szrj     case INTEGER_CST:
208338fd1498Szrj     case REAL_CST:
208438fd1498Szrj     case STRING_CST:
208538fd1498Szrj     case COMPLEX_CST:
208638fd1498Szrj       pp->constant (t);
208738fd1498Szrj       break;
208838fd1498Szrj 
208938fd1498Szrj     case USERDEF_LITERAL:
209038fd1498Szrj       pp_cxx_userdef_literal (pp, t);
209138fd1498Szrj       break;
209238fd1498Szrj 
209338fd1498Szrj     case THROW_EXPR:
209438fd1498Szrj       /* While waiting for caret diagnostics, avoid printing
209538fd1498Szrj 	 __cxa_allocate_exception, __cxa_throw, and the like.  */
209638fd1498Szrj       pp_cxx_ws_string (pp, M_("<throw-expression>"));
209738fd1498Szrj       break;
209838fd1498Szrj 
209938fd1498Szrj     case PTRMEM_CST:
210038fd1498Szrj       pp_ampersand (pp);
210138fd1498Szrj       dump_type (pp, PTRMEM_CST_CLASS (t), flags);
210238fd1498Szrj       pp_cxx_colon_colon (pp);
210338fd1498Szrj       pp_cxx_tree_identifier (pp, DECL_NAME (PTRMEM_CST_MEMBER (t)));
210438fd1498Szrj       break;
210538fd1498Szrj 
210638fd1498Szrj     case COMPOUND_EXPR:
210738fd1498Szrj       pp_cxx_left_paren (pp);
210838fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
210938fd1498Szrj       pp_separate_with_comma (pp);
211038fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
211138fd1498Szrj       pp_cxx_right_paren (pp);
211238fd1498Szrj       break;
211338fd1498Szrj 
211438fd1498Szrj     case COND_EXPR:
211538fd1498Szrj     case VEC_COND_EXPR:
211638fd1498Szrj       pp_cxx_left_paren (pp);
211738fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
211838fd1498Szrj       pp_string (pp, " ? ");
211938fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
212038fd1498Szrj       pp_string (pp, " : ");
212138fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 2), flags | TFF_EXPR_IN_PARENS);
212238fd1498Szrj       pp_cxx_right_paren (pp);
212338fd1498Szrj       break;
212438fd1498Szrj 
212538fd1498Szrj     case SAVE_EXPR:
212638fd1498Szrj       if (TREE_HAS_CONSTRUCTOR (t))
212738fd1498Szrj 	{
212838fd1498Szrj 	  pp_cxx_ws_string (pp, "new");
212938fd1498Szrj 	  pp_cxx_whitespace (pp);
213038fd1498Szrj 	  dump_type (pp, TREE_TYPE (TREE_TYPE (t)), flags);
213138fd1498Szrj 	}
213238fd1498Szrj       else
213338fd1498Szrj 	dump_expr (pp, TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
213438fd1498Szrj       break;
213538fd1498Szrj 
213638fd1498Szrj     case AGGR_INIT_EXPR:
213738fd1498Szrj       {
213838fd1498Szrj 	tree fn = NULL_TREE;
213938fd1498Szrj 
214038fd1498Szrj 	if (TREE_CODE (AGGR_INIT_EXPR_FN (t)) == ADDR_EXPR)
214138fd1498Szrj 	  fn = TREE_OPERAND (AGGR_INIT_EXPR_FN (t), 0);
214238fd1498Szrj 
214338fd1498Szrj 	if (fn && TREE_CODE (fn) == FUNCTION_DECL)
214438fd1498Szrj 	  {
214538fd1498Szrj 	    if (DECL_CONSTRUCTOR_P (fn))
214638fd1498Szrj 	      dump_type (pp, DECL_CONTEXT (fn), flags);
214738fd1498Szrj 	    else
214838fd1498Szrj 	      dump_decl (pp, fn, 0);
214938fd1498Szrj 	  }
215038fd1498Szrj 	else
215138fd1498Szrj 	  dump_expr (pp, AGGR_INIT_EXPR_FN (t), 0);
215238fd1498Szrj       }
215338fd1498Szrj       dump_aggr_init_expr_args (pp, t, flags, true);
215438fd1498Szrj       break;
215538fd1498Szrj 
215638fd1498Szrj     case CALL_EXPR:
215738fd1498Szrj       {
215838fd1498Szrj 	tree fn = CALL_EXPR_FN (t);
215938fd1498Szrj 	bool skipfirst = false;
216038fd1498Szrj 
216138fd1498Szrj 	/* Deal with internal functions.  */
216238fd1498Szrj 	if (fn == NULL_TREE)
216338fd1498Szrj 	  {
216438fd1498Szrj 	    pp_string (pp, internal_fn_name (CALL_EXPR_IFN (t)));
216538fd1498Szrj 	    dump_call_expr_args (pp, t, flags, skipfirst);
216638fd1498Szrj 	    break;
216738fd1498Szrj 	  }
216838fd1498Szrj 
216938fd1498Szrj 	if (TREE_CODE (fn) == ADDR_EXPR)
217038fd1498Szrj 	  fn = TREE_OPERAND (fn, 0);
217138fd1498Szrj 
217238fd1498Szrj 	/* Nobody is interested in seeing the guts of vcalls.  */
217338fd1498Szrj 	if (TREE_CODE (fn) == OBJ_TYPE_REF)
217438fd1498Szrj 	  fn = resolve_virtual_fun_from_obj_type_ref (fn);
217538fd1498Szrj 
217638fd1498Szrj 	if (TREE_TYPE (fn) != NULL_TREE
217738fd1498Szrj 	    && NEXT_CODE (fn) == METHOD_TYPE
217838fd1498Szrj 	    && call_expr_nargs (t))
217938fd1498Szrj 	  {
218038fd1498Szrj 	    tree ob = CALL_EXPR_ARG (t, 0);
218138fd1498Szrj 	    if (TREE_CODE (ob) == ADDR_EXPR)
218238fd1498Szrj 	      {
218338fd1498Szrj 		dump_expr (pp, TREE_OPERAND (ob, 0),
218438fd1498Szrj                            flags | TFF_EXPR_IN_PARENS);
218538fd1498Szrj 		pp_cxx_dot (pp);
218638fd1498Szrj 	      }
218738fd1498Szrj 	    else if (!is_this_parameter (ob))
218838fd1498Szrj 	      {
218938fd1498Szrj 		dump_expr (pp, ob, flags | TFF_EXPR_IN_PARENS);
219038fd1498Szrj 		pp_cxx_arrow (pp);
219138fd1498Szrj 	      }
219238fd1498Szrj 	    skipfirst = true;
219338fd1498Szrj 	  }
219438fd1498Szrj 	if (flag_sanitize & SANITIZE_UNDEFINED
219538fd1498Szrj 	    && is_ubsan_builtin_p (fn))
219638fd1498Szrj 	  {
219738fd1498Szrj 	    pp_string (cxx_pp, M_("<ubsan routine call>"));
219838fd1498Szrj 	    break;
219938fd1498Szrj 	  }
220038fd1498Szrj 	dump_expr (pp, fn, flags | TFF_EXPR_IN_PARENS);
220138fd1498Szrj 	dump_call_expr_args (pp, t, flags, skipfirst);
220238fd1498Szrj       }
220338fd1498Szrj       break;
220438fd1498Szrj 
220538fd1498Szrj     case TARGET_EXPR:
220638fd1498Szrj       /* Note that this only works for G++ target exprs.  If somebody
220738fd1498Szrj 	 builds a general TARGET_EXPR, there's no way to represent that
220838fd1498Szrj 	 it initializes anything other that the parameter slot for the
220938fd1498Szrj 	 default argument.  Note we may have cleared out the first
221038fd1498Szrj 	 operand in expand_expr, so don't go killing ourselves.  */
221138fd1498Szrj       if (TREE_OPERAND (t, 1))
221238fd1498Szrj 	dump_expr (pp, TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
221338fd1498Szrj       break;
221438fd1498Szrj 
221538fd1498Szrj     case POINTER_PLUS_EXPR:
221638fd1498Szrj       dump_binary_op (pp, "+", t, flags);
221738fd1498Szrj       break;
221838fd1498Szrj 
221938fd1498Szrj     case POINTER_DIFF_EXPR:
222038fd1498Szrj       dump_binary_op (pp, "-", t, flags);
222138fd1498Szrj       break;
222238fd1498Szrj 
222338fd1498Szrj     case INIT_EXPR:
222438fd1498Szrj     case MODIFY_EXPR:
222538fd1498Szrj       dump_binary_op (pp, OVL_OP_INFO (true, NOP_EXPR)->name, t, flags);
222638fd1498Szrj       break;
222738fd1498Szrj 
222838fd1498Szrj     case PLUS_EXPR:
222938fd1498Szrj     case MINUS_EXPR:
223038fd1498Szrj     case MULT_EXPR:
223138fd1498Szrj     case TRUNC_DIV_EXPR:
223238fd1498Szrj     case TRUNC_MOD_EXPR:
223338fd1498Szrj     case MIN_EXPR:
223438fd1498Szrj     case MAX_EXPR:
223538fd1498Szrj     case LSHIFT_EXPR:
223638fd1498Szrj     case RSHIFT_EXPR:
223738fd1498Szrj     case BIT_IOR_EXPR:
223838fd1498Szrj     case BIT_XOR_EXPR:
223938fd1498Szrj     case BIT_AND_EXPR:
224038fd1498Szrj     case TRUTH_ANDIF_EXPR:
224138fd1498Szrj     case TRUTH_ORIF_EXPR:
224238fd1498Szrj     case LT_EXPR:
224338fd1498Szrj     case LE_EXPR:
224438fd1498Szrj     case GT_EXPR:
224538fd1498Szrj     case GE_EXPR:
224638fd1498Szrj     case EQ_EXPR:
224738fd1498Szrj     case NE_EXPR:
224838fd1498Szrj     case EXACT_DIV_EXPR:
224938fd1498Szrj       dump_binary_op (pp, OVL_OP_INFO (false, TREE_CODE (t))->name, t, flags);
225038fd1498Szrj       break;
225138fd1498Szrj 
225238fd1498Szrj     case CEIL_DIV_EXPR:
225338fd1498Szrj     case FLOOR_DIV_EXPR:
225438fd1498Szrj     case ROUND_DIV_EXPR:
225538fd1498Szrj     case RDIV_EXPR:
225638fd1498Szrj       dump_binary_op (pp, "/", t, flags);
225738fd1498Szrj       break;
225838fd1498Szrj 
225938fd1498Szrj     case CEIL_MOD_EXPR:
226038fd1498Szrj     case FLOOR_MOD_EXPR:
226138fd1498Szrj     case ROUND_MOD_EXPR:
226238fd1498Szrj       dump_binary_op (pp, "%", t, flags);
226338fd1498Szrj       break;
226438fd1498Szrj 
226538fd1498Szrj     case COMPONENT_REF:
226638fd1498Szrj       {
226738fd1498Szrj 	tree ob = TREE_OPERAND (t, 0);
226838fd1498Szrj 	if (INDIRECT_REF_P (ob))
226938fd1498Szrj 	  {
227038fd1498Szrj 	    ob = TREE_OPERAND (ob, 0);
227138fd1498Szrj 	    if (!is_this_parameter (ob))
227238fd1498Szrj 	      {
227338fd1498Szrj 		dump_expr (pp, ob, flags | TFF_EXPR_IN_PARENS);
227438fd1498Szrj 		if (TREE_CODE (TREE_TYPE (ob)) == REFERENCE_TYPE)
227538fd1498Szrj 		  pp_cxx_dot (pp);
227638fd1498Szrj 		else
227738fd1498Szrj 		  pp_cxx_arrow (pp);
227838fd1498Szrj 	      }
227938fd1498Szrj 	  }
228038fd1498Szrj 	else
228138fd1498Szrj 	  {
228238fd1498Szrj 	    dump_expr (pp, ob, flags | TFF_EXPR_IN_PARENS);
228338fd1498Szrj 	    if (TREE_CODE (ob) != ARROW_EXPR)
228438fd1498Szrj 	      pp_cxx_dot (pp);
228538fd1498Szrj 	  }
228638fd1498Szrj 	dump_expr (pp, TREE_OPERAND (t, 1), flags & ~TFF_EXPR_IN_PARENS);
228738fd1498Szrj       }
228838fd1498Szrj       break;
228938fd1498Szrj 
229038fd1498Szrj     case ARRAY_REF:
229138fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
229238fd1498Szrj       pp_cxx_left_bracket (pp);
229338fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
229438fd1498Szrj       pp_cxx_right_bracket (pp);
229538fd1498Szrj       break;
229638fd1498Szrj 
229738fd1498Szrj     case UNARY_PLUS_EXPR:
229838fd1498Szrj       dump_unary_op (pp, "+", t, flags);
229938fd1498Szrj       break;
230038fd1498Szrj 
230138fd1498Szrj     case ADDR_EXPR:
230238fd1498Szrj       if (TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
230338fd1498Szrj 	  || TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST
230438fd1498Szrj 	  /* An ADDR_EXPR can have reference type.  In that case, we
230538fd1498Szrj 	     shouldn't print the `&' doing so indicates to the user
230638fd1498Szrj 	     that the expression has pointer type.  */
230738fd1498Szrj 	  || (TREE_TYPE (t)
230838fd1498Szrj 	      && TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE))
230938fd1498Szrj 	dump_expr (pp, TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
231038fd1498Szrj       else if (TREE_CODE (TREE_OPERAND (t, 0)) == LABEL_DECL)
231138fd1498Szrj 	dump_unary_op (pp, "&&", t, flags);
231238fd1498Szrj       else
231338fd1498Szrj 	dump_unary_op (pp, "&", t, flags);
231438fd1498Szrj       break;
231538fd1498Szrj 
231638fd1498Szrj     case INDIRECT_REF:
231738fd1498Szrj       if (TREE_HAS_CONSTRUCTOR (t))
231838fd1498Szrj 	{
231938fd1498Szrj 	  t = TREE_OPERAND (t, 0);
232038fd1498Szrj 	  gcc_assert (TREE_CODE (t) == CALL_EXPR);
232138fd1498Szrj 	  dump_expr (pp, CALL_EXPR_FN (t), flags | TFF_EXPR_IN_PARENS);
232238fd1498Szrj 	  dump_call_expr_args (pp, t, flags, true);
232338fd1498Szrj 	}
232438fd1498Szrj       else
232538fd1498Szrj 	{
232638fd1498Szrj 	  if (TREE_OPERAND (t,0) != NULL_TREE
232738fd1498Szrj 	      && TREE_TYPE (TREE_OPERAND (t, 0))
232838fd1498Szrj 	      && NEXT_CODE (TREE_OPERAND (t, 0)) == REFERENCE_TYPE)
232938fd1498Szrj 	    dump_expr (pp, TREE_OPERAND (t, 0), flags);
233038fd1498Szrj 	  else
233138fd1498Szrj 	    dump_unary_op (pp, "*", t, flags);
233238fd1498Szrj 	}
233338fd1498Szrj       break;
233438fd1498Szrj 
233538fd1498Szrj     case MEM_REF:
233638fd1498Szrj       if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
233738fd1498Szrj 	  && integer_zerop (TREE_OPERAND (t, 1)))
233838fd1498Szrj 	dump_expr (pp, TREE_OPERAND (TREE_OPERAND (t, 0), 0), flags);
233938fd1498Szrj       else
234038fd1498Szrj 	{
234138fd1498Szrj 	  pp_cxx_star (pp);
234238fd1498Szrj 	  if (!integer_zerop (TREE_OPERAND (t, 1)))
234338fd1498Szrj 	    {
234438fd1498Szrj 	      pp_cxx_left_paren (pp);
234538fd1498Szrj 	      if (!integer_onep (TYPE_SIZE_UNIT
234638fd1498Szrj 				 (TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0))))))
234738fd1498Szrj 		{
234838fd1498Szrj 		  pp_cxx_left_paren (pp);
234938fd1498Szrj 		  dump_type (pp, ptr_type_node, flags);
235038fd1498Szrj 		  pp_cxx_right_paren (pp);
235138fd1498Szrj 		}
235238fd1498Szrj 	    }
235338fd1498Szrj 	  dump_expr (pp, TREE_OPERAND (t, 0), flags);
235438fd1498Szrj 	  if (!integer_zerop (TREE_OPERAND (t, 1)))
235538fd1498Szrj 	    {
235638fd1498Szrj 	      pp_cxx_ws_string (pp, "+");
235738fd1498Szrj 	      dump_expr (pp, fold_convert (ssizetype, TREE_OPERAND (t, 1)),
235838fd1498Szrj                          flags);
235938fd1498Szrj 	      pp_cxx_right_paren (pp);
236038fd1498Szrj 	    }
236138fd1498Szrj 	}
236238fd1498Szrj       break;
236338fd1498Szrj 
236438fd1498Szrj     case NEGATE_EXPR:
236538fd1498Szrj     case BIT_NOT_EXPR:
236638fd1498Szrj     case TRUTH_NOT_EXPR:
236738fd1498Szrj     case PREDECREMENT_EXPR:
236838fd1498Szrj     case PREINCREMENT_EXPR:
236938fd1498Szrj       dump_unary_op (pp, OVL_OP_INFO (false, TREE_CODE (t))->name, t, flags);
237038fd1498Szrj       break;
237138fd1498Szrj 
237238fd1498Szrj     case POSTDECREMENT_EXPR:
237338fd1498Szrj     case POSTINCREMENT_EXPR:
237438fd1498Szrj       pp_cxx_left_paren (pp);
237538fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
237638fd1498Szrj       pp_cxx_ws_string (pp, OVL_OP_INFO (false, TREE_CODE (t))->name);
237738fd1498Szrj       pp_cxx_right_paren (pp);
237838fd1498Szrj       break;
237938fd1498Szrj 
238038fd1498Szrj     case NON_LVALUE_EXPR:
238138fd1498Szrj       /* FIXME: This is a KLUDGE workaround for a parsing problem.  There
238238fd1498Szrj 	 should be another level of INDIRECT_REF so that I don't have to do
238338fd1498Szrj 	 this.  */
238438fd1498Szrj       if (TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == POINTER_TYPE)
238538fd1498Szrj 	{
238638fd1498Szrj 	  tree next = TREE_TYPE (TREE_TYPE (t));
238738fd1498Szrj 
238838fd1498Szrj 	  while (TYPE_PTR_P (next))
238938fd1498Szrj 	    next = TREE_TYPE (next);
239038fd1498Szrj 
239138fd1498Szrj 	  if (TREE_CODE (next) == FUNCTION_TYPE)
239238fd1498Szrj 	    {
239338fd1498Szrj 	      if (flags & TFF_EXPR_IN_PARENS)
239438fd1498Szrj 		pp_cxx_left_paren (pp);
239538fd1498Szrj 	      pp_cxx_star (pp);
239638fd1498Szrj 	      dump_expr (pp, TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
239738fd1498Szrj 	      if (flags & TFF_EXPR_IN_PARENS)
239838fd1498Szrj 		pp_cxx_right_paren (pp);
239938fd1498Szrj 	      break;
240038fd1498Szrj 	    }
240138fd1498Szrj 	  /* Else fall through.  */
240238fd1498Szrj 	}
240338fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
240438fd1498Szrj       break;
240538fd1498Szrj 
240638fd1498Szrj     CASE_CONVERT:
240738fd1498Szrj     case IMPLICIT_CONV_EXPR:
240838fd1498Szrj     case VIEW_CONVERT_EXPR:
240938fd1498Szrj       {
241038fd1498Szrj 	tree op = TREE_OPERAND (t, 0);
241138fd1498Szrj 	tree ttype = TREE_TYPE (t);
241238fd1498Szrj 	tree optype = TREE_TYPE (op);
241338fd1498Szrj 
241438fd1498Szrj 	if (TREE_CODE (ttype) != TREE_CODE (optype)
241538fd1498Szrj 	    && POINTER_TYPE_P (ttype)
241638fd1498Szrj 	    && POINTER_TYPE_P (optype)
241738fd1498Szrj 	    && same_type_p (TREE_TYPE (optype),
241838fd1498Szrj 			    TREE_TYPE (ttype)))
241938fd1498Szrj 	  {
242038fd1498Szrj 	    if (TREE_CODE (ttype) == REFERENCE_TYPE)
242138fd1498Szrj 	      {
242238fd1498Szrj 		STRIP_NOPS (op);
242338fd1498Szrj 		if (TREE_CODE (op) == ADDR_EXPR)
242438fd1498Szrj 		  dump_expr (pp, TREE_OPERAND (op, 0), flags);
242538fd1498Szrj 		else
242638fd1498Szrj 		  dump_unary_op (pp, "*", t, flags);
242738fd1498Szrj 	      }
242838fd1498Szrj 	    else
242938fd1498Szrj 	      dump_unary_op (pp, "&", t, flags);
243038fd1498Szrj 	  }
243138fd1498Szrj 	else if (!same_type_p (TREE_TYPE (op), TREE_TYPE (t)))
243238fd1498Szrj 	  {
243338fd1498Szrj 	    /* It is a cast, but we cannot tell whether it is a
243438fd1498Szrj 	       reinterpret or static cast. Use the C style notation.  */
243538fd1498Szrj 	    if (flags & TFF_EXPR_IN_PARENS)
243638fd1498Szrj 	      pp_cxx_left_paren (pp);
243738fd1498Szrj 	    pp_cxx_left_paren (pp);
243838fd1498Szrj 	    dump_type (pp, TREE_TYPE (t), flags);
243938fd1498Szrj 	    pp_cxx_right_paren (pp);
244038fd1498Szrj 	    dump_expr (pp, op, flags | TFF_EXPR_IN_PARENS);
244138fd1498Szrj 	    if (flags & TFF_EXPR_IN_PARENS)
244238fd1498Szrj 	      pp_cxx_right_paren (pp);
244338fd1498Szrj 	  }
244438fd1498Szrj 	else
244538fd1498Szrj 	  dump_expr (pp, op, flags);
244638fd1498Szrj 	break;
244738fd1498Szrj       }
244838fd1498Szrj 
244938fd1498Szrj     case CONSTRUCTOR:
245038fd1498Szrj       if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
245138fd1498Szrj 	{
245238fd1498Szrj 	  tree idx = build_ptrmemfunc_access_expr (t, pfn_identifier);
245338fd1498Szrj 
245438fd1498Szrj 	  if (integer_zerop (idx))
245538fd1498Szrj 	    {
245638fd1498Szrj 	      /* A NULL pointer-to-member constant.  */
245738fd1498Szrj 	      pp_cxx_left_paren (pp);
245838fd1498Szrj 	      pp_cxx_left_paren (pp);
245938fd1498Szrj 	      dump_type (pp, TREE_TYPE (t), flags);
246038fd1498Szrj 	      pp_cxx_right_paren (pp);
246138fd1498Szrj 	      pp_character (pp, '0');
246238fd1498Szrj 	      pp_cxx_right_paren (pp);
246338fd1498Szrj 	      break;
246438fd1498Szrj 	    }
246538fd1498Szrj 	  else if (tree_fits_shwi_p (idx))
246638fd1498Szrj 	    {
246738fd1498Szrj 	      tree virtuals;
246838fd1498Szrj 	      unsigned HOST_WIDE_INT n;
246938fd1498Szrj 
247038fd1498Szrj 	      t = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)));
247138fd1498Szrj 	      t = TYPE_METHOD_BASETYPE (t);
247238fd1498Szrj 	      virtuals = BINFO_VIRTUALS (TYPE_BINFO (TYPE_MAIN_VARIANT (t)));
247338fd1498Szrj 
247438fd1498Szrj 	      n = tree_to_shwi (idx);
247538fd1498Szrj 
247638fd1498Szrj 	      /* Map vtable index back one, to allow for the null pointer to
247738fd1498Szrj 		 member.  */
247838fd1498Szrj 	      --n;
247938fd1498Szrj 
248038fd1498Szrj 	      while (n > 0 && virtuals)
248138fd1498Szrj 		{
248238fd1498Szrj 		  --n;
248338fd1498Szrj 		  virtuals = TREE_CHAIN (virtuals);
248438fd1498Szrj 		}
248538fd1498Szrj 	      if (virtuals)
248638fd1498Szrj 		{
248738fd1498Szrj 		  dump_expr (pp, BV_FN (virtuals),
248838fd1498Szrj 			     flags | TFF_EXPR_IN_PARENS);
248938fd1498Szrj 		  break;
249038fd1498Szrj 		}
249138fd1498Szrj 	    }
249238fd1498Szrj 	}
249338fd1498Szrj       if (TREE_TYPE (t) && LAMBDA_TYPE_P (TREE_TYPE (t)))
249438fd1498Szrj 	pp_string (pp, "<lambda closure object>");
249538fd1498Szrj       if (TREE_TYPE (t) && EMPTY_CONSTRUCTOR_P (t))
249638fd1498Szrj 	{
249738fd1498Szrj 	  dump_type (pp, TREE_TYPE (t), 0);
249838fd1498Szrj 	  pp_cxx_left_paren (pp);
249938fd1498Szrj 	  pp_cxx_right_paren (pp);
250038fd1498Szrj 	}
250138fd1498Szrj       else
250238fd1498Szrj 	{
250338fd1498Szrj 	  if (!BRACE_ENCLOSED_INITIALIZER_P (t))
250438fd1498Szrj 	    dump_type (pp, TREE_TYPE (t), 0);
250538fd1498Szrj 	  pp_cxx_left_brace (pp);
250638fd1498Szrj 	  dump_expr_init_vec (pp, CONSTRUCTOR_ELTS (t), flags);
250738fd1498Szrj 	  pp_cxx_right_brace (pp);
250838fd1498Szrj 	}
250938fd1498Szrj 
251038fd1498Szrj       break;
251138fd1498Szrj 
251238fd1498Szrj     case OFFSET_REF:
251338fd1498Szrj       {
251438fd1498Szrj 	tree ob = TREE_OPERAND (t, 0);
251538fd1498Szrj 	if (is_dummy_object (ob))
251638fd1498Szrj 	  {
251738fd1498Szrj 	    t = TREE_OPERAND (t, 1);
251838fd1498Szrj 	    if (TREE_CODE (t) == FUNCTION_DECL)
251938fd1498Szrj 	      /* A::f */
252038fd1498Szrj 	      dump_expr (pp, t, flags | TFF_EXPR_IN_PARENS);
252138fd1498Szrj 	    else if (BASELINK_P (t))
252238fd1498Szrj 	      dump_expr (pp, OVL_FIRST (BASELINK_FUNCTIONS (t)),
252338fd1498Szrj 			 flags | TFF_EXPR_IN_PARENS);
252438fd1498Szrj 	    else
252538fd1498Szrj 	      dump_decl (pp, t, flags);
252638fd1498Szrj 	  }
252738fd1498Szrj 	else
252838fd1498Szrj 	  {
252938fd1498Szrj 	    if (INDIRECT_REF_P (ob))
253038fd1498Szrj 	      {
253138fd1498Szrj 		dump_expr (pp, TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS);
253238fd1498Szrj 		pp_cxx_arrow (pp);
253338fd1498Szrj 		pp_cxx_star (pp);
253438fd1498Szrj 	      }
253538fd1498Szrj 	    else
253638fd1498Szrj 	      {
253738fd1498Szrj 		dump_expr (pp, ob, flags | TFF_EXPR_IN_PARENS);
253838fd1498Szrj 		pp_cxx_dot (pp);
253938fd1498Szrj 		pp_cxx_star (pp);
254038fd1498Szrj 	      }
254138fd1498Szrj 	    dump_expr (pp, TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
254238fd1498Szrj 	  }
254338fd1498Szrj 	break;
254438fd1498Szrj       }
254538fd1498Szrj 
254638fd1498Szrj     case TEMPLATE_PARM_INDEX:
254738fd1498Szrj       dump_decl (pp, TEMPLATE_PARM_DECL (t), flags & ~TFF_DECL_SPECIFIERS);
254838fd1498Szrj       break;
254938fd1498Szrj 
255038fd1498Szrj     case CAST_EXPR:
255138fd1498Szrj       if (TREE_OPERAND (t, 0) == NULL_TREE
255238fd1498Szrj 	  || TREE_CHAIN (TREE_OPERAND (t, 0)))
255338fd1498Szrj 	{
255438fd1498Szrj 	  dump_type (pp, TREE_TYPE (t), flags);
255538fd1498Szrj 	  pp_cxx_left_paren (pp);
255638fd1498Szrj 	  dump_expr_list (pp, TREE_OPERAND (t, 0), flags);
255738fd1498Szrj 	  pp_cxx_right_paren (pp);
255838fd1498Szrj 	}
255938fd1498Szrj       else
256038fd1498Szrj 	{
256138fd1498Szrj 	  pp_cxx_left_paren (pp);
256238fd1498Szrj 	  dump_type (pp, TREE_TYPE (t), flags);
256338fd1498Szrj 	  pp_cxx_right_paren (pp);
256438fd1498Szrj 	  pp_cxx_left_paren (pp);
256538fd1498Szrj 	  dump_expr_list (pp, TREE_OPERAND (t, 0), flags);
256638fd1498Szrj 	  pp_cxx_right_paren (pp);
256738fd1498Szrj 	}
256838fd1498Szrj       break;
256938fd1498Szrj 
257038fd1498Szrj     case STATIC_CAST_EXPR:
257138fd1498Szrj       pp_cxx_ws_string (pp, "static_cast");
257238fd1498Szrj       goto cast;
257338fd1498Szrj     case REINTERPRET_CAST_EXPR:
257438fd1498Szrj       pp_cxx_ws_string (pp, "reinterpret_cast");
257538fd1498Szrj       goto cast;
257638fd1498Szrj     case CONST_CAST_EXPR:
257738fd1498Szrj       pp_cxx_ws_string (pp, "const_cast");
257838fd1498Szrj       goto cast;
257938fd1498Szrj     case DYNAMIC_CAST_EXPR:
258038fd1498Szrj       pp_cxx_ws_string (pp, "dynamic_cast");
258138fd1498Szrj     cast:
258238fd1498Szrj       pp_cxx_begin_template_argument_list (pp);
258338fd1498Szrj       dump_type (pp, TREE_TYPE (t), flags);
258438fd1498Szrj       pp_cxx_end_template_argument_list (pp);
258538fd1498Szrj       pp_cxx_left_paren (pp);
258638fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 0), flags);
258738fd1498Szrj       pp_cxx_right_paren (pp);
258838fd1498Szrj       break;
258938fd1498Szrj 
259038fd1498Szrj     case ARROW_EXPR:
259138fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 0), flags);
259238fd1498Szrj       pp_cxx_arrow (pp);
259338fd1498Szrj       break;
259438fd1498Szrj 
259538fd1498Szrj     case SIZEOF_EXPR:
259638fd1498Szrj     case ALIGNOF_EXPR:
259738fd1498Szrj       if (TREE_CODE (t) == SIZEOF_EXPR)
259838fd1498Szrj 	pp_cxx_ws_string (pp, "sizeof");
259938fd1498Szrj       else
260038fd1498Szrj 	{
260138fd1498Szrj 	  gcc_assert (TREE_CODE (t) == ALIGNOF_EXPR);
260238fd1498Szrj 	  pp_cxx_ws_string (pp, "__alignof__");
260338fd1498Szrj 	}
260438fd1498Szrj       op = TREE_OPERAND (t, 0);
260538fd1498Szrj       if (PACK_EXPANSION_P (op))
260638fd1498Szrj 	{
260738fd1498Szrj 	  pp_string (pp, "...");
260838fd1498Szrj 	  op = PACK_EXPANSION_PATTERN (op);
260938fd1498Szrj 	}
261038fd1498Szrj       pp_cxx_whitespace (pp);
261138fd1498Szrj       pp_cxx_left_paren (pp);
261238fd1498Szrj       if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
261338fd1498Szrj 	dump_type (pp, TREE_TYPE (op), flags);
261438fd1498Szrj       else if (TYPE_P (TREE_OPERAND (t, 0)))
261538fd1498Szrj 	dump_type (pp, op, flags);
261638fd1498Szrj       else
261738fd1498Szrj 	dump_expr (pp, op, flags);
261838fd1498Szrj       pp_cxx_right_paren (pp);
261938fd1498Szrj       break;
262038fd1498Szrj 
262138fd1498Szrj     case AT_ENCODE_EXPR:
262238fd1498Szrj       pp_cxx_ws_string (pp, "@encode");
262338fd1498Szrj       pp_cxx_whitespace (pp);
262438fd1498Szrj       pp_cxx_left_paren (pp);
262538fd1498Szrj       dump_type (pp, TREE_OPERAND (t, 0), flags);
262638fd1498Szrj       pp_cxx_right_paren (pp);
262738fd1498Szrj       break;
262838fd1498Szrj 
262938fd1498Szrj     case NOEXCEPT_EXPR:
263038fd1498Szrj       pp_cxx_ws_string (pp, "noexcept");
263138fd1498Szrj       pp_cxx_whitespace (pp);
263238fd1498Szrj       pp_cxx_left_paren (pp);
263338fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 0), flags);
263438fd1498Szrj       pp_cxx_right_paren (pp);
263538fd1498Szrj       break;
263638fd1498Szrj 
263738fd1498Szrj     case REALPART_EXPR:
263838fd1498Szrj     case IMAGPART_EXPR:
263938fd1498Szrj       pp_cxx_ws_string (pp, OVL_OP_INFO (false, TREE_CODE (t))->name);
264038fd1498Szrj       pp_cxx_whitespace (pp);
264138fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 0), flags);
264238fd1498Szrj       break;
264338fd1498Szrj 
264438fd1498Szrj     case DEFAULT_ARG:
264538fd1498Szrj       pp_string (pp, M_("<unparsed>"));
264638fd1498Szrj       break;
264738fd1498Szrj 
264838fd1498Szrj     case TRY_CATCH_EXPR:
264938fd1498Szrj     case CLEANUP_POINT_EXPR:
265038fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 0), flags);
265138fd1498Szrj       break;
265238fd1498Szrj 
265338fd1498Szrj     case PSEUDO_DTOR_EXPR:
265438fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 0), flags);
265538fd1498Szrj       pp_cxx_dot (pp);
265638fd1498Szrj       if (TREE_OPERAND (t, 1))
265738fd1498Szrj 	{
265838fd1498Szrj 	  dump_type (pp, TREE_OPERAND (t, 1), flags);
265938fd1498Szrj 	  pp_cxx_colon_colon (pp);
266038fd1498Szrj 	}
266138fd1498Szrj       pp_cxx_complement (pp);
266238fd1498Szrj       dump_type (pp, TREE_OPERAND (t, 2), flags);
266338fd1498Szrj       break;
266438fd1498Szrj 
266538fd1498Szrj     case TEMPLATE_ID_EXPR:
266638fd1498Szrj       dump_decl (pp, t, flags);
266738fd1498Szrj       break;
266838fd1498Szrj 
266938fd1498Szrj     case BIND_EXPR:
267038fd1498Szrj     case STMT_EXPR:
267138fd1498Szrj     case EXPR_STMT:
267238fd1498Szrj     case STATEMENT_LIST:
267338fd1498Szrj       /* We don't yet have a way of dumping statements in a
267438fd1498Szrj 	 human-readable format.  */
267538fd1498Szrj       pp_string (pp, "({...})");
267638fd1498Szrj       break;
267738fd1498Szrj 
267838fd1498Szrj     case LOOP_EXPR:
267938fd1498Szrj       pp_string (pp, "while (1) { ");
268038fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
268138fd1498Szrj       pp_cxx_right_brace (pp);
268238fd1498Szrj       break;
268338fd1498Szrj 
268438fd1498Szrj     case EXIT_EXPR:
268538fd1498Szrj       pp_string (pp, "if (");
268638fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
268738fd1498Szrj       pp_string (pp, ") break; ");
268838fd1498Szrj       break;
268938fd1498Szrj 
269038fd1498Szrj     case BASELINK:
269138fd1498Szrj       dump_expr (pp, BASELINK_FUNCTIONS (t), flags & ~TFF_EXPR_IN_PARENS);
269238fd1498Szrj       break;
269338fd1498Szrj 
269438fd1498Szrj     case EMPTY_CLASS_EXPR:
269538fd1498Szrj       dump_type (pp, TREE_TYPE (t), flags);
269638fd1498Szrj       pp_cxx_left_paren (pp);
269738fd1498Szrj       pp_cxx_right_paren (pp);
269838fd1498Szrj       break;
269938fd1498Szrj 
270038fd1498Szrj     case NON_DEPENDENT_EXPR:
270138fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 0), flags);
270238fd1498Szrj       break;
270338fd1498Szrj 
270438fd1498Szrj     case ARGUMENT_PACK_SELECT:
270538fd1498Szrj       dump_template_argument (pp, ARGUMENT_PACK_SELECT_FROM_PACK (t), flags);
270638fd1498Szrj       break;
270738fd1498Szrj 
270838fd1498Szrj     case RECORD_TYPE:
270938fd1498Szrj     case UNION_TYPE:
271038fd1498Szrj     case ENUMERAL_TYPE:
271138fd1498Szrj     case REAL_TYPE:
271238fd1498Szrj     case VOID_TYPE:
271338fd1498Szrj     case BOOLEAN_TYPE:
271438fd1498Szrj     case INTEGER_TYPE:
271538fd1498Szrj     case COMPLEX_TYPE:
271638fd1498Szrj     case VECTOR_TYPE:
271738fd1498Szrj     case DECLTYPE_TYPE:
271838fd1498Szrj       pp_type_specifier_seq (pp, t);
271938fd1498Szrj       break;
272038fd1498Szrj 
272138fd1498Szrj     case TYPENAME_TYPE:
272238fd1498Szrj       /* We get here when we want to print a dependent type as an
272338fd1498Szrj          id-expression, without any disambiguator decoration.  */
272438fd1498Szrj       pp->id_expression (t);
272538fd1498Szrj       break;
272638fd1498Szrj 
272738fd1498Szrj     case TEMPLATE_TYPE_PARM:
272838fd1498Szrj     case TEMPLATE_TEMPLATE_PARM:
272938fd1498Szrj     case BOUND_TEMPLATE_TEMPLATE_PARM:
273038fd1498Szrj       dump_type (pp, t, flags);
273138fd1498Szrj       break;
273238fd1498Szrj 
273338fd1498Szrj     case TRAIT_EXPR:
273438fd1498Szrj       pp_cxx_trait_expression (pp, t);
273538fd1498Szrj       break;
273638fd1498Szrj 
273738fd1498Szrj     case VA_ARG_EXPR:
273838fd1498Szrj       pp_cxx_va_arg_expression (pp, t);
273938fd1498Szrj       break;
274038fd1498Szrj 
274138fd1498Szrj     case OFFSETOF_EXPR:
274238fd1498Szrj       pp_cxx_offsetof_expression (pp, t);
274338fd1498Szrj       break;
274438fd1498Szrj 
274538fd1498Szrj     case ADDRESSOF_EXPR:
274638fd1498Szrj       pp_cxx_addressof_expression (pp, t);
274738fd1498Szrj       break;
274838fd1498Szrj 
274938fd1498Szrj     case SCOPE_REF:
275038fd1498Szrj       dump_decl (pp, t, flags);
275138fd1498Szrj       break;
275238fd1498Szrj 
275338fd1498Szrj     case EXPR_PACK_EXPANSION:
275438fd1498Szrj     case UNARY_LEFT_FOLD_EXPR:
275538fd1498Szrj     case UNARY_RIGHT_FOLD_EXPR:
275638fd1498Szrj     case BINARY_LEFT_FOLD_EXPR:
275738fd1498Szrj     case BINARY_RIGHT_FOLD_EXPR:
275838fd1498Szrj     case TYPEID_EXPR:
275938fd1498Szrj     case MEMBER_REF:
276038fd1498Szrj     case DOTSTAR_EXPR:
276138fd1498Szrj     case NEW_EXPR:
276238fd1498Szrj     case VEC_NEW_EXPR:
276338fd1498Szrj     case DELETE_EXPR:
276438fd1498Szrj     case VEC_DELETE_EXPR:
276538fd1498Szrj     case MODOP_EXPR:
276638fd1498Szrj     case ABS_EXPR:
276738fd1498Szrj     case CONJ_EXPR:
276838fd1498Szrj     case VECTOR_CST:
276938fd1498Szrj     case FIXED_CST:
277038fd1498Szrj     case UNORDERED_EXPR:
277138fd1498Szrj     case ORDERED_EXPR:
277238fd1498Szrj     case UNLT_EXPR:
277338fd1498Szrj     case UNLE_EXPR:
277438fd1498Szrj     case UNGT_EXPR:
277538fd1498Szrj     case UNGE_EXPR:
277638fd1498Szrj     case UNEQ_EXPR:
277738fd1498Szrj     case LTGT_EXPR:
277838fd1498Szrj     case COMPLEX_EXPR:
277938fd1498Szrj     case BIT_FIELD_REF:
278038fd1498Szrj     case FIX_TRUNC_EXPR:
278138fd1498Szrj     case FLOAT_EXPR:
278238fd1498Szrj       pp->expression (t);
278338fd1498Szrj       break;
278438fd1498Szrj 
278538fd1498Szrj     case TRUTH_AND_EXPR:
278638fd1498Szrj     case TRUTH_OR_EXPR:
278738fd1498Szrj     case TRUTH_XOR_EXPR:
278838fd1498Szrj       if (flags & TFF_EXPR_IN_PARENS)
278938fd1498Szrj 	pp_cxx_left_paren (pp);
279038fd1498Szrj       pp->expression (t);
279138fd1498Szrj       if (flags & TFF_EXPR_IN_PARENS)
279238fd1498Szrj 	pp_cxx_right_paren (pp);
279338fd1498Szrj       break;
279438fd1498Szrj 
279538fd1498Szrj     case OBJ_TYPE_REF:
279638fd1498Szrj       dump_expr (pp, resolve_virtual_fun_from_obj_type_ref (t), flags);
279738fd1498Szrj       break;
279838fd1498Szrj 
279938fd1498Szrj     case LAMBDA_EXPR:
280038fd1498Szrj       pp_string (pp, M_("<lambda>"));
280138fd1498Szrj       break;
280238fd1498Szrj 
280338fd1498Szrj     case PAREN_EXPR:
280438fd1498Szrj       pp_cxx_left_paren (pp);
280538fd1498Szrj       dump_expr (pp, TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
280638fd1498Szrj       pp_cxx_right_paren (pp);
280738fd1498Szrj       break;
280838fd1498Szrj 
280938fd1498Szrj     case REQUIRES_EXPR:
281038fd1498Szrj       pp_cxx_requires_expr (cxx_pp, t);
281138fd1498Szrj       break;
281238fd1498Szrj 
281338fd1498Szrj     case SIMPLE_REQ:
281438fd1498Szrj       pp_cxx_simple_requirement (cxx_pp, t);
281538fd1498Szrj       break;
281638fd1498Szrj 
281738fd1498Szrj     case TYPE_REQ:
281838fd1498Szrj       pp_cxx_type_requirement (cxx_pp, t);
281938fd1498Szrj       break;
282038fd1498Szrj 
282138fd1498Szrj     case COMPOUND_REQ:
282238fd1498Szrj       pp_cxx_compound_requirement (cxx_pp, t);
282338fd1498Szrj       break;
282438fd1498Szrj 
282538fd1498Szrj     case NESTED_REQ:
282638fd1498Szrj       pp_cxx_nested_requirement (cxx_pp, t);
282738fd1498Szrj       break;
282838fd1498Szrj 
282938fd1498Szrj     case PRED_CONSTR:
283038fd1498Szrj     case CHECK_CONSTR:
283138fd1498Szrj     case EXPR_CONSTR:
283238fd1498Szrj     case TYPE_CONSTR:
283338fd1498Szrj     case ICONV_CONSTR:
283438fd1498Szrj     case DEDUCT_CONSTR:
283538fd1498Szrj     case EXCEPT_CONSTR:
283638fd1498Szrj     case PARM_CONSTR:
283738fd1498Szrj     case CONJ_CONSTR:
283838fd1498Szrj     case DISJ_CONSTR:
283938fd1498Szrj       pp_cxx_constraint (cxx_pp, t);
284038fd1498Szrj       break;
284138fd1498Szrj 
284238fd1498Szrj     case PLACEHOLDER_EXPR:
284338fd1498Szrj       pp_string (pp, M_("*this"));
284438fd1498Szrj       break;
284538fd1498Szrj 
284638fd1498Szrj     case TREE_LIST:
284738fd1498Szrj       dump_expr_list (pp, t, flags);
284838fd1498Szrj       break;
284938fd1498Szrj 
285038fd1498Szrj       /*  This list is incomplete, but should suffice for now.
285138fd1498Szrj 	  It is very important that `sorry' does not call
285238fd1498Szrj 	  `report_error_function'.  That could cause an infinite loop.  */
285338fd1498Szrj     default:
285438fd1498Szrj       pp_unsupported_tree (pp, t);
285538fd1498Szrj       /* Fall through.  */
285638fd1498Szrj     case ERROR_MARK:
285738fd1498Szrj       pp_string (pp, M_("<expression error>"));
285838fd1498Szrj       break;
285938fd1498Szrj     }
286038fd1498Szrj }
286138fd1498Szrj 
286238fd1498Szrj static void
dump_binary_op(cxx_pretty_printer * pp,const char * opstring,tree t,int flags)286338fd1498Szrj dump_binary_op (cxx_pretty_printer *pp, const char *opstring, tree t,
286438fd1498Szrj                 int flags)
286538fd1498Szrj {
286638fd1498Szrj   pp_cxx_left_paren (pp);
286738fd1498Szrj   dump_expr (pp, TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
286838fd1498Szrj   pp_cxx_whitespace (pp);
286938fd1498Szrj   if (opstring)
287038fd1498Szrj     pp_cxx_ws_string (pp, opstring);
287138fd1498Szrj   else
287238fd1498Szrj     pp_string (pp, M_("<unknown operator>"));
287338fd1498Szrj   pp_cxx_whitespace (pp);
287438fd1498Szrj   dump_expr (pp, TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
287538fd1498Szrj   pp_cxx_right_paren (pp);
287638fd1498Szrj }
287738fd1498Szrj 
287838fd1498Szrj static void
dump_unary_op(cxx_pretty_printer * pp,const char * opstring,tree t,int flags)287938fd1498Szrj dump_unary_op (cxx_pretty_printer *pp, const char *opstring, tree t, int flags)
288038fd1498Szrj {
288138fd1498Szrj   if (flags & TFF_EXPR_IN_PARENS)
288238fd1498Szrj     pp_cxx_left_paren (pp);
288338fd1498Szrj   pp_cxx_ws_string (pp, opstring);
288438fd1498Szrj   dump_expr (pp, TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
288538fd1498Szrj   if (flags & TFF_EXPR_IN_PARENS)
288638fd1498Szrj     pp_cxx_right_paren (pp);
288738fd1498Szrj }
288838fd1498Szrj 
288938fd1498Szrj static void
reinit_cxx_pp(void)289038fd1498Szrj reinit_cxx_pp (void)
289138fd1498Szrj {
289238fd1498Szrj   pp_clear_output_area (cxx_pp);
289338fd1498Szrj   cxx_pp->padding = pp_none;
289438fd1498Szrj   pp_indentation (cxx_pp) = 0;
289538fd1498Szrj   pp_needs_newline (cxx_pp) = false;
289638fd1498Szrj   cxx_pp->enclosing_scope = current_function_decl;
289738fd1498Szrj }
289838fd1498Szrj 
289938fd1498Szrj /* Same as pp_formatted_text, except the return string is a separate
290038fd1498Szrj    copy and has a GGC storage duration, e.g. an indefinite lifetime.  */
290138fd1498Szrj 
290238fd1498Szrj inline const char *
pp_ggc_formatted_text(pretty_printer * pp)290338fd1498Szrj pp_ggc_formatted_text (pretty_printer *pp)
290438fd1498Szrj {
290538fd1498Szrj   return ggc_strdup (pp_formatted_text (pp));
290638fd1498Szrj }
290738fd1498Szrj 
290838fd1498Szrj /* Exported interface to stringifying types, exprs and decls under TFF_*
290938fd1498Szrj    control.  */
291038fd1498Szrj 
291138fd1498Szrj const char *
type_as_string(tree typ,int flags)291238fd1498Szrj type_as_string (tree typ, int flags)
291338fd1498Szrj {
291438fd1498Szrj   reinit_cxx_pp ();
291538fd1498Szrj   pp_translate_identifiers (cxx_pp) = false;
291638fd1498Szrj   dump_type (cxx_pp, typ, flags);
291738fd1498Szrj   return pp_ggc_formatted_text (cxx_pp);
291838fd1498Szrj }
291938fd1498Szrj 
292038fd1498Szrj const char *
type_as_string_translate(tree typ,int flags)292138fd1498Szrj type_as_string_translate (tree typ, int flags)
292238fd1498Szrj {
292338fd1498Szrj   reinit_cxx_pp ();
292438fd1498Szrj   dump_type (cxx_pp, typ, flags);
292538fd1498Szrj   return pp_ggc_formatted_text (cxx_pp);
292638fd1498Szrj }
292738fd1498Szrj 
292838fd1498Szrj const char *
expr_as_string(tree decl,int flags)292938fd1498Szrj expr_as_string (tree decl, int flags)
293038fd1498Szrj {
293138fd1498Szrj   reinit_cxx_pp ();
293238fd1498Szrj   pp_translate_identifiers (cxx_pp) = false;
293338fd1498Szrj   dump_expr (cxx_pp, decl, flags);
293438fd1498Szrj   return pp_ggc_formatted_text (cxx_pp);
293538fd1498Szrj }
293638fd1498Szrj 
293738fd1498Szrj /* Wrap decl_as_string with options appropriate for dwarf.  */
293838fd1498Szrj 
293938fd1498Szrj const char *
decl_as_dwarf_string(tree decl,int flags)294038fd1498Szrj decl_as_dwarf_string (tree decl, int flags)
294138fd1498Szrj {
294238fd1498Szrj   const char *name;
294338fd1498Szrj   /* Curiously, reinit_cxx_pp doesn't reset the flags field, so setting the flag
294438fd1498Szrj      here will be adequate to get the desired behavior.  */
294538fd1498Szrj   cxx_pp->flags |= pp_c_flag_gnu_v3;
294638fd1498Szrj   name = decl_as_string (decl, flags);
294738fd1498Szrj   /* Subsequent calls to the pretty printer shouldn't use this style.  */
294838fd1498Szrj   cxx_pp->flags &= ~pp_c_flag_gnu_v3;
294938fd1498Szrj   return name;
295038fd1498Szrj }
295138fd1498Szrj 
295238fd1498Szrj const char *
decl_as_string(tree decl,int flags)295338fd1498Szrj decl_as_string (tree decl, int flags)
295438fd1498Szrj {
295538fd1498Szrj   reinit_cxx_pp ();
295638fd1498Szrj   pp_translate_identifiers (cxx_pp) = false;
295738fd1498Szrj   dump_decl (cxx_pp, decl, flags);
295838fd1498Szrj   return pp_ggc_formatted_text (cxx_pp);
295938fd1498Szrj }
296038fd1498Szrj 
296138fd1498Szrj const char *
decl_as_string_translate(tree decl,int flags)296238fd1498Szrj decl_as_string_translate (tree decl, int flags)
296338fd1498Szrj {
296438fd1498Szrj   reinit_cxx_pp ();
296538fd1498Szrj   dump_decl (cxx_pp, decl, flags);
296638fd1498Szrj   return pp_ggc_formatted_text (cxx_pp);
296738fd1498Szrj }
296838fd1498Szrj 
296938fd1498Szrj /* Wrap lang_decl_name with options appropriate for dwarf.  */
297038fd1498Szrj 
297138fd1498Szrj const char *
lang_decl_dwarf_name(tree decl,int v,bool translate)297238fd1498Szrj lang_decl_dwarf_name (tree decl, int v, bool translate)
297338fd1498Szrj {
297438fd1498Szrj   const char *name;
297538fd1498Szrj   /* Curiously, reinit_cxx_pp doesn't reset the flags field, so setting the flag
297638fd1498Szrj      here will be adequate to get the desired behavior.  */
297738fd1498Szrj   cxx_pp->flags |= pp_c_flag_gnu_v3;
297838fd1498Szrj   name = lang_decl_name (decl, v, translate);
297938fd1498Szrj   /* Subsequent calls to the pretty printer shouldn't use this style.  */
298038fd1498Szrj   cxx_pp->flags &= ~pp_c_flag_gnu_v3;
298138fd1498Szrj   return name;
298238fd1498Szrj }
298338fd1498Szrj 
298438fd1498Szrj /* Generate the three forms of printable names for cxx_printable_name.  */
298538fd1498Szrj 
298638fd1498Szrj const char *
lang_decl_name(tree decl,int v,bool translate)298738fd1498Szrj lang_decl_name (tree decl, int v, bool translate)
298838fd1498Szrj {
298938fd1498Szrj   if (v >= 2)
299038fd1498Szrj     return (translate
299138fd1498Szrj 	    ? decl_as_string_translate (decl, TFF_DECL_SPECIFIERS)
299238fd1498Szrj 	    : decl_as_string (decl, TFF_DECL_SPECIFIERS));
299338fd1498Szrj 
299438fd1498Szrj   reinit_cxx_pp ();
299538fd1498Szrj   pp_translate_identifiers (cxx_pp) = translate;
299638fd1498Szrj   if (v == 1
299738fd1498Szrj       && (DECL_CLASS_SCOPE_P (decl)
299838fd1498Szrj 	  || (DECL_NAMESPACE_SCOPE_P (decl)
299938fd1498Szrj 	      && CP_DECL_CONTEXT (decl) != global_namespace)))
300038fd1498Szrj     {
300138fd1498Szrj       dump_type (cxx_pp, CP_DECL_CONTEXT (decl), TFF_PLAIN_IDENTIFIER);
300238fd1498Szrj       pp_cxx_colon_colon (cxx_pp);
300338fd1498Szrj     }
300438fd1498Szrj 
300538fd1498Szrj   if (TREE_CODE (decl) == FUNCTION_DECL)
300638fd1498Szrj     dump_function_name (cxx_pp, decl, TFF_PLAIN_IDENTIFIER);
300738fd1498Szrj   else if ((DECL_NAME (decl) == NULL_TREE)
300838fd1498Szrj            && TREE_CODE (decl) == NAMESPACE_DECL)
300938fd1498Szrj     dump_decl (cxx_pp, decl, TFF_PLAIN_IDENTIFIER | TFF_UNQUALIFIED_NAME);
301038fd1498Szrj   else
301138fd1498Szrj     dump_decl (cxx_pp, DECL_NAME (decl), TFF_PLAIN_IDENTIFIER);
301238fd1498Szrj 
301338fd1498Szrj   return pp_ggc_formatted_text (cxx_pp);
301438fd1498Szrj }
301538fd1498Szrj 
301638fd1498Szrj /* Return the location of a tree passed to %+ formats.  */
301738fd1498Szrj 
301838fd1498Szrj location_t
location_of(tree t)301938fd1498Szrj location_of (tree t)
302038fd1498Szrj {
302138fd1498Szrj   if (TYPE_P (t))
302238fd1498Szrj     {
302338fd1498Szrj       t = TYPE_MAIN_DECL (t);
302438fd1498Szrj       if (t == NULL_TREE)
302538fd1498Szrj 	return input_location;
302638fd1498Szrj     }
302738fd1498Szrj   else if (TREE_CODE (t) == OVERLOAD)
302838fd1498Szrj     t = OVL_FIRST (t);
302938fd1498Szrj 
303038fd1498Szrj   if (DECL_P (t))
303138fd1498Szrj     return DECL_SOURCE_LOCATION (t);
303238fd1498Szrj   if (TREE_CODE (t) == DEFAULT_ARG)
303338fd1498Szrj     return defarg_location (t);
303438fd1498Szrj   return EXPR_LOC_OR_LOC (t, input_location);
303538fd1498Szrj }
303638fd1498Szrj 
303738fd1498Szrj /* Now the interfaces from error et al to dump_type et al. Each takes an
303838fd1498Szrj    on/off VERBOSE flag and supply the appropriate TFF_ flags to a dump_
303938fd1498Szrj    function.  */
304038fd1498Szrj 
304138fd1498Szrj static const char *
decl_to_string(tree decl,int verbose)304238fd1498Szrj decl_to_string (tree decl, int verbose)
304338fd1498Szrj {
304438fd1498Szrj   int flags = 0;
304538fd1498Szrj 
304638fd1498Szrj   if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == RECORD_TYPE
304738fd1498Szrj       || TREE_CODE (decl) == UNION_TYPE || TREE_CODE (decl) == ENUMERAL_TYPE)
304838fd1498Szrj     flags = TFF_CLASS_KEY_OR_ENUM;
304938fd1498Szrj   if (verbose)
305038fd1498Szrj     flags |= TFF_DECL_SPECIFIERS;
305138fd1498Szrj   else if (TREE_CODE (decl) == FUNCTION_DECL)
305238fd1498Szrj     flags |= TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE;
305338fd1498Szrj   flags |= TFF_TEMPLATE_HEADER;
305438fd1498Szrj 
305538fd1498Szrj   reinit_cxx_pp ();
305638fd1498Szrj   dump_decl (cxx_pp, decl, flags);
305738fd1498Szrj   return pp_ggc_formatted_text (cxx_pp);
305838fd1498Szrj }
305938fd1498Szrj 
306038fd1498Szrj static const char *
expr_to_string(tree decl)306138fd1498Szrj expr_to_string (tree decl)
306238fd1498Szrj {
306338fd1498Szrj   reinit_cxx_pp ();
306438fd1498Szrj   dump_expr (cxx_pp, decl, 0);
306538fd1498Szrj   return pp_ggc_formatted_text (cxx_pp);
306638fd1498Szrj }
306738fd1498Szrj 
306838fd1498Szrj static const char *
fndecl_to_string(tree fndecl,int verbose)306938fd1498Szrj fndecl_to_string (tree fndecl, int verbose)
307038fd1498Szrj {
307138fd1498Szrj   int flags;
307238fd1498Szrj 
307338fd1498Szrj   flags = TFF_EXCEPTION_SPECIFICATION | TFF_DECL_SPECIFIERS
307438fd1498Szrj     | TFF_TEMPLATE_HEADER;
307538fd1498Szrj   if (verbose)
307638fd1498Szrj     flags |= TFF_FUNCTION_DEFAULT_ARGUMENTS;
307738fd1498Szrj   reinit_cxx_pp ();
307838fd1498Szrj   dump_decl (cxx_pp, fndecl, flags);
307938fd1498Szrj   return pp_ggc_formatted_text (cxx_pp);
308038fd1498Szrj }
308138fd1498Szrj 
308238fd1498Szrj 
308338fd1498Szrj static const char *
code_to_string(enum tree_code c)308438fd1498Szrj code_to_string (enum tree_code c)
308538fd1498Szrj {
308638fd1498Szrj   return get_tree_code_name (c);
308738fd1498Szrj }
308838fd1498Szrj 
308938fd1498Szrj const char *
language_to_string(enum languages c)309038fd1498Szrj language_to_string (enum languages c)
309138fd1498Szrj {
309238fd1498Szrj   switch (c)
309338fd1498Szrj     {
309438fd1498Szrj     case lang_c:
309538fd1498Szrj       return "C";
309638fd1498Szrj 
309738fd1498Szrj     case lang_cplusplus:
309838fd1498Szrj       return "C++";
309938fd1498Szrj 
310038fd1498Szrj     default:
310138fd1498Szrj       gcc_unreachable ();
310238fd1498Szrj     }
310338fd1498Szrj   return NULL;
310438fd1498Szrj }
310538fd1498Szrj 
310638fd1498Szrj /* Return the proper printed version of a parameter to a C++ function.  */
310738fd1498Szrj 
310838fd1498Szrj static const char *
parm_to_string(int p)310938fd1498Szrj parm_to_string (int p)
311038fd1498Szrj {
311138fd1498Szrj   reinit_cxx_pp ();
311238fd1498Szrj   if (p < 0)
311338fd1498Szrj     pp_string (cxx_pp, "'this'");
311438fd1498Szrj   else
311538fd1498Szrj     pp_decimal_int (cxx_pp, p + 1);
311638fd1498Szrj   return pp_ggc_formatted_text (cxx_pp);
311738fd1498Szrj }
311838fd1498Szrj 
311938fd1498Szrj static const char *
op_to_string(bool assop,enum tree_code p)312038fd1498Szrj op_to_string (bool assop, enum tree_code p)
312138fd1498Szrj {
312238fd1498Szrj   tree id = ovl_op_identifier (assop, p);
312338fd1498Szrj   return id ? IDENTIFIER_POINTER (id) : M_("<unknown>");
312438fd1498Szrj }
312538fd1498Szrj 
312638fd1498Szrj /* Return a GC-allocated representation of type TYP, with verbosity VERBOSE.
312738fd1498Szrj 
312838fd1498Szrj    If QUOTE is non-NULL and if *QUOTE is true, then quotes are added to the
312938fd1498Szrj    string in appropriate places, and *QUOTE is written to with false
313038fd1498Szrj    to suppress pp_format's trailing close quote so that e.g.
313138fd1498Szrj      foo_typedef {aka underlying_foo} {enum}
313238fd1498Szrj    can be printed by "%qT" as:
313338fd1498Szrj      `foo_typedef' {aka `underlying_foo'} {enum}
313438fd1498Szrj    rather than:
313538fd1498Szrj      `foo_typedef {aka underlying_foo} {enum}'
313638fd1498Szrj    When adding such quotes, if POSTPROCESSED is true (for handling %H and %I)
313738fd1498Szrj    then a leading open quote will be added, whereas if POSTPROCESSED is false
313838fd1498Szrj    (for handling %T) then any leading quote has already been added by
313938fd1498Szrj    pp_format, or is not needed due to QUOTE being NULL (for template arguments
314038fd1498Szrj    within %H and %I).
314138fd1498Szrj 
314238fd1498Szrj    SHOW_COLOR is used to determine the colorization of any quotes that
314338fd1498Szrj    are added.  */
314438fd1498Szrj 
314538fd1498Szrj static const char *
type_to_string(tree typ,int verbose,bool postprocessed,bool * quote,bool show_color)314638fd1498Szrj type_to_string (tree typ, int verbose, bool postprocessed, bool *quote,
314738fd1498Szrj 		bool show_color)
314838fd1498Szrj {
314938fd1498Szrj   int flags = 0;
315038fd1498Szrj   if (verbose)
315138fd1498Szrj     flags |= TFF_CLASS_KEY_OR_ENUM;
315238fd1498Szrj   flags |= TFF_TEMPLATE_HEADER;
315338fd1498Szrj 
315438fd1498Szrj   reinit_cxx_pp ();
315538fd1498Szrj 
315638fd1498Szrj   if (postprocessed && quote && *quote)
315738fd1498Szrj     pp_begin_quote (cxx_pp, show_color);
315838fd1498Szrj 
315938fd1498Szrj   struct obstack *ob = pp_buffer (cxx_pp)->obstack;
316038fd1498Szrj   int type_start, type_len;
316138fd1498Szrj   type_start = obstack_object_size (ob);
316238fd1498Szrj 
316338fd1498Szrj   dump_type (cxx_pp, typ, flags);
316438fd1498Szrj 
316538fd1498Szrj   /* Remember the end of the initial dump.  */
316638fd1498Szrj   type_len = obstack_object_size (ob) - type_start;
316738fd1498Szrj 
316838fd1498Szrj   /* If we're printing a type that involves typedefs, also print the
316938fd1498Szrj      stripped version.  But sometimes the stripped version looks
317038fd1498Szrj      exactly the same, so we don't want it after all.  To avoid printing
317138fd1498Szrj      it in that case, we play ugly obstack games.  */
317238fd1498Szrj   if (typ && TYPE_P (typ) && typ != TYPE_CANONICAL (typ)
317338fd1498Szrj       && !uses_template_parms (typ))
317438fd1498Szrj     {
317538fd1498Szrj       int aka_start, aka_len; char *p;
317638fd1498Szrj       tree aka = strip_typedefs (typ);
317738fd1498Szrj       if (quote && *quote)
317838fd1498Szrj 	pp_end_quote (cxx_pp, show_color);
317938fd1498Szrj       pp_string (cxx_pp, " {aka");
318038fd1498Szrj       pp_cxx_whitespace (cxx_pp);
318138fd1498Szrj       if (quote && *quote)
318238fd1498Szrj 	pp_begin_quote (cxx_pp, show_color);
318338fd1498Szrj       /* And remember the start of the aka dump.  */
318438fd1498Szrj       aka_start = obstack_object_size (ob);
318538fd1498Szrj       dump_type (cxx_pp, aka, flags);
318638fd1498Szrj       aka_len = obstack_object_size (ob) - aka_start;
318738fd1498Szrj       if (quote && *quote)
318838fd1498Szrj 	pp_end_quote (cxx_pp, show_color);
318938fd1498Szrj       pp_right_brace (cxx_pp);
319038fd1498Szrj       p = (char*)obstack_base (ob);
319138fd1498Szrj       /* If they are identical, cut off the aka by unwinding the obstack.  */
319238fd1498Szrj       if (type_len == aka_len
319338fd1498Szrj 	  && memcmp (p + type_start, p+aka_start, type_len) == 0)
319438fd1498Szrj 	{
319538fd1498Szrj 	  /* We can't add a '\0' here, since we may be adding a closing quote
319638fd1498Szrj 	     below, and it would be hidden by the '\0'.
319738fd1498Szrj 	     Instead, manually unwind the current object within the obstack
319838fd1498Szrj 	     so that the insertion point is at the end of the type, before
319938fd1498Szrj 	     the "' {aka".  */
320038fd1498Szrj 	  int delta = type_start + type_len - obstack_object_size (ob);
320138fd1498Szrj 	  gcc_assert (delta <= 0);
320238fd1498Szrj 	  obstack_blank_fast (ob, delta);
320338fd1498Szrj 	}
320438fd1498Szrj       else
320538fd1498Szrj 	if (quote)
320638fd1498Szrj 	  /* No further closing quotes are needed.  */
320738fd1498Szrj 	  *quote = false;
320838fd1498Szrj     }
320938fd1498Szrj 
321038fd1498Szrj   if (quote && *quote)
321138fd1498Szrj     {
321238fd1498Szrj       pp_end_quote (cxx_pp, show_color);
321338fd1498Szrj       *quote = false;
321438fd1498Szrj     }
321538fd1498Szrj   return pp_ggc_formatted_text (cxx_pp);
321638fd1498Szrj }
321738fd1498Szrj 
321838fd1498Szrj static const char *
args_to_string(tree p,int verbose)321938fd1498Szrj args_to_string (tree p, int verbose)
322038fd1498Szrj {
322138fd1498Szrj   int flags = 0;
322238fd1498Szrj   if (verbose)
322338fd1498Szrj     flags |= TFF_CLASS_KEY_OR_ENUM;
322438fd1498Szrj 
322538fd1498Szrj   if (p == NULL_TREE)
322638fd1498Szrj     return "";
322738fd1498Szrj 
322838fd1498Szrj   if (TYPE_P (TREE_VALUE (p)))
322938fd1498Szrj     return type_as_string_translate (p, flags);
323038fd1498Szrj 
323138fd1498Szrj   reinit_cxx_pp ();
323238fd1498Szrj   for (; p; p = TREE_CHAIN (p))
323338fd1498Szrj     {
323438fd1498Szrj       if (null_node_p (TREE_VALUE (p)))
323538fd1498Szrj 	pp_cxx_ws_string (cxx_pp, "NULL");
323638fd1498Szrj       else
323738fd1498Szrj 	dump_type (cxx_pp, error_type (TREE_VALUE (p)), flags);
323838fd1498Szrj       if (TREE_CHAIN (p))
323938fd1498Szrj 	pp_separate_with_comma (cxx_pp);
324038fd1498Szrj     }
324138fd1498Szrj   return pp_ggc_formatted_text (cxx_pp);
324238fd1498Szrj }
324338fd1498Szrj 
324438fd1498Szrj /* Pretty-print a deduction substitution (from deduction_tsubst_fntype).  P
324538fd1498Szrj    is a TREE_LIST with purpose the TEMPLATE_DECL, value the template
324638fd1498Szrj    arguments.  */
324738fd1498Szrj 
324838fd1498Szrj static const char *
subst_to_string(tree p)324938fd1498Szrj subst_to_string (tree p)
325038fd1498Szrj {
325138fd1498Szrj   tree decl = TREE_PURPOSE (p);
325238fd1498Szrj   tree targs = TREE_VALUE (p);
325338fd1498Szrj   tree tparms = DECL_TEMPLATE_PARMS (decl);
325438fd1498Szrj   int flags = (TFF_DECL_SPECIFIERS|TFF_TEMPLATE_HEADER
325538fd1498Szrj 	       |TFF_NO_TEMPLATE_BINDINGS);
325638fd1498Szrj 
325738fd1498Szrj   if (p == NULL_TREE)
325838fd1498Szrj     return "";
325938fd1498Szrj 
326038fd1498Szrj   reinit_cxx_pp ();
326138fd1498Szrj   dump_template_decl (cxx_pp, TREE_PURPOSE (p), flags);
326238fd1498Szrj   dump_substitution (cxx_pp, NULL, tparms, targs, /*flags=*/0);
326338fd1498Szrj   return pp_ggc_formatted_text (cxx_pp);
326438fd1498Szrj }
326538fd1498Szrj 
326638fd1498Szrj static const char *
cv_to_string(tree p,int v)326738fd1498Szrj cv_to_string (tree p, int v)
326838fd1498Szrj {
326938fd1498Szrj   reinit_cxx_pp ();
327038fd1498Szrj   cxx_pp->padding = v ? pp_before : pp_none;
327138fd1498Szrj   pp_cxx_cv_qualifier_seq (cxx_pp, p);
327238fd1498Szrj   return pp_ggc_formatted_text (cxx_pp);
327338fd1498Szrj }
327438fd1498Szrj 
327538fd1498Szrj static const char *
eh_spec_to_string(tree p,int)327638fd1498Szrj eh_spec_to_string (tree p, int /*v*/)
327738fd1498Szrj {
327838fd1498Szrj   int flags = 0;
327938fd1498Szrj   reinit_cxx_pp ();
328038fd1498Szrj   dump_exception_spec (cxx_pp, p, flags);
328138fd1498Szrj   return pp_ggc_formatted_text (cxx_pp);
328238fd1498Szrj }
328338fd1498Szrj 
328438fd1498Szrj /* Langhook for print_error_function.  */
328538fd1498Szrj void
cxx_print_error_function(diagnostic_context * context,const char * file,diagnostic_info * diagnostic)328638fd1498Szrj cxx_print_error_function (diagnostic_context *context, const char *file,
328738fd1498Szrj 			  diagnostic_info *diagnostic)
328838fd1498Szrj {
3289*58e805e6Szrj   char *prefix;
3290*58e805e6Szrj   if (file)
3291*58e805e6Szrj     prefix = xstrdup (file);
3292*58e805e6Szrj   else
3293*58e805e6Szrj     prefix = NULL;
329438fd1498Szrj   lhd_print_error_function (context, file, diagnostic);
3295*58e805e6Szrj   pp_set_prefix (context->printer, prefix);
329638fd1498Szrj   maybe_print_instantiation_context (context);
329738fd1498Szrj }
329838fd1498Szrj 
329938fd1498Szrj static void
cp_diagnostic_starter(diagnostic_context * context,diagnostic_info * diagnostic)330038fd1498Szrj cp_diagnostic_starter (diagnostic_context *context,
330138fd1498Szrj 		       diagnostic_info *diagnostic)
330238fd1498Szrj {
330338fd1498Szrj   diagnostic_report_current_module (context, diagnostic_location (diagnostic));
330438fd1498Szrj   cp_print_error_function (context, diagnostic);
330538fd1498Szrj   maybe_print_instantiation_context (context);
330638fd1498Szrj   maybe_print_constexpr_context (context);
330738fd1498Szrj   pp_set_prefix (context->printer, diagnostic_build_prefix (context,
330838fd1498Szrj 								 diagnostic));
330938fd1498Szrj }
331038fd1498Szrj 
331138fd1498Szrj /* Print current function onto BUFFER, in the process of reporting
331238fd1498Szrj    a diagnostic message.  Called from cp_diagnostic_starter.  */
331338fd1498Szrj static void
cp_print_error_function(diagnostic_context * context,diagnostic_info * diagnostic)331438fd1498Szrj cp_print_error_function (diagnostic_context *context,
331538fd1498Szrj 			 diagnostic_info *diagnostic)
331638fd1498Szrj {
331738fd1498Szrj   /* If we are in an instantiation context, current_function_decl is likely
331838fd1498Szrj      to be wrong, so just rely on print_instantiation_full_context.  */
331938fd1498Szrj   if (current_instantiation ())
332038fd1498Szrj     return;
332138fd1498Szrj   if (diagnostic_last_function_changed (context, diagnostic))
332238fd1498Szrj     {
3323*58e805e6Szrj       char *old_prefix = pp_take_prefix (context->printer);
332438fd1498Szrj       const char *file = LOCATION_FILE (diagnostic_location (diagnostic));
332538fd1498Szrj       tree abstract_origin = diagnostic_abstract_origin (diagnostic);
332638fd1498Szrj       char *new_prefix = (file && abstract_origin == NULL)
332738fd1498Szrj 			 ? file_name_as_prefix (context, file) : NULL;
332838fd1498Szrj 
332938fd1498Szrj       pp_set_prefix (context->printer, new_prefix);
333038fd1498Szrj 
333138fd1498Szrj       if (current_function_decl == NULL)
333238fd1498Szrj 	pp_string (context->printer, _("At global scope:"));
333338fd1498Szrj       else
333438fd1498Szrj 	{
333538fd1498Szrj 	  tree fndecl, ao;
333638fd1498Szrj 
333738fd1498Szrj 	  if (abstract_origin)
333838fd1498Szrj 	    {
333938fd1498Szrj 	      ao = BLOCK_ABSTRACT_ORIGIN (abstract_origin);
334038fd1498Szrj 	      while (TREE_CODE (ao) == BLOCK
334138fd1498Szrj 		     && BLOCK_ABSTRACT_ORIGIN (ao)
334238fd1498Szrj 		     && BLOCK_ABSTRACT_ORIGIN (ao) != ao)
334338fd1498Szrj 		ao = BLOCK_ABSTRACT_ORIGIN (ao);
334438fd1498Szrj 	      gcc_assert (TREE_CODE (ao) == FUNCTION_DECL);
334538fd1498Szrj 	      fndecl = ao;
334638fd1498Szrj 	    }
334738fd1498Szrj 	  else
334838fd1498Szrj 	    fndecl = current_function_decl;
334938fd1498Szrj 
335038fd1498Szrj 	  pp_printf (context->printer, function_category (fndecl),
335138fd1498Szrj 		     cxx_printable_name_translate (fndecl, 2));
335238fd1498Szrj 
335338fd1498Szrj 	  while (abstract_origin)
335438fd1498Szrj 	    {
335538fd1498Szrj 	      location_t *locus;
335638fd1498Szrj 	      tree block = abstract_origin;
335738fd1498Szrj 
335838fd1498Szrj 	      locus = &BLOCK_SOURCE_LOCATION (block);
335938fd1498Szrj 	      fndecl = NULL;
336038fd1498Szrj 	      block = BLOCK_SUPERCONTEXT (block);
336138fd1498Szrj 	      while (block && TREE_CODE (block) == BLOCK
336238fd1498Szrj 		     && BLOCK_ABSTRACT_ORIGIN (block))
336338fd1498Szrj 		{
336438fd1498Szrj 		  ao = BLOCK_ABSTRACT_ORIGIN (block);
336538fd1498Szrj 
336638fd1498Szrj 		  while (TREE_CODE (ao) == BLOCK
336738fd1498Szrj 			 && BLOCK_ABSTRACT_ORIGIN (ao)
336838fd1498Szrj 			 && BLOCK_ABSTRACT_ORIGIN (ao) != ao)
336938fd1498Szrj 		    ao = BLOCK_ABSTRACT_ORIGIN (ao);
337038fd1498Szrj 
337138fd1498Szrj 		  if (TREE_CODE (ao) == FUNCTION_DECL)
337238fd1498Szrj 		    {
337338fd1498Szrj 		      fndecl = ao;
337438fd1498Szrj 		      break;
337538fd1498Szrj 		    }
337638fd1498Szrj 		  else if (TREE_CODE (ao) != BLOCK)
337738fd1498Szrj 		    break;
337838fd1498Szrj 
337938fd1498Szrj 		  block = BLOCK_SUPERCONTEXT (block);
338038fd1498Szrj 		}
338138fd1498Szrj 	      if (fndecl)
338238fd1498Szrj 		abstract_origin = block;
338338fd1498Szrj 	      else
338438fd1498Szrj 		{
338538fd1498Szrj 		  while (block && TREE_CODE (block) == BLOCK)
338638fd1498Szrj 		    block = BLOCK_SUPERCONTEXT (block);
338738fd1498Szrj 
338838fd1498Szrj 		  if (block && TREE_CODE (block) == FUNCTION_DECL)
338938fd1498Szrj 		    fndecl = block;
339038fd1498Szrj 		  abstract_origin = NULL;
339138fd1498Szrj 		}
339238fd1498Szrj 	      if (fndecl)
339338fd1498Szrj 		{
339438fd1498Szrj 		  expanded_location s = expand_location (*locus);
339538fd1498Szrj 		  pp_character (context->printer, ',');
339638fd1498Szrj 		  pp_newline (context->printer);
339738fd1498Szrj 		  if (s.file != NULL)
339838fd1498Szrj 		    {
339938fd1498Szrj 		      if (context->show_column && s.column != 0)
340038fd1498Szrj 			pp_printf (context->printer,
340138fd1498Szrj 				   _("    inlined from %qs at %r%s:%d:%d%R"),
340238fd1498Szrj 				   cxx_printable_name_translate (fndecl, 2),
340338fd1498Szrj 				   "locus", s.file, s.line, s.column);
340438fd1498Szrj 		      else
340538fd1498Szrj 			pp_printf (context->printer,
340638fd1498Szrj 				   _("    inlined from %qs at %r%s:%d%R"),
340738fd1498Szrj 				   cxx_printable_name_translate (fndecl, 2),
340838fd1498Szrj 				   "locus", s.file, s.line);
340938fd1498Szrj 
341038fd1498Szrj 		    }
341138fd1498Szrj 		  else
341238fd1498Szrj 		    pp_printf (context->printer, _("    inlined from %qs"),
341338fd1498Szrj 			       cxx_printable_name_translate (fndecl, 2));
341438fd1498Szrj 		}
341538fd1498Szrj 	    }
341638fd1498Szrj 	  pp_character (context->printer, ':');
341738fd1498Szrj 	}
341838fd1498Szrj       pp_newline (context->printer);
341938fd1498Szrj 
342038fd1498Szrj       diagnostic_set_last_function (context, diagnostic);
342138fd1498Szrj       pp_destroy_prefix (context->printer);
342238fd1498Szrj       context->printer->prefix = old_prefix;
342338fd1498Szrj     }
342438fd1498Szrj }
342538fd1498Szrj 
342638fd1498Szrj /* Returns a description of FUNCTION using standard terminology.  The
342738fd1498Szrj    result is a format string of the form "In CATEGORY %qs".  */
342838fd1498Szrj static const char *
function_category(tree fn)342938fd1498Szrj function_category (tree fn)
343038fd1498Szrj {
343138fd1498Szrj   /* We can get called from the middle-end for diagnostics of function
343238fd1498Szrj      clones.  Make sure we have language specific information before
343338fd1498Szrj      dereferencing it.  */
343438fd1498Szrj   if (DECL_LANG_SPECIFIC (STRIP_TEMPLATE (fn))
343538fd1498Szrj       && DECL_FUNCTION_MEMBER_P (fn))
343638fd1498Szrj     {
343738fd1498Szrj       if (DECL_STATIC_FUNCTION_P (fn))
343838fd1498Szrj 	return _("In static member function %qs");
343938fd1498Szrj       else if (DECL_COPY_CONSTRUCTOR_P (fn))
344038fd1498Szrj 	return _("In copy constructor %qs");
344138fd1498Szrj       else if (DECL_CONSTRUCTOR_P (fn))
344238fd1498Szrj 	return _("In constructor %qs");
344338fd1498Szrj       else if (DECL_DESTRUCTOR_P (fn))
344438fd1498Szrj 	return _("In destructor %qs");
344538fd1498Szrj       else if (LAMBDA_FUNCTION_P (fn))
344638fd1498Szrj 	return _("In lambda function");
344738fd1498Szrj       else
344838fd1498Szrj 	return _("In member function %qs");
344938fd1498Szrj     }
345038fd1498Szrj   else
345138fd1498Szrj     return _("In function %qs");
345238fd1498Szrj }
345338fd1498Szrj 
345438fd1498Szrj /* Report the full context of a current template instantiation,
345538fd1498Szrj    onto BUFFER.  */
345638fd1498Szrj static void
print_instantiation_full_context(diagnostic_context * context)345738fd1498Szrj print_instantiation_full_context (diagnostic_context *context)
345838fd1498Szrj {
345938fd1498Szrj   struct tinst_level *p = current_instantiation ();
346038fd1498Szrj   location_t location = input_location;
346138fd1498Szrj 
346238fd1498Szrj   if (p)
346338fd1498Szrj     {
346438fd1498Szrj       pp_verbatim (context->printer,
346538fd1498Szrj 		   p->list_p ()
346638fd1498Szrj 		   ? _("%s: In substitution of %qS:\n")
346738fd1498Szrj 		   : _("%s: In instantiation of %q#D:\n"),
346838fd1498Szrj 		   LOCATION_FILE (location),
346938fd1498Szrj 		   p->get_node ());
347038fd1498Szrj 
347138fd1498Szrj       location = p->locus;
347238fd1498Szrj       p = p->next;
347338fd1498Szrj     }
347438fd1498Szrj 
347538fd1498Szrj   print_instantiation_partial_context (context, p, location);
347638fd1498Szrj }
347738fd1498Szrj 
347838fd1498Szrj /* Helper function of print_instantiation_partial_context() that
347938fd1498Szrj    prints a single line of instantiation context.  */
348038fd1498Szrj 
348138fd1498Szrj static void
print_instantiation_partial_context_line(diagnostic_context * context,struct tinst_level * t,location_t loc,bool recursive_p)348238fd1498Szrj print_instantiation_partial_context_line (diagnostic_context *context,
348338fd1498Szrj 					  struct tinst_level *t,
348438fd1498Szrj 					  location_t loc, bool recursive_p)
348538fd1498Szrj {
348638fd1498Szrj   if (loc == UNKNOWN_LOCATION)
348738fd1498Szrj     return;
348838fd1498Szrj 
348938fd1498Szrj   expanded_location xloc = expand_location (loc);
349038fd1498Szrj 
349138fd1498Szrj   if (context->show_column)
349238fd1498Szrj     pp_verbatim (context->printer, _("%r%s:%d:%d:%R   "),
349338fd1498Szrj 		 "locus", xloc.file, xloc.line, xloc.column);
349438fd1498Szrj   else
349538fd1498Szrj     pp_verbatim (context->printer, _("%r%s:%d:%R   "),
349638fd1498Szrj 		 "locus", xloc.file, xloc.line);
349738fd1498Szrj 
349838fd1498Szrj   if (t != NULL)
349938fd1498Szrj     {
350038fd1498Szrj       if (t->list_p ())
350138fd1498Szrj 	pp_verbatim (context->printer,
350238fd1498Szrj 		     recursive_p
350338fd1498Szrj 		     ? _("recursively required by substitution of %qS\n")
350438fd1498Szrj 		     : _("required by substitution of %qS\n"),
350538fd1498Szrj 		     t->get_node ());
350638fd1498Szrj       else
350738fd1498Szrj 	pp_verbatim (context->printer,
350838fd1498Szrj 		     recursive_p
350938fd1498Szrj 		     ? _("recursively required from %q#D\n")
351038fd1498Szrj 		     : _("required from %q#D\n"),
351138fd1498Szrj 		     t->get_node ());
351238fd1498Szrj     }
351338fd1498Szrj   else
351438fd1498Szrj     {
351538fd1498Szrj       pp_verbatim (context->printer,
351638fd1498Szrj 		   recursive_p
351738fd1498Szrj 		   ? _("recursively required from here\n")
351838fd1498Szrj 		   : _("required from here\n"));
351938fd1498Szrj     }
352038fd1498Szrj }
352138fd1498Szrj 
352238fd1498Szrj /* Same as print_instantiation_full_context but less verbose.  */
352338fd1498Szrj 
352438fd1498Szrj static void
print_instantiation_partial_context(diagnostic_context * context,struct tinst_level * t0,location_t loc)352538fd1498Szrj print_instantiation_partial_context (diagnostic_context *context,
352638fd1498Szrj 				     struct tinst_level *t0, location_t loc)
352738fd1498Szrj {
352838fd1498Szrj   struct tinst_level *t;
352938fd1498Szrj   int n_total = 0;
353038fd1498Szrj   int n;
353138fd1498Szrj   location_t prev_loc = loc;
353238fd1498Szrj 
353338fd1498Szrj   for (t = t0; t != NULL; t = t->next)
353438fd1498Szrj     if (prev_loc != t->locus)
353538fd1498Szrj       {
353638fd1498Szrj 	prev_loc = t->locus;
353738fd1498Szrj 	n_total++;
353838fd1498Szrj       }
353938fd1498Szrj 
354038fd1498Szrj   t = t0;
354138fd1498Szrj 
354238fd1498Szrj   if (template_backtrace_limit
354338fd1498Szrj       && n_total > template_backtrace_limit)
354438fd1498Szrj     {
354538fd1498Szrj       int skip = n_total - template_backtrace_limit;
354638fd1498Szrj       int head = template_backtrace_limit / 2;
354738fd1498Szrj 
354838fd1498Szrj       /* Avoid skipping just 1.  If so, skip 2.  */
354938fd1498Szrj       if (skip == 1)
355038fd1498Szrj        {
355138fd1498Szrj          skip = 2;
355238fd1498Szrj          head = (template_backtrace_limit - 1) / 2;
355338fd1498Szrj        }
355438fd1498Szrj 
355538fd1498Szrj       for (n = 0; n < head; n++)
355638fd1498Szrj 	{
355738fd1498Szrj 	  gcc_assert (t != NULL);
355838fd1498Szrj 	  if (loc != t->locus)
355938fd1498Szrj 	    print_instantiation_partial_context_line (context, t, loc,
356038fd1498Szrj 						      /*recursive_p=*/false);
356138fd1498Szrj 	  loc = t->locus;
356238fd1498Szrj 	  t = t->next;
356338fd1498Szrj 	}
356438fd1498Szrj       if (t != NULL && skip > 0)
356538fd1498Szrj 	{
356638fd1498Szrj 	  expanded_location xloc;
356738fd1498Szrj 	  xloc = expand_location (loc);
356838fd1498Szrj 	  if (context->show_column)
356938fd1498Szrj 	    pp_verbatim (context->printer,
357038fd1498Szrj 			 _("%r%s:%d:%d:%R   [ skipping %d instantiation "
357138fd1498Szrj 			   "contexts, use -ftemplate-backtrace-limit=0 to "
357238fd1498Szrj 			   "disable ]\n"),
357338fd1498Szrj 			 "locus", xloc.file, xloc.line, xloc.column, skip);
357438fd1498Szrj 	  else
357538fd1498Szrj 	    pp_verbatim (context->printer,
357638fd1498Szrj 			 _("%r%s:%d:%R   [ skipping %d instantiation "
357738fd1498Szrj 			   "contexts, use -ftemplate-backtrace-limit=0 to "
357838fd1498Szrj 			   "disable ]\n"),
357938fd1498Szrj 			 "locus", xloc.file, xloc.line, skip);
358038fd1498Szrj 
358138fd1498Szrj 	  do {
358238fd1498Szrj 	    loc = t->locus;
358338fd1498Szrj 	    t = t->next;
358438fd1498Szrj 	  } while (t != NULL && --skip > 0);
358538fd1498Szrj 	}
358638fd1498Szrj     }
358738fd1498Szrj 
358838fd1498Szrj   while (t != NULL)
358938fd1498Szrj     {
359038fd1498Szrj       while (t->next != NULL && t->locus == t->next->locus)
359138fd1498Szrj 	{
359238fd1498Szrj 	  loc = t->locus;
359338fd1498Szrj 	  t = t->next;
359438fd1498Szrj 	}
359538fd1498Szrj       print_instantiation_partial_context_line (context, t, loc,
359638fd1498Szrj 						t->locus == loc);
359738fd1498Szrj       loc = t->locus;
359838fd1498Szrj       t = t->next;
359938fd1498Szrj     }
360038fd1498Szrj   print_instantiation_partial_context_line (context, NULL, loc,
360138fd1498Szrj 					    /*recursive_p=*/false);
360238fd1498Szrj }
360338fd1498Szrj 
360438fd1498Szrj /* Called from cp_thing to print the template context for an error.  */
360538fd1498Szrj static void
maybe_print_instantiation_context(diagnostic_context * context)360638fd1498Szrj maybe_print_instantiation_context (diagnostic_context *context)
360738fd1498Szrj {
360838fd1498Szrj   if (!problematic_instantiation_changed () || current_instantiation () == 0)
360938fd1498Szrj     return;
361038fd1498Szrj 
361138fd1498Szrj   record_last_problematic_instantiation ();
361238fd1498Szrj   print_instantiation_full_context (context);
361338fd1498Szrj }
361438fd1498Szrj 
361538fd1498Szrj /* Report what constexpr call(s) we're trying to expand, if any.  */
361638fd1498Szrj 
361738fd1498Szrj void
maybe_print_constexpr_context(diagnostic_context * context)361838fd1498Szrj maybe_print_constexpr_context (diagnostic_context *context)
361938fd1498Szrj {
362038fd1498Szrj   vec<tree> call_stack = cx_error_context ();
362138fd1498Szrj   unsigned ix;
362238fd1498Szrj   tree t;
362338fd1498Szrj 
362438fd1498Szrj   FOR_EACH_VEC_ELT (call_stack, ix, t)
362538fd1498Szrj     {
362638fd1498Szrj       expanded_location xloc = expand_location (EXPR_LOCATION (t));
362738fd1498Szrj       const char *s = expr_as_string (t, 0);
362838fd1498Szrj       if (context->show_column)
362938fd1498Szrj 	pp_verbatim (context->printer,
363038fd1498Szrj 		     _("%r%s:%d:%d:%R   in %<constexpr%> expansion of %qs"),
363138fd1498Szrj 		     "locus", xloc.file, xloc.line, xloc.column, s);
363238fd1498Szrj       else
363338fd1498Szrj 	pp_verbatim (context->printer,
363438fd1498Szrj 		     _("%r%s:%d:%R   in %<constexpr%> expansion of %qs"),
363538fd1498Szrj 		     "locus", xloc.file, xloc.line, s);
363638fd1498Szrj       pp_newline (context->printer);
363738fd1498Szrj     }
363838fd1498Szrj }
363938fd1498Szrj 
364038fd1498Szrj 
364138fd1498Szrj /* Return true iff TYPE_A and TYPE_B are template types that are
364238fd1498Szrj    meaningful to compare.  */
364338fd1498Szrj 
364438fd1498Szrj static bool
comparable_template_types_p(tree type_a,tree type_b)364538fd1498Szrj comparable_template_types_p (tree type_a, tree type_b)
364638fd1498Szrj {
364738fd1498Szrj   if (!CLASS_TYPE_P (type_a))
364838fd1498Szrj     return false;
364938fd1498Szrj   if (!CLASS_TYPE_P (type_b))
365038fd1498Szrj     return false;
365138fd1498Szrj 
365238fd1498Szrj   tree tinfo_a = TYPE_TEMPLATE_INFO (type_a);
365338fd1498Szrj   tree tinfo_b = TYPE_TEMPLATE_INFO (type_b);
365438fd1498Szrj   if (!tinfo_a || !tinfo_b)
365538fd1498Szrj     return false;
365638fd1498Szrj 
365738fd1498Szrj   return TI_TEMPLATE (tinfo_a) == TI_TEMPLATE (tinfo_b);
365838fd1498Szrj }
365938fd1498Szrj 
366038fd1498Szrj /* Start a new line indented by SPC spaces on PP.  */
366138fd1498Szrj 
366238fd1498Szrj static void
newline_and_indent(pretty_printer * pp,int spc)366338fd1498Szrj newline_and_indent (pretty_printer *pp, int spc)
366438fd1498Szrj {
366538fd1498Szrj   pp_newline (pp);
366638fd1498Szrj   for (int i = 0; i < spc; i++)
366738fd1498Szrj     pp_space (pp);
366838fd1498Szrj }
366938fd1498Szrj 
367038fd1498Szrj /* Generate a GC-allocated string for ARG, an expression or type.  */
367138fd1498Szrj 
367238fd1498Szrj static const char *
arg_to_string(tree arg,bool verbose)367338fd1498Szrj arg_to_string (tree arg, bool verbose)
367438fd1498Szrj {
367538fd1498Szrj   if (TYPE_P (arg))
367638fd1498Szrj     return type_to_string (arg, verbose, true, NULL, false);
367738fd1498Szrj   else
367838fd1498Szrj     return expr_to_string (arg);
367938fd1498Szrj }
368038fd1498Szrj 
368138fd1498Szrj /* Subroutine to type_to_string_with_compare and
368238fd1498Szrj    print_template_tree_comparison.
368338fd1498Szrj 
368438fd1498Szrj    Print a representation of ARG (an expression or type) to PP,
368538fd1498Szrj    colorizing it as "type-diff" if PP->show_color.  */
368638fd1498Szrj 
368738fd1498Szrj static void
print_nonequal_arg(pretty_printer * pp,tree arg,bool verbose)368838fd1498Szrj print_nonequal_arg (pretty_printer *pp, tree arg, bool verbose)
368938fd1498Szrj {
369038fd1498Szrj   pp_printf (pp, "%r%s%R",
369138fd1498Szrj 	     "type-diff",
369238fd1498Szrj 	     (arg
369338fd1498Szrj 	      ? arg_to_string (arg, verbose)
369438fd1498Szrj 	      : G_("(no argument)")));
369538fd1498Szrj }
369638fd1498Szrj 
369738fd1498Szrj /* Recursively print template TYPE_A to PP, as compared to template TYPE_B.
369838fd1498Szrj 
369938fd1498Szrj    The types must satisfy comparable_template_types_p.
370038fd1498Szrj 
370138fd1498Szrj    If INDENT is 0, then this is equivalent to type_to_string (TYPE_A), but
370238fd1498Szrj    potentially colorizing/eliding in comparison with TYPE_B.
370338fd1498Szrj 
370438fd1498Szrj    For example given types:
370538fd1498Szrj      vector<map<int,double>>
370638fd1498Szrj    and
370738fd1498Szrj      vector<map<int,float>>
370838fd1498Szrj    then the result on PP would be:
370938fd1498Szrj      vector<map<[...],double>>
371038fd1498Szrj    with type elision, and:
371138fd1498Szrj      vector<map<int,double>>
371238fd1498Szrj    without type elision.
371338fd1498Szrj 
371438fd1498Szrj    In both cases the parts of TYPE that differ from PEER will be colorized
371538fd1498Szrj    if pp_show_color (pp) is true.  In the above example, this would be
371638fd1498Szrj    "double".
371738fd1498Szrj 
371838fd1498Szrj    If INDENT is non-zero, then the types are printed in a tree-like form
371938fd1498Szrj    which shows both types.  In the above example, the result on PP would be:
372038fd1498Szrj 
372138fd1498Szrj      vector<
372238fd1498Szrj        map<
372338fd1498Szrj          [...],
372438fd1498Szrj          [double != float]>>
372538fd1498Szrj 
372638fd1498Szrj    and without type-elision would be:
372738fd1498Szrj 
372838fd1498Szrj      vector<
372938fd1498Szrj        map<
373038fd1498Szrj          int,
373138fd1498Szrj          [double != float]>>
373238fd1498Szrj 
373338fd1498Szrj    As before, the differing parts of the types are colorized if
373438fd1498Szrj    pp_show_color (pp) is true ("double" and "float" in this example).
373538fd1498Szrj 
373638fd1498Szrj    Template arguments in which both types are using the default arguments
373738fd1498Szrj    are not printed; if at least one of the two types is using a non-default
373838fd1498Szrj    argument, then that argument is printed (or both arguments for the
373938fd1498Szrj    tree-like print format).  */
374038fd1498Szrj 
374138fd1498Szrj static void
print_template_differences(pretty_printer * pp,tree type_a,tree type_b,bool verbose,int indent)374238fd1498Szrj print_template_differences (pretty_printer *pp, tree type_a, tree type_b,
374338fd1498Szrj 			    bool verbose, int indent)
374438fd1498Szrj {
374538fd1498Szrj   if (indent)
374638fd1498Szrj     newline_and_indent (pp, indent);
374738fd1498Szrj 
374838fd1498Szrj   tree tinfo_a = TYPE_TEMPLATE_INFO (type_a);
374938fd1498Szrj   tree tinfo_b = TYPE_TEMPLATE_INFO (type_b);
375038fd1498Szrj 
375138fd1498Szrj   pp_printf (pp, "%s<",
375238fd1498Szrj 	     IDENTIFIER_POINTER (DECL_NAME (TI_TEMPLATE (tinfo_a))));
375338fd1498Szrj 
375438fd1498Szrj   tree args_a = TI_ARGS (tinfo_a);
375538fd1498Szrj   tree args_b = TI_ARGS (tinfo_b);
375638fd1498Szrj   gcc_assert (TREE_CODE (args_a) == TREE_VEC);
375738fd1498Szrj   gcc_assert (TREE_CODE (args_b) == TREE_VEC);
375838fd1498Szrj   int flags = 0;
375938fd1498Szrj   int len_a = get_non_default_template_args_count (args_a, flags);
376038fd1498Szrj   args_a = INNERMOST_TEMPLATE_ARGS (args_a);
376138fd1498Szrj   int len_b = get_non_default_template_args_count (args_b, flags);
376238fd1498Szrj   args_b = INNERMOST_TEMPLATE_ARGS (args_b);
376338fd1498Szrj   /* Determine the maximum range of args for which non-default template args
376438fd1498Szrj      were used; beyond this, only default args (if any) were used, and so
376538fd1498Szrj      they will be equal from this point onwards.
376638fd1498Szrj      One of the two peers might have used default arguments within this
376738fd1498Szrj      range, but the other will be using non-default arguments, and so
376838fd1498Szrj      it's more readable to print both within this range, to highlight
376938fd1498Szrj      the differences.  */
377038fd1498Szrj   int len_max = MAX (len_a, len_b);
377138fd1498Szrj   gcc_assert (TREE_CODE (args_a) == TREE_VEC);
377238fd1498Szrj   gcc_assert (TREE_CODE (args_b) == TREE_VEC);
377338fd1498Szrj   for (int idx = 0; idx < len_max; idx++)
377438fd1498Szrj     {
377538fd1498Szrj       if (idx)
377638fd1498Szrj 	pp_character (pp, ',');
377738fd1498Szrj 
377838fd1498Szrj       tree arg_a = TREE_VEC_ELT (args_a, idx);
377938fd1498Szrj       tree arg_b = TREE_VEC_ELT (args_b, idx);
378038fd1498Szrj       if (arg_a == arg_b)
378138fd1498Szrj 	{
378238fd1498Szrj 	  if (indent)
378338fd1498Szrj 	    newline_and_indent (pp, indent + 2);
378438fd1498Szrj 	  /* Can do elision here, printing "[...]".  */
378538fd1498Szrj 	  if (flag_elide_type)
378638fd1498Szrj 	    pp_string (pp, G_("[...]"));
378738fd1498Szrj 	  else
378838fd1498Szrj 	    pp_string (pp, arg_to_string (arg_a, verbose));
378938fd1498Szrj 	}
379038fd1498Szrj       else
379138fd1498Szrj 	{
379238fd1498Szrj 	  int new_indent = indent ? indent + 2 : 0;
379338fd1498Szrj 	  if (comparable_template_types_p (arg_a, arg_b))
379438fd1498Szrj 	    print_template_differences (pp, arg_a, arg_b, verbose, new_indent);
379538fd1498Szrj 	  else
379638fd1498Szrj 	    if (indent)
379738fd1498Szrj 	      {
379838fd1498Szrj 		newline_and_indent (pp, indent + 2);
379938fd1498Szrj 		pp_character (pp, '[');
380038fd1498Szrj 		print_nonequal_arg (pp, arg_a, verbose);
380138fd1498Szrj 		pp_string (pp, " != ");
380238fd1498Szrj 		print_nonequal_arg (pp, arg_b, verbose);
380338fd1498Szrj 		pp_character (pp, ']');
380438fd1498Szrj 	      }
380538fd1498Szrj 	    else
380638fd1498Szrj 	      print_nonequal_arg (pp, arg_a, verbose);
380738fd1498Szrj 	}
380838fd1498Szrj     }
380938fd1498Szrj   pp_printf (pp, ">");
381038fd1498Szrj }
381138fd1498Szrj 
381238fd1498Szrj /* As type_to_string, but for a template, potentially colorizing/eliding
381338fd1498Szrj    in comparison with PEER.
381438fd1498Szrj    For example, if TYPE is map<int,double> and PEER is map<int,int>,
381538fd1498Szrj    then the resulting string would be:
381638fd1498Szrj      map<[...],double>
381738fd1498Szrj    with type elision, and:
381838fd1498Szrj      map<int,double>
381938fd1498Szrj    without type elision.
382038fd1498Szrj 
382138fd1498Szrj    In both cases the parts of TYPE that differ from PEER will be colorized
382238fd1498Szrj    if SHOW_COLOR is true.  In the above example, this would be "double".
382338fd1498Szrj 
382438fd1498Szrj    Template arguments in which both types are using the default arguments
382538fd1498Szrj    are not printed; if at least one of the two types is using a non-default
382638fd1498Szrj    argument, then both arguments are printed.
382738fd1498Szrj 
382838fd1498Szrj    The resulting string is in a GC-allocated buffer.  */
382938fd1498Szrj 
383038fd1498Szrj static const char *
type_to_string_with_compare(tree type,tree peer,bool verbose,bool show_color)383138fd1498Szrj type_to_string_with_compare (tree type, tree peer, bool verbose,
383238fd1498Szrj 			     bool show_color)
383338fd1498Szrj {
383438fd1498Szrj   pretty_printer inner_pp;
383538fd1498Szrj   pretty_printer *pp = &inner_pp;
383638fd1498Szrj   pp_show_color (pp) = show_color;
383738fd1498Szrj 
383838fd1498Szrj   print_template_differences (pp, type, peer, verbose, 0);
383938fd1498Szrj   return pp_ggc_formatted_text (pp);
384038fd1498Szrj }
384138fd1498Szrj 
384238fd1498Szrj /* Recursively print a tree-like comparison of TYPE_A and TYPE_B to PP,
384338fd1498Szrj    indented by INDENT spaces.
384438fd1498Szrj 
384538fd1498Szrj    For example given types:
384638fd1498Szrj 
384738fd1498Szrj      vector<map<int,double>>
384838fd1498Szrj 
384938fd1498Szrj    and
385038fd1498Szrj 
385138fd1498Szrj      vector<map<double,float>>
385238fd1498Szrj 
385338fd1498Szrj    the output with type elision would be:
385438fd1498Szrj 
385538fd1498Szrj      vector<
385638fd1498Szrj        map<
385738fd1498Szrj          [...],
385838fd1498Szrj          [double != float]>>
385938fd1498Szrj 
386038fd1498Szrj    and without type-elision would be:
386138fd1498Szrj 
386238fd1498Szrj      vector<
386338fd1498Szrj        map<
386438fd1498Szrj          int,
386538fd1498Szrj          [double != float]>>
386638fd1498Szrj 
386738fd1498Szrj    TYPE_A and TYPE_B must both be comparable template types
386838fd1498Szrj    (as per comparable_template_types_p).
386938fd1498Szrj 
387038fd1498Szrj    Template arguments in which both types are using the default arguments
387138fd1498Szrj    are not printed; if at least one of the two types is using a non-default
387238fd1498Szrj    argument, then both arguments are printed.  */
387338fd1498Szrj 
387438fd1498Szrj static void
print_template_tree_comparison(pretty_printer * pp,tree type_a,tree type_b,bool verbose,int indent)387538fd1498Szrj print_template_tree_comparison (pretty_printer *pp, tree type_a, tree type_b,
387638fd1498Szrj 				bool verbose, int indent)
387738fd1498Szrj {
387838fd1498Szrj   print_template_differences (pp, type_a, type_b, verbose, indent);
387938fd1498Szrj }
388038fd1498Szrj 
388138fd1498Szrj /* Subroutine for use in a format_postprocessor::handle
388238fd1498Szrj    implementation.  Adds a chunk to the end of
388338fd1498Szrj    formatted output, so that it will be printed
388438fd1498Szrj    by pp_output_formatted_text.  */
388538fd1498Szrj 
388638fd1498Szrj static void
append_formatted_chunk(pretty_printer * pp,const char * content)388738fd1498Szrj append_formatted_chunk (pretty_printer *pp, const char *content)
388838fd1498Szrj {
388938fd1498Szrj   output_buffer *buffer = pp_buffer (pp);
389038fd1498Szrj   struct chunk_info *chunk_array = buffer->cur_chunk_array;
389138fd1498Szrj   const char **args = chunk_array->args;
389238fd1498Szrj 
389338fd1498Szrj   unsigned int chunk_idx;
389438fd1498Szrj   for (chunk_idx = 0; args[chunk_idx]; chunk_idx++)
389538fd1498Szrj     ;
389638fd1498Szrj   args[chunk_idx++] = content;
389738fd1498Szrj   args[chunk_idx] = NULL;
389838fd1498Szrj }
389938fd1498Szrj 
390038fd1498Szrj /* Create a copy of CONTENT, with quotes added, and,
390138fd1498Szrj    potentially, with colorization.
390238fd1498Szrj    No escaped is performed on CONTENT.
390338fd1498Szrj    The result is in a GC-allocated buffer. */
390438fd1498Szrj 
390538fd1498Szrj static const char *
add_quotes(const char * content,bool show_color)390638fd1498Szrj add_quotes (const char *content, bool show_color)
390738fd1498Szrj {
390838fd1498Szrj   pretty_printer tmp_pp;
390938fd1498Szrj   pp_show_color (&tmp_pp) = show_color;
391038fd1498Szrj 
391138fd1498Szrj   /* We have to use "%<%s%>" rather than "%qs" here in order to avoid
391238fd1498Szrj      quoting colorization bytes within the results.  */
391338fd1498Szrj   pp_printf (&tmp_pp, "%<%s%>", content);
391438fd1498Szrj 
391538fd1498Szrj   return pp_ggc_formatted_text (&tmp_pp);
391638fd1498Szrj }
391738fd1498Szrj 
391838fd1498Szrj /* If we had %H and %I, and hence deferred printing them,
391938fd1498Szrj    print them now, storing the result into the chunk_info
392038fd1498Szrj    for pp_format.  Quote them if 'q' was provided.
392138fd1498Szrj    Also print the difference in tree form, adding it as
392238fd1498Szrj    an additional chunk.  */
392338fd1498Szrj 
392438fd1498Szrj void
handle(pretty_printer * pp)392538fd1498Szrj cxx_format_postprocessor::handle (pretty_printer *pp)
392638fd1498Szrj {
392738fd1498Szrj   /* If we have one of %H and %I, the other should have
392838fd1498Szrj      been present.  */
392938fd1498Szrj   if (m_type_a.m_tree || m_type_b.m_tree)
393038fd1498Szrj     {
393138fd1498Szrj       /* Avoid reentrancy issues by working with a copy of
393238fd1498Szrj 	 m_type_a and m_type_b, resetting them now.  */
393338fd1498Szrj       deferred_printed_type type_a = m_type_a;
393438fd1498Szrj       deferred_printed_type type_b = m_type_b;
393538fd1498Szrj       m_type_a = deferred_printed_type ();
393638fd1498Szrj       m_type_b = deferred_printed_type ();
393738fd1498Szrj 
393838fd1498Szrj       gcc_assert (type_a.m_buffer_ptr);
393938fd1498Szrj       gcc_assert (type_b.m_buffer_ptr);
394038fd1498Szrj 
394138fd1498Szrj       bool show_color = pp_show_color (pp);
394238fd1498Szrj 
394338fd1498Szrj       const char *type_a_text;
394438fd1498Szrj       const char *type_b_text;
394538fd1498Szrj 
394638fd1498Szrj       if (comparable_template_types_p (type_a.m_tree, type_b.m_tree))
394738fd1498Szrj 	{
394838fd1498Szrj 	  type_a_text
394938fd1498Szrj 	    = type_to_string_with_compare (type_a.m_tree, type_b.m_tree,
395038fd1498Szrj 					   type_a.m_verbose, show_color);
395138fd1498Szrj 	  type_b_text
395238fd1498Szrj 	    = type_to_string_with_compare (type_b.m_tree, type_a.m_tree,
395338fd1498Szrj 					   type_b.m_verbose, show_color);
395438fd1498Szrj 
395538fd1498Szrj 	  if (flag_diagnostics_show_template_tree)
395638fd1498Szrj 	    {
395738fd1498Szrj 	      pretty_printer inner_pp;
395838fd1498Szrj 	      pp_show_color (&inner_pp) = pp_show_color (pp);
395938fd1498Szrj 	      print_template_tree_comparison
396038fd1498Szrj 		(&inner_pp, type_a.m_tree, type_b.m_tree, type_a.m_verbose, 2);
396138fd1498Szrj 	      append_formatted_chunk (pp, pp_ggc_formatted_text (&inner_pp));
396238fd1498Szrj 	    }
396338fd1498Szrj 	}
396438fd1498Szrj       else
396538fd1498Szrj 	{
396638fd1498Szrj 	  /* If the types were not comparable (or if only one of %H/%I was
396738fd1498Szrj 	     provided), they are printed normally, and no difference tree
396838fd1498Szrj 	     is printed.  */
396938fd1498Szrj 	  type_a_text = type_to_string (type_a.m_tree, type_a.m_verbose,
397038fd1498Szrj 					true, &type_a.m_quote, show_color);
397138fd1498Szrj 	  type_b_text = type_to_string (type_b.m_tree, type_b.m_verbose,
397238fd1498Szrj 					true, &type_b.m_quote, show_color);
397338fd1498Szrj 	}
397438fd1498Szrj 
397538fd1498Szrj       if (type_a.m_quote)
397638fd1498Szrj 	type_a_text = add_quotes (type_a_text, show_color);
397738fd1498Szrj       *type_a.m_buffer_ptr = type_a_text;
397838fd1498Szrj 
397938fd1498Szrj        if (type_b.m_quote)
398038fd1498Szrj 	type_b_text = add_quotes (type_b_text, show_color);
398138fd1498Szrj       *type_b.m_buffer_ptr = type_b_text;
398238fd1498Szrj    }
398338fd1498Szrj }
398438fd1498Szrj 
398538fd1498Szrj /* Subroutine for handling %H and %I, to support i18n of messages like:
398638fd1498Szrj 
398738fd1498Szrj     error_at (loc, "could not convert %qE from %qH to %qI",
398838fd1498Szrj 	       expr, type_a, type_b);
398938fd1498Szrj 
399038fd1498Szrj    so that we can print things like:
399138fd1498Szrj 
399238fd1498Szrj      could not convert 'foo' from 'map<int,double>' to 'map<int,int>'
399338fd1498Szrj 
399438fd1498Szrj    and, with type-elision:
399538fd1498Szrj 
399638fd1498Szrj      could not convert 'foo' from 'map<[...],double>' to 'map<[...],int>'
399738fd1498Szrj 
399838fd1498Szrj    (with color-coding of the differences between the types).
399938fd1498Szrj 
400038fd1498Szrj    The %H and %I format codes are peers: both must be present,
400138fd1498Szrj    and they affect each other.  Hence to handle them, we must
400238fd1498Szrj    delay printing until we have both, deferring the printing to
400338fd1498Szrj    pretty_printer's m_format_postprocessor hook.
400438fd1498Szrj 
400538fd1498Szrj    This is called in phase 2 of pp_format, when it is accumulating
400638fd1498Szrj    a series of formatted chunks.  We stash the location of the chunk
400738fd1498Szrj    we're meant to have written to, so that we can write to it in the
400838fd1498Szrj    m_format_postprocessor hook.
400938fd1498Szrj 
401038fd1498Szrj    We also need to stash whether a 'q' prefix was provided (the QUOTE
401138fd1498Szrj    param)  so that we can add the quotes when writing out the delayed
401238fd1498Szrj    chunk.  */
401338fd1498Szrj 
401438fd1498Szrj static void
defer_phase_2_of_type_diff(deferred_printed_type * deferred,tree type,const char ** buffer_ptr,bool verbose,bool quote)401538fd1498Szrj defer_phase_2_of_type_diff (deferred_printed_type *deferred,
401638fd1498Szrj 			    tree type, const char **buffer_ptr,
401738fd1498Szrj 			    bool verbose, bool quote)
401838fd1498Szrj {
401938fd1498Szrj   gcc_assert (deferred->m_tree == NULL_TREE);
402038fd1498Szrj   gcc_assert (deferred->m_buffer_ptr == NULL);
402138fd1498Szrj   *deferred = deferred_printed_type (type, buffer_ptr, verbose, quote);
402238fd1498Szrj }
402338fd1498Szrj 
402438fd1498Szrj 
402538fd1498Szrj /* Called from output_format -- during diagnostic message processing --
402638fd1498Szrj    to handle C++ specific format specifier with the following meanings:
402738fd1498Szrj    %A   function argument-list.
402838fd1498Szrj    %C	tree code.
402938fd1498Szrj    %D   declaration.
403038fd1498Szrj    %E   expression.
403138fd1498Szrj    %F   function declaration.
403238fd1498Szrj    %L	language as used in extern "lang".
403338fd1498Szrj    %O	binary operator.
403438fd1498Szrj    %P   function parameter whose position is indicated by an integer.
403538fd1498Szrj    %Q	assignment operator.
403638fd1498Szrj    %S   substitution (template + args)
403738fd1498Szrj    %T   type.
403838fd1498Szrj    %V   cv-qualifier.
403938fd1498Szrj    %X   exception-specification.
404038fd1498Szrj    %H   type difference (from)
404138fd1498Szrj    %I   type difference (to).  */
404238fd1498Szrj static bool
cp_printer(pretty_printer * pp,text_info * text,const char * spec,int precision,bool wide,bool set_locus,bool verbose,bool * quoted,const char ** buffer_ptr)404338fd1498Szrj cp_printer (pretty_printer *pp, text_info *text, const char *spec,
404438fd1498Szrj 	    int precision, bool wide, bool set_locus, bool verbose,
404538fd1498Szrj 	    bool *quoted, const char **buffer_ptr)
404638fd1498Szrj {
404738fd1498Szrj   gcc_assert (pp->m_format_postprocessor);
404838fd1498Szrj   cxx_format_postprocessor *postprocessor
404938fd1498Szrj     = static_cast <cxx_format_postprocessor *> (pp->m_format_postprocessor);
405038fd1498Szrj 
405138fd1498Szrj   const char *result;
405238fd1498Szrj   tree t = NULL;
405338fd1498Szrj #define next_tree    (t = va_arg (*text->args_ptr, tree))
405438fd1498Szrj #define next_tcode   ((enum tree_code) va_arg (*text->args_ptr, int))
405538fd1498Szrj #define next_lang    ((enum languages) va_arg (*text->args_ptr, int))
405638fd1498Szrj #define next_int     va_arg (*text->args_ptr, int)
405738fd1498Szrj 
405838fd1498Szrj   if (precision != 0 || wide)
405938fd1498Szrj     return false;
406038fd1498Szrj 
406138fd1498Szrj   switch (*spec)
406238fd1498Szrj     {
406338fd1498Szrj     case 'A': result = args_to_string (next_tree, verbose);	break;
406438fd1498Szrj     case 'C': result = code_to_string (next_tcode);		break;
406538fd1498Szrj     case 'D':
406638fd1498Szrj       {
406738fd1498Szrj 	tree temp = next_tree;
406838fd1498Szrj 	if (VAR_P (temp)
406938fd1498Szrj 	    && DECL_HAS_DEBUG_EXPR_P (temp))
407038fd1498Szrj 	  {
407138fd1498Szrj 	    temp = DECL_DEBUG_EXPR (temp);
407238fd1498Szrj 	    if (!DECL_P (temp))
407338fd1498Szrj 	      {
407438fd1498Szrj 		result = expr_to_string (temp);
407538fd1498Szrj 		break;
407638fd1498Szrj 	      }
407738fd1498Szrj 	  }
407838fd1498Szrj 	result = decl_to_string (temp, verbose);
407938fd1498Szrj       }
408038fd1498Szrj       break;
408138fd1498Szrj     case 'E': result = expr_to_string (next_tree);		break;
408238fd1498Szrj     case 'F': result = fndecl_to_string (next_tree, verbose);	break;
408338fd1498Szrj     case 'L': result = language_to_string (next_lang);		break;
408438fd1498Szrj     case 'O': result = op_to_string (false, next_tcode);	break;
408538fd1498Szrj     case 'P': result = parm_to_string (next_int);		break;
408638fd1498Szrj     case 'Q': result = op_to_string (true, next_tcode);		break;
408738fd1498Szrj     case 'S': result = subst_to_string (next_tree);		break;
408838fd1498Szrj     case 'T':
408938fd1498Szrj       {
409038fd1498Szrj 	result = type_to_string (next_tree, verbose, false, quoted,
409138fd1498Szrj 				 pp_show_color (pp));
409238fd1498Szrj       }
409338fd1498Szrj       break;
409438fd1498Szrj     case 'V': result = cv_to_string (next_tree, verbose);	break;
409538fd1498Szrj     case 'X': result = eh_spec_to_string (next_tree, verbose);  break;
409638fd1498Szrj 
409738fd1498Szrj     case 'G':
409838fd1498Szrj       percent_G_format (text);
409938fd1498Szrj       return true;
410038fd1498Szrj 
410138fd1498Szrj     case 'K':
410238fd1498Szrj       t = va_arg (*text->args_ptr, tree);
410338fd1498Szrj       percent_K_format (text, t);
410438fd1498Szrj       return true;
410538fd1498Szrj 
410638fd1498Szrj     case 'H':
410738fd1498Szrj       {
410838fd1498Szrj 	defer_phase_2_of_type_diff (&postprocessor->m_type_a, next_tree,
410938fd1498Szrj 				    buffer_ptr, verbose, *quoted);
411038fd1498Szrj 	return true;
411138fd1498Szrj       }
411238fd1498Szrj 
411338fd1498Szrj     case 'I':
411438fd1498Szrj       {
411538fd1498Szrj 	defer_phase_2_of_type_diff (&postprocessor->m_type_b, next_tree,
411638fd1498Szrj 				    buffer_ptr, verbose, *quoted);
411738fd1498Szrj 	return true;
411838fd1498Szrj       }
411938fd1498Szrj 
412038fd1498Szrj     default:
412138fd1498Szrj       return false;
412238fd1498Szrj     }
412338fd1498Szrj 
412438fd1498Szrj   pp_string (pp, result);
412538fd1498Szrj   if (set_locus && t != NULL)
412638fd1498Szrj     text->set_location (0, location_of (t), true);
412738fd1498Szrj   return true;
412838fd1498Szrj #undef next_tree
412938fd1498Szrj #undef next_tcode
413038fd1498Szrj #undef next_lang
413138fd1498Szrj #undef next_int
413238fd1498Szrj }
413338fd1498Szrj 
413438fd1498Szrj /* Warn about the use of C++0x features when appropriate.  */
413538fd1498Szrj void
maybe_warn_cpp0x(cpp0x_warn_str str)413638fd1498Szrj maybe_warn_cpp0x (cpp0x_warn_str str)
413738fd1498Szrj {
413838fd1498Szrj   if ((cxx_dialect == cxx98) && !in_system_header_at (input_location))
413938fd1498Szrj     /* We really want to suppress this warning in system headers,
414038fd1498Szrj        because libstdc++ uses variadic templates even when we aren't
414138fd1498Szrj        in C++0x mode. */
414238fd1498Szrj     switch (str)
414338fd1498Szrj       {
414438fd1498Szrj       case CPP0X_INITIALIZER_LISTS:
414538fd1498Szrj 	pedwarn (input_location, 0,
414638fd1498Szrj 		 "extended initializer lists "
414738fd1498Szrj 		 "only available with -std=c++11 or -std=gnu++11");
414838fd1498Szrj 	break;
414938fd1498Szrj       case CPP0X_EXPLICIT_CONVERSION:
415038fd1498Szrj 	pedwarn (input_location, 0,
415138fd1498Szrj 		 "explicit conversion operators "
415238fd1498Szrj 		 "only available with -std=c++11 or -std=gnu++11");
415338fd1498Szrj 	break;
415438fd1498Szrj       case CPP0X_VARIADIC_TEMPLATES:
415538fd1498Szrj 	pedwarn (input_location, 0,
415638fd1498Szrj 		 "variadic templates "
415738fd1498Szrj 		 "only available with -std=c++11 or -std=gnu++11");
415838fd1498Szrj 	break;
415938fd1498Szrj       case CPP0X_LAMBDA_EXPR:
416038fd1498Szrj 	pedwarn (input_location, 0,
416138fd1498Szrj 		 "lambda expressions "
416238fd1498Szrj 		  "only available with -std=c++11 or -std=gnu++11");
416338fd1498Szrj 	break;
416438fd1498Szrj       case CPP0X_AUTO:
416538fd1498Szrj 	pedwarn (input_location, 0,
416638fd1498Szrj 		 "C++11 auto only available with -std=c++11 or -std=gnu++11");
416738fd1498Szrj 	break;
416838fd1498Szrj       case CPP0X_SCOPED_ENUMS:
416938fd1498Szrj 	pedwarn (input_location, 0,
417038fd1498Szrj 		 "scoped enums only available with -std=c++11 or -std=gnu++11");
417138fd1498Szrj 	break;
417238fd1498Szrj       case CPP0X_DEFAULTED_DELETED:
417338fd1498Szrj 	pedwarn (input_location, 0,
417438fd1498Szrj 		 "defaulted and deleted functions "
417538fd1498Szrj 		 "only available with -std=c++11 or -std=gnu++11");
417638fd1498Szrj 	break;
417738fd1498Szrj       case CPP0X_INLINE_NAMESPACES:
417838fd1498Szrj 	pedwarn (input_location, OPT_Wpedantic,
417938fd1498Szrj 		 "inline namespaces "
418038fd1498Szrj 		 "only available with -std=c++11 or -std=gnu++11");
418138fd1498Szrj 	break;
418238fd1498Szrj       case CPP0X_OVERRIDE_CONTROLS:
418338fd1498Szrj 	pedwarn (input_location, 0,
418438fd1498Szrj 		 "override controls (override/final) "
418538fd1498Szrj 		 "only available with -std=c++11 or -std=gnu++11");
418638fd1498Szrj         break;
418738fd1498Szrj       case CPP0X_NSDMI:
418838fd1498Szrj 	pedwarn (input_location, 0,
418938fd1498Szrj 		 "non-static data member initializers "
419038fd1498Szrj 		 "only available with -std=c++11 or -std=gnu++11");
419138fd1498Szrj         break;
419238fd1498Szrj       case CPP0X_USER_DEFINED_LITERALS:
419338fd1498Szrj 	pedwarn (input_location, 0,
419438fd1498Szrj 		 "user-defined literals "
419538fd1498Szrj 		 "only available with -std=c++11 or -std=gnu++11");
419638fd1498Szrj 	break;
419738fd1498Szrj       case CPP0X_DELEGATING_CTORS:
419838fd1498Szrj 	pedwarn (input_location, 0,
419938fd1498Szrj 		 "delegating constructors "
420038fd1498Szrj 		 "only available with -std=c++11 or -std=gnu++11");
420138fd1498Szrj         break;
420238fd1498Szrj       case CPP0X_INHERITING_CTORS:
420338fd1498Szrj 	pedwarn (input_location, 0,
420438fd1498Szrj 		 "inheriting constructors "
420538fd1498Szrj 		 "only available with -std=c++11 or -std=gnu++11");
420638fd1498Szrj         break;
420738fd1498Szrj       case CPP0X_ATTRIBUTES:
420838fd1498Szrj 	pedwarn (input_location, 0,
420938fd1498Szrj 		 "c++11 attributes "
421038fd1498Szrj 		 "only available with -std=c++11 or -std=gnu++11");
421138fd1498Szrj 	break;
421238fd1498Szrj       case CPP0X_REF_QUALIFIER:
421338fd1498Szrj 	pedwarn (input_location, 0,
421438fd1498Szrj 		 "ref-qualifiers "
421538fd1498Szrj 		 "only available with -std=c++11 or -std=gnu++11");
421638fd1498Szrj 	break;
421738fd1498Szrj       default:
421838fd1498Szrj 	gcc_unreachable ();
421938fd1498Szrj       }
422038fd1498Szrj }
422138fd1498Szrj 
422238fd1498Szrj /* Warn about the use of variadic templates when appropriate.  */
422338fd1498Szrj void
maybe_warn_variadic_templates(void)422438fd1498Szrj maybe_warn_variadic_templates (void)
422538fd1498Szrj {
422638fd1498Szrj   maybe_warn_cpp0x (CPP0X_VARIADIC_TEMPLATES);
422738fd1498Szrj }
422838fd1498Szrj 
422938fd1498Szrj 
423038fd1498Szrj /* Issue an ISO C++98 pedantic warning at LOCATION, conditional on
423138fd1498Szrj    option OPT with text GMSGID.  Use this function to report
423238fd1498Szrj    diagnostics for constructs that are invalid C++98, but valid
423338fd1498Szrj    C++0x.  */
423438fd1498Szrj bool
pedwarn_cxx98(location_t location,int opt,const char * gmsgid,...)423538fd1498Szrj pedwarn_cxx98 (location_t location, int opt, const char *gmsgid, ...)
423638fd1498Szrj {
423738fd1498Szrj   diagnostic_info diagnostic;
423838fd1498Szrj   va_list ap;
423938fd1498Szrj   bool ret;
424038fd1498Szrj   rich_location richloc (line_table, location);
424138fd1498Szrj 
424238fd1498Szrj   va_start (ap, gmsgid);
424338fd1498Szrj   diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
424438fd1498Szrj 		       (cxx_dialect == cxx98) ? DK_PEDWARN : DK_WARNING);
424538fd1498Szrj   diagnostic.option_index = opt;
424638fd1498Szrj   ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
424738fd1498Szrj   va_end (ap);
424838fd1498Szrj   return ret;
424938fd1498Szrj }
425038fd1498Szrj 
425138fd1498Szrj /* Issue a diagnostic that NAME cannot be found in SCOPE.  DECL is what
425238fd1498Szrj    we found when we tried to do the lookup.  LOCATION is the location of
425338fd1498Szrj    the NAME identifier.  */
425438fd1498Szrj 
425538fd1498Szrj void
qualified_name_lookup_error(tree scope,tree name,tree decl,location_t location)425638fd1498Szrj qualified_name_lookup_error (tree scope, tree name,
425738fd1498Szrj 			     tree decl, location_t location)
425838fd1498Szrj {
425938fd1498Szrj   if (scope == error_mark_node)
426038fd1498Szrj     ; /* We already complained.  */
426138fd1498Szrj   else if (TYPE_P (scope))
426238fd1498Szrj     {
426338fd1498Szrj       if (!COMPLETE_TYPE_P (scope))
426438fd1498Szrj 	error_at (location, "incomplete type %qT used in nested name specifier",
426538fd1498Szrj 		  scope);
426638fd1498Szrj       else if (TREE_CODE (decl) == TREE_LIST)
426738fd1498Szrj 	{
426838fd1498Szrj 	  error_at (location, "reference to %<%T::%D%> is ambiguous",
426938fd1498Szrj 		    scope, name);
427038fd1498Szrj 	  print_candidates (decl);
427138fd1498Szrj 	}
427238fd1498Szrj       else
427338fd1498Szrj 	error_at (location, "%qD is not a member of %qT", name, scope);
427438fd1498Szrj     }
427538fd1498Szrj   else if (scope != global_namespace)
427638fd1498Szrj     {
427738fd1498Szrj       error_at (location, "%qD is not a member of %qD", name, scope);
427838fd1498Szrj       if (!suggest_alternative_in_explicit_scope (location, name, scope))
427938fd1498Szrj 	suggest_alternatives_for (location, name, false);
428038fd1498Szrj     }
428138fd1498Szrj   else
428238fd1498Szrj     {
428338fd1498Szrj       error_at (location, "%<::%D%> has not been declared", name);
428438fd1498Szrj       suggest_alternatives_for (location, name, true);
428538fd1498Szrj     }
428638fd1498Szrj }
4287