Home | History | Annotate | Line # | Download | only in cp
cxx-pretty-print.cc revision 1.1.1.1
      1 /* Implementation of subroutines for the GNU C++ pretty-printer.
      2    Copyright (C) 2003-2022 Free Software Foundation, Inc.
      3    Contributed by Gabriel Dos Reis <gdr (at) integrable-solutions.net>
      4 
      5 This file is part of GCC.
      6 
      7 GCC is free software; you can redistribute it and/or modify it under
      8 the terms of the GNU General Public License as published by the Free
      9 Software Foundation; either version 3, or (at your option) any later
     10 version.
     11 
     12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15 for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with GCC; see the file COPYING3.  If not see
     19 <http://www.gnu.org/licenses/>.  */
     20 
     21 #include "config.h"
     22 #include "system.h"
     23 #include "coretypes.h"
     24 #include "cp-tree.h"
     25 #include "cxx-pretty-print.h"
     26 #include "tree-pretty-print.h"
     27 
     28 static void pp_cxx_unqualified_id (cxx_pretty_printer *, tree);
     29 static void pp_cxx_nested_name_specifier (cxx_pretty_printer *, tree);
     30 static void pp_cxx_qualified_id (cxx_pretty_printer *, tree);
     31 static void pp_cxx_template_argument_list (cxx_pretty_printer *, tree);
     32 static void pp_cxx_type_specifier_seq (cxx_pretty_printer *, tree);
     33 static void pp_cxx_ptr_operator (cxx_pretty_printer *, tree);
     34 static void pp_cxx_parameter_declaration_clause (cxx_pretty_printer *, tree);
     35 static void pp_cxx_template_parameter (cxx_pretty_printer *, tree);
     36 static void pp_cxx_cast_expression (cxx_pretty_printer *, tree);
     37 static void pp_cxx_typeid_expression (cxx_pretty_printer *, tree);
     38 static void pp_cxx_unary_left_fold_expression (cxx_pretty_printer *, tree);
     39 static void pp_cxx_unary_right_fold_expression (cxx_pretty_printer *, tree);
     40 static void pp_cxx_binary_fold_expression (cxx_pretty_printer *, tree);
     41 static void pp_cxx_concept_definition (cxx_pretty_printer *, tree);
     42 
     43 
     45 static inline void
     46 pp_cxx_nonconsecutive_character (cxx_pretty_printer *pp, int c)
     47 {
     48   const char *p = pp_last_position_in_text (pp);
     49 
     50   if (p != NULL && *p == c)
     51     pp_cxx_whitespace (pp);
     52   pp_character (pp, c);
     53   pp->padding = pp_none;
     54 }
     55 
     56 #define pp_cxx_expression_list(PP, T)    \
     57    pp_c_expression_list (PP, T)
     58 #define pp_cxx_space_for_pointer_operator(PP, T)  \
     59    pp_c_space_for_pointer_operator (PP, T)
     60 #define pp_cxx_init_declarator(PP, T)    \
     61    pp_c_init_declarator (PP, T)
     62 #define pp_cxx_call_argument_list(PP, T) \
     63    pp_c_call_argument_list (PP, T)
     64 
     65 void
     66 pp_cxx_colon_colon (cxx_pretty_printer *pp)
     67 {
     68   pp_colon_colon (pp);
     69   pp->padding = pp_none;
     70 }
     71 
     72 void
     73 pp_cxx_begin_template_argument_list (cxx_pretty_printer *pp)
     74 {
     75   pp_cxx_nonconsecutive_character (pp, '<');
     76 }
     77 
     78 void
     79 pp_cxx_end_template_argument_list (cxx_pretty_printer *pp)
     80 {
     81   pp_cxx_nonconsecutive_character (pp, '>');
     82 }
     83 
     84 void
     85 pp_cxx_separate_with (cxx_pretty_printer *pp, int c)
     86 {
     87   pp_separate_with (pp, c);
     88   pp->padding = pp_none;
     89 }
     90 
     91 /* Expressions.  */
     92 
     93 /* conversion-function-id:
     94       operator conversion-type-id
     95 
     96    conversion-type-id:
     97       type-specifier-seq conversion-declarator(opt)
     98 
     99    conversion-declarator:
    100       ptr-operator conversion-declarator(opt)  */
    101 
    102 static inline void
    103 pp_cxx_conversion_function_id (cxx_pretty_printer *pp, tree t)
    104 {
    105   pp_cxx_ws_string (pp, "operator");
    106   pp_cxx_type_specifier_seq (pp, TREE_TYPE (t));
    107 }
    108 
    109 static inline void
    110 pp_cxx_template_id (cxx_pretty_printer *pp, tree t)
    111 {
    112   pp_cxx_unqualified_id (pp, TREE_OPERAND (t, 0));
    113   pp_cxx_begin_template_argument_list (pp);
    114   pp_cxx_template_argument_list (pp, TREE_OPERAND (t, 1));
    115   pp_cxx_end_template_argument_list (pp);
    116 }
    117 
    118 /* Prints the unqualified part of the id-expression T.
    119 
    120    unqualified-id:
    121      identifier
    122      operator-function-id
    123      conversion-function-id
    124      ~ class-name
    125      template-id  */
    126 
    127 static void
    128 pp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t)
    129 {
    130   enum tree_code code = TREE_CODE (t);
    131   switch (code)
    132     {
    133     case RESULT_DECL:
    134       pp->translate_string ("<return-value>");
    135       break;
    136 
    137     case OVERLOAD:
    138       t = OVL_FIRST (t);
    139       /* FALLTHRU */
    140     case VAR_DECL:
    141     case PARM_DECL:
    142     case CONST_DECL:
    143     case TYPE_DECL:
    144     case FUNCTION_DECL:
    145     case NAMESPACE_DECL:
    146     case FIELD_DECL:
    147     case LABEL_DECL:
    148     case USING_DECL:
    149     case TEMPLATE_DECL:
    150       t = DECL_NAME (t);
    151       /* FALLTHRU */
    152 
    153     case IDENTIFIER_NODE:
    154       if (t == NULL)
    155 	pp->translate_string ("<unnamed>");
    156       else if (IDENTIFIER_CONV_OP_P (t))
    157 	pp_cxx_conversion_function_id (pp, t);
    158       else
    159 	pp_cxx_tree_identifier (pp, t);
    160       break;
    161 
    162     case TEMPLATE_ID_EXPR:
    163       pp_cxx_template_id (pp, t);
    164       break;
    165 
    166     case BASELINK:
    167       pp_cxx_unqualified_id (pp, BASELINK_FUNCTIONS (t));
    168       break;
    169 
    170     case RECORD_TYPE:
    171     case UNION_TYPE:
    172     case ENUMERAL_TYPE:
    173     case TYPENAME_TYPE:
    174     case UNBOUND_CLASS_TEMPLATE:
    175       pp_cxx_unqualified_id (pp, TYPE_NAME (t));
    176       if (tree ti = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (t))
    177 	if (PRIMARY_TEMPLATE_P (TI_TEMPLATE (ti)))
    178 	  {
    179 	    pp_cxx_begin_template_argument_list (pp);
    180 	    tree args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (ti));
    181 	    pp_cxx_template_argument_list (pp, args);
    182 	    pp_cxx_end_template_argument_list (pp);
    183 	  }
    184       break;
    185 
    186     case BIT_NOT_EXPR:
    187       pp_cxx_complement (pp);
    188       pp_cxx_unqualified_id (pp, TREE_OPERAND (t, 0));
    189       break;
    190 
    191     case TEMPLATE_TYPE_PARM:
    192     case TEMPLATE_TEMPLATE_PARM:
    193       if (template_placeholder_p (t))
    194 	{
    195 	  t = TREE_TYPE (CLASS_PLACEHOLDER_TEMPLATE (t));
    196 	  pp_cxx_unqualified_id (pp, TYPE_IDENTIFIER (t));
    197 	  pp_string (pp, "<...auto...>");
    198 	}
    199       else if (TYPE_IDENTIFIER (t))
    200 	pp_cxx_unqualified_id (pp, TYPE_IDENTIFIER (t));
    201       else
    202 	pp_cxx_canonical_template_parameter (pp, t);
    203       break;
    204 
    205     case TEMPLATE_PARM_INDEX:
    206       pp_cxx_unqualified_id (pp, TEMPLATE_PARM_DECL (t));
    207       break;
    208 
    209     case BOUND_TEMPLATE_TEMPLATE_PARM:
    210       pp_cxx_cv_qualifier_seq (pp, t);
    211       pp_cxx_unqualified_id (pp, TYPE_IDENTIFIER (t));
    212       pp_cxx_begin_template_argument_list (pp);
    213       pp_cxx_template_argument_list (pp, TYPE_TI_ARGS (t));
    214       pp_cxx_end_template_argument_list (pp);
    215       break;
    216 
    217     default:
    218       pp_unsupported_tree (pp, t);
    219       break;
    220     }
    221 }
    222 
    223 /* Pretty-print out the token sequence ":: template" in template codes
    224    where it is needed to "inline declare" the (following) member as
    225    a template.  This situation arises when SCOPE of T is dependent
    226    on template parameters.  */
    227 
    228 static inline void
    229 pp_cxx_template_keyword_if_needed (cxx_pretty_printer *pp, tree scope, tree t)
    230 {
    231   if (TREE_CODE (t) == TEMPLATE_ID_EXPR
    232       && TYPE_P (scope) && dependent_type_p (scope))
    233     pp_cxx_ws_string (pp, "template");
    234 }
    235 
    236 /* nested-name-specifier:
    237       class-or-namespace-name :: nested-name-specifier(opt)
    238       class-or-namespace-name :: template nested-name-specifier   */
    239 
    240 static void
    241 pp_cxx_nested_name_specifier (cxx_pretty_printer *pp, tree t)
    242 {
    243   /* FIXME: When diagnosing references to concepts (especially as types?)
    244      we end up adding too many '::' to the name. This is partially due
    245      to the fact that pp->enclosing_namespace is null.  */
    246   if (t == global_namespace)
    247     {
    248       pp_cxx_colon_colon (pp);
    249     }
    250   else if (!SCOPE_FILE_SCOPE_P (t) && t != pp->enclosing_scope)
    251     {
    252       tree scope = get_containing_scope (t);
    253       pp_cxx_nested_name_specifier (pp, scope);
    254       pp_cxx_template_keyword_if_needed (pp, scope, t);
    255       pp_cxx_unqualified_id (pp, t);
    256       pp_cxx_colon_colon (pp);
    257     }
    258 }
    259 
    260 /* qualified-id:
    261       nested-name-specifier template(opt) unqualified-id  */
    262 
    263 static void
    264 pp_cxx_qualified_id (cxx_pretty_printer *pp, tree t)
    265 {
    266   switch (TREE_CODE (t))
    267     {
    268       /* A pointer-to-member is always qualified.  */
    269     case PTRMEM_CST:
    270       pp_cxx_nested_name_specifier (pp, PTRMEM_CST_CLASS (t));
    271       pp_cxx_unqualified_id (pp, PTRMEM_CST_MEMBER (t));
    272       break;
    273 
    274       /* In Standard C++, functions cannot possibly be used as
    275 	 nested-name-specifiers.  However, there are situations where
    276 	 is "makes sense" to output the surrounding function name for the
    277 	 purpose of emphasizing on the scope kind.  Just printing the
    278 	 function name might not be sufficient as it may be overloaded; so,
    279 	 we decorate the function with its signature too.
    280 	 FIXME:  This is probably the wrong pretty-printing for conversion
    281 	 functions and some function templates.  */
    282     case OVERLOAD:
    283       t = OVL_FIRST (t);
    284       /* FALLTHRU */
    285     case FUNCTION_DECL:
    286       if (DECL_FUNCTION_MEMBER_P (t))
    287 	pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
    288       pp_cxx_unqualified_id
    289 	(pp, DECL_CONSTRUCTOR_P (t) ? DECL_CONTEXT (t) : t);
    290       pp_cxx_parameter_declaration_clause (pp, TREE_TYPE (t));
    291       break;
    292 
    293     case OFFSET_REF:
    294     case SCOPE_REF:
    295       pp_cxx_nested_name_specifier (pp, TREE_OPERAND (t, 0));
    296       pp_cxx_unqualified_id (pp, TREE_OPERAND (t, 1));
    297       break;
    298 
    299     default:
    300       {
    301 	tree scope = get_containing_scope (t);
    302 	if (scope != pp->enclosing_scope)
    303 	  {
    304 	    pp_cxx_nested_name_specifier (pp, scope);
    305 	    pp_cxx_template_keyword_if_needed (pp, scope, t);
    306 	  }
    307 	pp_cxx_unqualified_id (pp, t);
    308       }
    309       break;
    310     }
    311 }
    312 
    313 /* Given a value e of ENUMERAL_TYPE:
    314    Print out the first ENUMERATOR id with value e, if one is found,
    315    (including nested names but excluding the enum name if unscoped)
    316    else print out the value as a C-style cast (type-id)value.  */
    317 
    318 static void
    319 pp_cxx_enumeration_constant (cxx_pretty_printer *pp, tree e)
    320 {
    321   tree type = TREE_TYPE (e);
    322   tree value = NULL_TREE;
    323 
    324   /* Find the name of this constant.  */
    325   if ((pp->flags & pp_c_flag_gnu_v3) == 0)
    326     for (value = TYPE_VALUES (type); value != NULL_TREE;
    327 	 value = TREE_CHAIN (value))
    328       if (tree_int_cst_equal (DECL_INITIAL (TREE_VALUE (value)), e))
    329 	break;
    330 
    331   if (value != NULL_TREE)
    332     {
    333       if (!ENUM_IS_SCOPED (type))
    334 	type = get_containing_scope (type);
    335       pp_cxx_nested_name_specifier (pp, type);
    336       pp->id_expression (TREE_PURPOSE (value));
    337     }
    338   else
    339     {
    340       /* Value must have been cast.  */
    341        pp_c_type_cast (pp, type);
    342        pp_c_integer_constant (pp, e);
    343     }
    344 }
    345 
    346 
    347 void
    348 cxx_pretty_printer::constant (tree t)
    349 {
    350   switch (TREE_CODE (t))
    351     {
    352     case STRING_CST:
    353       {
    354 	const bool in_parens = PAREN_STRING_LITERAL_P (t);
    355 	if (in_parens)
    356 	  pp_cxx_left_paren (this);
    357 	c_pretty_printer::constant (t);
    358 	if (in_parens)
    359 	  pp_cxx_right_paren (this);
    360       }
    361       break;
    362 
    363     case INTEGER_CST:
    364       if (NULLPTR_TYPE_P (TREE_TYPE (t)))
    365 	{
    366 	  pp_string (this, "nullptr");
    367 	  break;
    368 	}
    369       else if (TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
    370 	{
    371 	  pp_cxx_enumeration_constant (this, t);
    372 	  break;
    373 	}
    374       /* fall through.  */
    375 
    376     default:
    377       c_pretty_printer::constant (t);
    378       break;
    379     }
    380 }
    381 
    382 /* id-expression:
    383       unqualified-id
    384       qualified-id   */
    385 
    386 void
    387 cxx_pretty_printer::id_expression (tree t)
    388 {
    389   if (TREE_CODE (t) == OVERLOAD)
    390     t = OVL_FIRST (t);
    391   if (DECL_P (t) && DECL_CONTEXT (t))
    392     pp_cxx_qualified_id (this, t);
    393   else
    394     pp_cxx_unqualified_id (this, t);
    395 }
    396 
    397 /* user-defined literal:
    398       literal ud-suffix  */
    399 
    400 void
    401 pp_cxx_userdef_literal (cxx_pretty_printer *pp, tree t)
    402 {
    403   pp->constant (USERDEF_LITERAL_VALUE (t));
    404   pp->id_expression (USERDEF_LITERAL_SUFFIX_ID (t));
    405 }
    406 
    407 
    408 /* primary-expression:
    409      literal
    410      this
    411      :: identifier
    412      :: operator-function-id
    413      :: qualifier-id
    414      ( expression )
    415      id-expression
    416 
    417    GNU Extensions:
    418      __builtin_va_arg ( assignment-expression , type-id )
    419      __builtin_offsetof ( type-id, offsetof-expression )
    420      __builtin_addressof ( expression )
    421 
    422      __has_nothrow_assign ( type-id )
    423      __has_nothrow_constructor ( type-id )
    424      __has_nothrow_copy ( type-id )
    425      __has_trivial_assign ( type-id )
    426      __has_trivial_constructor ( type-id )
    427      __has_trivial_copy ( type-id )
    428      __has_unique_object_representations ( type-id )
    429      __has_trivial_destructor ( type-id )
    430      __has_virtual_destructor ( type-id )
    431      __is_abstract ( type-id )
    432      __is_base_of ( type-id , type-id )
    433      __is_class ( type-id )
    434      __is_empty ( type-id )
    435      __is_enum ( type-id )
    436      __is_literal_type ( type-id )
    437      __is_pod ( type-id )
    438      __is_polymorphic ( type-id )
    439      __is_std_layout ( type-id )
    440      __is_trivial ( type-id )
    441      __is_union ( type-id )  */
    442 
    443 void
    444 cxx_pretty_printer::primary_expression (tree t)
    445 {
    446   switch (TREE_CODE (t))
    447     {
    448     case VOID_CST:
    449     case INTEGER_CST:
    450     case REAL_CST:
    451     case COMPLEX_CST:
    452     case STRING_CST:
    453       constant (t);
    454       break;
    455 
    456     case USERDEF_LITERAL:
    457       pp_cxx_userdef_literal (this, t);
    458       break;
    459 
    460     case BASELINK:
    461       t = BASELINK_FUNCTIONS (t);
    462       /* FALLTHRU */
    463     case VAR_DECL:
    464     case PARM_DECL:
    465     case FIELD_DECL:
    466     case FUNCTION_DECL:
    467     case OVERLOAD:
    468     case CONST_DECL:
    469     case TEMPLATE_DECL:
    470       id_expression (t);
    471       break;
    472 
    473     case RESULT_DECL:
    474     case TEMPLATE_TYPE_PARM:
    475     case TEMPLATE_TEMPLATE_PARM:
    476     case TEMPLATE_PARM_INDEX:
    477       pp_cxx_unqualified_id (this, t);
    478       break;
    479 
    480     case STMT_EXPR:
    481       pp_cxx_left_paren (this);
    482       statement (STMT_EXPR_STMT (t));
    483       pp_cxx_right_paren (this);
    484       break;
    485 
    486     case TRAIT_EXPR:
    487       pp_cxx_trait_expression (this, t);
    488       break;
    489 
    490     case VA_ARG_EXPR:
    491       pp_cxx_va_arg_expression (this, t);
    492       break;
    493 
    494     case OFFSETOF_EXPR:
    495       pp_cxx_offsetof_expression (this, t);
    496       break;
    497 
    498     case ADDRESSOF_EXPR:
    499       pp_cxx_addressof_expression (this, t);
    500       break;
    501 
    502     case REQUIRES_EXPR:
    503       pp_cxx_requires_expr (this, t);
    504       break;
    505 
    506     default:
    507       c_pretty_printer::primary_expression (t);
    508       break;
    509     }
    510 }
    511 
    512 /* postfix-expression:
    513      primary-expression
    514      postfix-expression [ expression ]
    515      postfix-expression ( expression-list(opt) )
    516      simple-type-specifier ( expression-list(opt) )
    517      typename ::(opt) nested-name-specifier identifier ( expression-list(opt) )
    518      typename ::(opt) nested-name-specifier template(opt)
    519 				       template-id ( expression-list(opt) )
    520      postfix-expression . template(opt) ::(opt) id-expression
    521      postfix-expression -> template(opt) ::(opt) id-expression
    522      postfix-expression . pseudo-destructor-name
    523      postfix-expression -> pseudo-destructor-name
    524      postfix-expression ++
    525      postfix-expression --
    526      dynamic_cast < type-id > ( expression )
    527      static_cast < type-id > ( expression )
    528      reinterpret_cast < type-id > ( expression )
    529      const_cast < type-id > ( expression )
    530      typeid ( expression )
    531      typeid ( type-id )  */
    532 
    533 void
    534 cxx_pretty_printer::postfix_expression (tree t)
    535 {
    536   enum tree_code code = TREE_CODE (t);
    537 
    538   switch (code)
    539     {
    540     case AGGR_INIT_EXPR:
    541     case CALL_EXPR:
    542       {
    543 	tree fun = cp_get_callee (t);
    544 	tree saved_scope = enclosing_scope;
    545 	bool skipfirst = false;
    546 	tree arg;
    547 
    548 	if (TREE_CODE (fun) == ADDR_EXPR)
    549 	  fun = TREE_OPERAND (fun, 0);
    550 
    551 	/* In templates, where there is no way to tell whether a given
    552 	   call uses an actual member function.  So the parser builds
    553 	   FUN as a COMPONENT_REF or a plain IDENTIFIER_NODE until
    554 	   instantiation time.  */
    555 	if (TREE_CODE (fun) != FUNCTION_DECL)
    556 	  ;
    557 	else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun))
    558 	  {
    559 	    tree object = (code == AGGR_INIT_EXPR
    560 			   ? (AGGR_INIT_VIA_CTOR_P (t)
    561 			      ? AGGR_INIT_EXPR_SLOT (t)
    562 			      : AGGR_INIT_EXPR_ARG (t, 0))
    563 			   : CALL_EXPR_ARG (t, 0));
    564 
    565 	    while (TREE_CODE (object) == NOP_EXPR)
    566 	      object = TREE_OPERAND (object, 0);
    567 
    568 	    if (TREE_CODE (object) == ADDR_EXPR)
    569 	      object = TREE_OPERAND (object, 0);
    570 
    571 	    if (!TYPE_PTR_P (TREE_TYPE (object)))
    572 	      {
    573 		postfix_expression (object);
    574 		pp_cxx_dot (this);
    575 	      }
    576 	    else
    577 	      {
    578 		postfix_expression (object);
    579 		pp_cxx_arrow (this);
    580 	      }
    581 	    skipfirst = true;
    582 	    enclosing_scope = strip_pointer_operator (TREE_TYPE (object));
    583 	  }
    584 
    585 	postfix_expression (fun);
    586 	enclosing_scope = saved_scope;
    587 	pp_cxx_left_paren (this);
    588 	if (code == AGGR_INIT_EXPR)
    589 	  {
    590 	    aggr_init_expr_arg_iterator iter;
    591 	    FOR_EACH_AGGR_INIT_EXPR_ARG (arg, iter, t)
    592 	      {
    593 		if (skipfirst)
    594 		  skipfirst = false;
    595 		else
    596 		  {
    597 		    expression (arg);
    598 		    if (more_aggr_init_expr_args_p (&iter))
    599 		      pp_cxx_separate_with (this, ',');
    600 		  }
    601 	      }
    602 	  }
    603 	else
    604 	  {
    605 	    call_expr_arg_iterator iter;
    606 	    FOR_EACH_CALL_EXPR_ARG (arg, iter, t)
    607 	      {
    608 		if (skipfirst)
    609 		  skipfirst = false;
    610 		else
    611 		  {
    612 		    expression (arg);
    613 		    if (more_call_expr_args_p (&iter))
    614 		      pp_cxx_separate_with (this, ',');
    615 		  }
    616 	      }
    617 	  }
    618 	pp_cxx_right_paren (this);
    619       }
    620       if (code == AGGR_INIT_EXPR && AGGR_INIT_VIA_CTOR_P (t))
    621 	{
    622 	  pp_cxx_separate_with (this, ',');
    623 	  postfix_expression (AGGR_INIT_EXPR_SLOT (t));
    624 	}
    625       break;
    626 
    627     case BASELINK:
    628     case VAR_DECL:
    629     case PARM_DECL:
    630     case FIELD_DECL:
    631     case FUNCTION_DECL:
    632     case OVERLOAD:
    633     case CONST_DECL:
    634     case TEMPLATE_DECL:
    635     case RESULT_DECL:
    636       primary_expression (t);
    637       break;
    638 
    639     case DYNAMIC_CAST_EXPR:
    640     case STATIC_CAST_EXPR:
    641     case REINTERPRET_CAST_EXPR:
    642     case CONST_CAST_EXPR:
    643       if (code == DYNAMIC_CAST_EXPR)
    644 	pp_cxx_ws_string (this, "dynamic_cast");
    645       else if (code == STATIC_CAST_EXPR)
    646 	pp_cxx_ws_string (this, "static_cast");
    647       else if (code == REINTERPRET_CAST_EXPR)
    648 	pp_cxx_ws_string (this, "reinterpret_cast");
    649       else
    650 	pp_cxx_ws_string (this, "const_cast");
    651       pp_cxx_begin_template_argument_list (this);
    652       type_id (TREE_TYPE (t));
    653       pp_cxx_end_template_argument_list (this);
    654       pp_left_paren (this);
    655       expression (TREE_OPERAND (t, 0));
    656       pp_right_paren (this);
    657       break;
    658 
    659     case BIT_CAST_EXPR:
    660       pp_cxx_ws_string (this, "__builtin_bit_cast");
    661       pp_left_paren (this);
    662       type_id (TREE_TYPE (t));
    663       pp_comma (this);
    664       expression (TREE_OPERAND (t, 0));
    665       pp_right_paren (this);
    666       break;
    667 
    668     case EMPTY_CLASS_EXPR:
    669       type_id (TREE_TYPE (t));
    670       pp_left_paren (this);
    671       pp_right_paren (this);
    672       break;
    673 
    674     case TYPEID_EXPR:
    675       pp_cxx_typeid_expression (this, t);
    676       break;
    677 
    678     case PSEUDO_DTOR_EXPR:
    679       postfix_expression (TREE_OPERAND (t, 0));
    680       pp_cxx_dot (this);
    681       if (TREE_OPERAND (t, 1))
    682 	{
    683 	  pp_cxx_qualified_id (this, TREE_OPERAND (t, 1));
    684 	  pp_cxx_colon_colon (this);
    685 	}
    686       pp_complement (this);
    687       pp_cxx_unqualified_id (this, TREE_OPERAND (t, 2));
    688       break;
    689 
    690     case ARROW_EXPR:
    691       postfix_expression (TREE_OPERAND (t, 0));
    692       pp_cxx_arrow (this);
    693       break;
    694 
    695     default:
    696       c_pretty_printer::postfix_expression (t);
    697       break;
    698     }
    699 }
    700 
    701 /* new-expression:
    702       ::(opt) new new-placement(opt) new-type-id new-initializer(opt)
    703       ::(opt) new new-placement(opt) ( type-id ) new-initializer(opt)
    704 
    705    new-placement:
    706       ( expression-list )
    707 
    708    new-type-id:
    709       type-specifier-seq new-declarator(opt)
    710 
    711    new-declarator:
    712       ptr-operator new-declarator(opt)
    713       direct-new-declarator
    714 
    715    direct-new-declarator
    716       [ expression ]
    717       direct-new-declarator [ constant-expression ]
    718 
    719    new-initializer:
    720       ( expression-list(opt) )  */
    721 
    722 static void
    723 pp_cxx_new_expression (cxx_pretty_printer *pp, tree t)
    724 {
    725   enum tree_code code = TREE_CODE (t);
    726   tree type = TREE_OPERAND (t, 1);
    727   tree init = TREE_OPERAND (t, 2);
    728   switch (code)
    729     {
    730     case NEW_EXPR:
    731     case VEC_NEW_EXPR:
    732       if (NEW_EXPR_USE_GLOBAL (t))
    733 	pp_cxx_colon_colon (pp);
    734       pp_cxx_ws_string (pp, "new");
    735       if (TREE_OPERAND (t, 0))
    736 	{
    737 	  pp_cxx_call_argument_list (pp, TREE_OPERAND (t, 0));
    738 	  pp_space (pp);
    739 	}
    740       if (TREE_CODE (type) == ARRAY_REF)
    741 	type = build_cplus_array_type
    742 	  (TREE_OPERAND (type, 0),
    743 	   build_index_type (fold_build2_loc (input_location,
    744 					  MINUS_EXPR, integer_type_node,
    745 					  TREE_OPERAND (type, 1),
    746 					  integer_one_node)));
    747       pp->type_id (type);
    748       if (init)
    749 	{
    750 	  pp_left_paren (pp);
    751 	  if (TREE_CODE (init) == TREE_LIST)
    752 	    pp_c_expression_list (pp, init);
    753 	  else if (init == void_node)
    754 	    ;			/* OK, empty initializer list.  */
    755 	  else
    756 	    pp->expression (init);
    757 	  pp_right_paren (pp);
    758 	}
    759       break;
    760 
    761     default:
    762       pp_unsupported_tree (pp, t);
    763     }
    764 }
    765 
    766 /* delete-expression:
    767       ::(opt) delete cast-expression
    768       ::(opt) delete [ ] cast-expression   */
    769 
    770 static void
    771 pp_cxx_delete_expression (cxx_pretty_printer *pp, tree t)
    772 {
    773   enum tree_code code = TREE_CODE (t);
    774   switch (code)
    775     {
    776     case DELETE_EXPR:
    777     case VEC_DELETE_EXPR:
    778       if (DELETE_EXPR_USE_GLOBAL (t))
    779 	pp_cxx_colon_colon (pp);
    780       pp_cxx_ws_string (pp, "delete");
    781       pp_space (pp);
    782       if (code == VEC_DELETE_EXPR
    783 	  || DELETE_EXPR_USE_VEC (t))
    784 	{
    785 	  pp_left_bracket (pp);
    786 	  pp_right_bracket (pp);
    787 	  pp_space (pp);
    788 	}
    789       pp_c_cast_expression (pp, TREE_OPERAND (t, 0));
    790       break;
    791 
    792     default:
    793       pp_unsupported_tree (pp, t);
    794     }
    795 }
    796 
    797 /* unary-expression:
    798       postfix-expression
    799       ++ cast-expression
    800       -- cast-expression
    801       unary-operator cast-expression
    802       sizeof unary-expression
    803       sizeof ( type-id )
    804       sizeof ... ( identifier )
    805       new-expression
    806       delete-expression
    807 
    808    unary-operator: one of
    809       *   &   +   -  !
    810 
    811    GNU extensions:
    812       __alignof__ unary-expression
    813       __alignof__ ( type-id )  */
    814 
    815 void
    816 cxx_pretty_printer::unary_expression (tree t)
    817 {
    818   enum tree_code code = TREE_CODE (t);
    819   switch (code)
    820     {
    821     case NEW_EXPR:
    822     case VEC_NEW_EXPR:
    823       pp_cxx_new_expression (this, t);
    824       break;
    825 
    826     case DELETE_EXPR:
    827     case VEC_DELETE_EXPR:
    828       pp_cxx_delete_expression (this, t);
    829       break;
    830 
    831     case SIZEOF_EXPR:
    832       if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
    833 	{
    834 	  pp_cxx_ws_string (this, "sizeof");
    835 	  pp_cxx_ws_string (this, "...");
    836 	  pp_cxx_whitespace (this);
    837 	  pp_cxx_left_paren (this);
    838 	  if (TYPE_P (TREE_OPERAND (t, 0)))
    839 	    type_id (TREE_OPERAND (t, 0));
    840 	  else
    841 	    unary_expression (TREE_OPERAND (t, 0));
    842 	  pp_cxx_right_paren (this);
    843 	  break;
    844 	}
    845       /* Fall through  */
    846 
    847     case ALIGNOF_EXPR:
    848       pp_cxx_ws_string (this, code == SIZEOF_EXPR ? "sizeof" : "__alignof__");
    849       pp_cxx_whitespace (this);
    850       if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
    851 	{
    852 	  pp_cxx_left_paren (this);
    853 	  type_id (TREE_TYPE (TREE_OPERAND (t, 0)));
    854 	  pp_cxx_right_paren (this);
    855 	}
    856       else if (TYPE_P (TREE_OPERAND (t, 0)))
    857 	{
    858 	  pp_cxx_left_paren (this);
    859 	  type_id (TREE_OPERAND (t, 0));
    860 	  pp_cxx_right_paren (this);
    861 	}
    862       else
    863 	unary_expression (TREE_OPERAND (t, 0));
    864       break;
    865 
    866     case AT_ENCODE_EXPR:
    867       pp_cxx_ws_string (this, "@encode");
    868       pp_cxx_whitespace (this);
    869       pp_cxx_left_paren (this);
    870       type_id (TREE_OPERAND (t, 0));
    871       pp_cxx_right_paren (this);
    872       break;
    873 
    874     case NOEXCEPT_EXPR:
    875       pp_cxx_ws_string (this, "noexcept");
    876       pp_cxx_whitespace (this);
    877       pp_cxx_left_paren (this);
    878       expression (TREE_OPERAND (t, 0));
    879       pp_cxx_right_paren (this);
    880       break;
    881 
    882     case UNARY_PLUS_EXPR:
    883       pp_plus (this);
    884       pp_cxx_cast_expression (this, TREE_OPERAND (t, 0));
    885       break;
    886 
    887     default:
    888       c_pretty_printer::unary_expression (t);
    889       break;
    890     }
    891 }
    892 
    893 /* cast-expression:
    894       unary-expression
    895       ( type-id ) cast-expression  */
    896 
    897 static void
    898 pp_cxx_cast_expression (cxx_pretty_printer *pp, tree t)
    899 {
    900   switch (TREE_CODE (t))
    901     {
    902     case CAST_EXPR:
    903     case IMPLICIT_CONV_EXPR:
    904       pp->type_id (TREE_TYPE (t));
    905       pp_cxx_call_argument_list (pp, TREE_OPERAND (t, 0));
    906       break;
    907 
    908     default:
    909       pp_c_cast_expression (pp, t);
    910       break;
    911     }
    912 }
    913 
    914 /* pm-expression:
    915       cast-expression
    916       pm-expression .* cast-expression
    917       pm-expression ->* cast-expression  */
    918 
    919 static void
    920 pp_cxx_pm_expression (cxx_pretty_printer *pp, tree t)
    921 {
    922   switch (TREE_CODE (t))
    923     {
    924       /* Handle unfortunate OFFSET_REF overloading here.  */
    925     case OFFSET_REF:
    926       if (TYPE_P (TREE_OPERAND (t, 0)))
    927 	{
    928 	  pp_cxx_qualified_id (pp, t);
    929 	  break;
    930 	}
    931       /* Fall through.  */
    932     case MEMBER_REF:
    933     case DOTSTAR_EXPR:
    934       pp_cxx_pm_expression (pp, TREE_OPERAND (t, 0));
    935       if (TREE_CODE (t) == MEMBER_REF)
    936 	pp_cxx_arrow (pp);
    937       else
    938 	pp_cxx_dot (pp);
    939       pp_star(pp);
    940       pp_cxx_cast_expression (pp, TREE_OPERAND (t, 1));
    941       break;
    942 
    943 
    944     default:
    945       pp_cxx_cast_expression (pp, t);
    946       break;
    947     }
    948 }
    949 
    950 /* multiplicative-expression:
    951       pm-expression
    952       multiplicative-expression * pm-expression
    953       multiplicative-expression / pm-expression
    954       multiplicative-expression % pm-expression  */
    955 
    956 void
    957 cxx_pretty_printer::multiplicative_expression (tree e)
    958 {
    959   enum tree_code code = TREE_CODE (e);
    960   switch (code)
    961     {
    962     case MULT_EXPR:
    963     case TRUNC_DIV_EXPR:
    964     case TRUNC_MOD_EXPR:
    965     case EXACT_DIV_EXPR:
    966     case RDIV_EXPR:
    967       multiplicative_expression (TREE_OPERAND (e, 0));
    968       pp_space (this);
    969       if (code == MULT_EXPR)
    970 	pp_star (this);
    971       else if (code != TRUNC_MOD_EXPR)
    972 	pp_slash (this);
    973       else
    974 	pp_modulo (this);
    975       pp_space (this);
    976       pp_cxx_pm_expression (this, TREE_OPERAND (e, 1));
    977       break;
    978 
    979     default:
    980       pp_cxx_pm_expression (this, e);
    981       break;
    982     }
    983 }
    984 
    985 /* conditional-expression:
    986       logical-or-expression
    987       logical-or-expression ?  expression  : assignment-expression  */
    988 
    989 void
    990 cxx_pretty_printer::conditional_expression (tree e)
    991 {
    992   if (TREE_CODE (e) == COND_EXPR)
    993     {
    994       pp_c_logical_or_expression (this, TREE_OPERAND (e, 0));
    995       pp_space (this);
    996       pp_question (this);
    997       pp_space (this);
    998       expression (TREE_OPERAND (e, 1));
    999       pp_space (this);
   1000       assignment_expression (TREE_OPERAND (e, 2));
   1001     }
   1002   else
   1003     pp_c_logical_or_expression (this, e);
   1004 }
   1005 
   1006 /* Pretty-print a compound assignment operator token as indicated by T.  */
   1007 
   1008 static void
   1009 pp_cxx_assignment_operator (cxx_pretty_printer *pp, tree t)
   1010 {
   1011   const char *op;
   1012 
   1013   switch (TREE_CODE (t))
   1014     {
   1015     case NOP_EXPR:
   1016       op = "=";
   1017       break;
   1018 
   1019     case PLUS_EXPR:
   1020       op = "+=";
   1021       break;
   1022 
   1023     case MINUS_EXPR:
   1024       op = "-=";
   1025       break;
   1026 
   1027     case TRUNC_DIV_EXPR:
   1028       op = "/=";
   1029       break;
   1030 
   1031     case TRUNC_MOD_EXPR:
   1032       op = "%=";
   1033       break;
   1034 
   1035     default:
   1036       op = get_tree_code_name (TREE_CODE (t));
   1037       break;
   1038     }
   1039 
   1040   pp_cxx_ws_string (pp, op);
   1041 }
   1042 
   1043 
   1044 /* assignment-expression:
   1045       conditional-expression
   1046       logical-or-expression assignment-operator assignment-expression
   1047       throw-expression
   1048 
   1049    throw-expression:
   1050        throw assignment-expression(opt)
   1051 
   1052    assignment-operator: one of
   1053       =    *=    /=    %=    +=    -=    >>=    <<=    &=    ^=    |=  */
   1054 
   1055 void
   1056 cxx_pretty_printer::assignment_expression (tree e)
   1057 {
   1058   switch (TREE_CODE (e))
   1059     {
   1060     case MODIFY_EXPR:
   1061     case INIT_EXPR:
   1062       pp_c_logical_or_expression (this, TREE_OPERAND (e, 0));
   1063       pp_space (this);
   1064       pp_equal (this);
   1065       pp_space (this);
   1066       assignment_expression (TREE_OPERAND (e, 1));
   1067       break;
   1068 
   1069     case THROW_EXPR:
   1070       pp_cxx_ws_string (this, "throw");
   1071       if (TREE_OPERAND (e, 0))
   1072 	assignment_expression (TREE_OPERAND (e, 0));
   1073       break;
   1074 
   1075     case MODOP_EXPR:
   1076       pp_c_logical_or_expression (this, TREE_OPERAND (e, 0));
   1077       pp_cxx_assignment_operator (this, TREE_OPERAND (e, 1));
   1078       assignment_expression (TREE_OPERAND (e, 2));
   1079       break;
   1080 
   1081     default:
   1082       conditional_expression (e);
   1083       break;
   1084     }
   1085 }
   1086 
   1087 void
   1088 cxx_pretty_printer::expression (tree t)
   1089 {
   1090   switch (TREE_CODE (t))
   1091     {
   1092     case STRING_CST:
   1093     case VOID_CST:
   1094     case INTEGER_CST:
   1095     case REAL_CST:
   1096     case COMPLEX_CST:
   1097       constant (t);
   1098       break;
   1099 
   1100     case USERDEF_LITERAL:
   1101       pp_cxx_userdef_literal (this, t);
   1102       break;
   1103 
   1104     case RESULT_DECL:
   1105       pp_cxx_unqualified_id (this, t);
   1106       break;
   1107 
   1108 #if 0
   1109     case OFFSET_REF:
   1110 #endif
   1111     case SCOPE_REF:
   1112     case PTRMEM_CST:
   1113       pp_cxx_qualified_id (this, t);
   1114       break;
   1115 
   1116     case OVERLOAD:
   1117       t = OVL_FIRST (t);
   1118       /* FALLTHRU */
   1119     case VAR_DECL:
   1120     case PARM_DECL:
   1121     case FIELD_DECL:
   1122     case CONST_DECL:
   1123     case FUNCTION_DECL:
   1124     case BASELINK:
   1125     case TEMPLATE_DECL:
   1126     case TEMPLATE_TYPE_PARM:
   1127     case TEMPLATE_PARM_INDEX:
   1128     case TEMPLATE_TEMPLATE_PARM:
   1129     case STMT_EXPR:
   1130     case REQUIRES_EXPR:
   1131       primary_expression (t);
   1132       break;
   1133 
   1134     case CALL_EXPR:
   1135     case DYNAMIC_CAST_EXPR:
   1136     case STATIC_CAST_EXPR:
   1137     case REINTERPRET_CAST_EXPR:
   1138     case CONST_CAST_EXPR:
   1139 #if 0
   1140     case MEMBER_REF:
   1141 #endif
   1142     case EMPTY_CLASS_EXPR:
   1143     case TYPEID_EXPR:
   1144     case PSEUDO_DTOR_EXPR:
   1145     case AGGR_INIT_EXPR:
   1146     case ARROW_EXPR:
   1147       postfix_expression (t);
   1148       break;
   1149 
   1150     case NEW_EXPR:
   1151     case VEC_NEW_EXPR:
   1152       pp_cxx_new_expression (this, t);
   1153       break;
   1154 
   1155     case DELETE_EXPR:
   1156     case VEC_DELETE_EXPR:
   1157       pp_cxx_delete_expression (this, t);
   1158       break;
   1159 
   1160     case SIZEOF_EXPR:
   1161     case ALIGNOF_EXPR:
   1162     case NOEXCEPT_EXPR:
   1163     case UNARY_PLUS_EXPR:
   1164       unary_expression (t);
   1165       break;
   1166 
   1167     case CAST_EXPR:
   1168     case IMPLICIT_CONV_EXPR:
   1169       pp_cxx_cast_expression (this, t);
   1170       break;
   1171 
   1172     case OFFSET_REF:
   1173     case MEMBER_REF:
   1174     case DOTSTAR_EXPR:
   1175       pp_cxx_pm_expression (this, t);
   1176       break;
   1177 
   1178     case MULT_EXPR:
   1179     case TRUNC_DIV_EXPR:
   1180     case TRUNC_MOD_EXPR:
   1181     case EXACT_DIV_EXPR:
   1182     case RDIV_EXPR:
   1183       multiplicative_expression (t);
   1184       break;
   1185 
   1186     case COND_EXPR:
   1187       conditional_expression (t);
   1188       break;
   1189 
   1190     case MODIFY_EXPR:
   1191     case INIT_EXPR:
   1192     case THROW_EXPR:
   1193     case MODOP_EXPR:
   1194       assignment_expression (t);
   1195       break;
   1196 
   1197     case NON_DEPENDENT_EXPR:
   1198     case MUST_NOT_THROW_EXPR:
   1199       expression (TREE_OPERAND (t, 0));
   1200       break;
   1201 
   1202     case EXPR_PACK_EXPANSION:
   1203       expression (PACK_EXPANSION_PATTERN (t));
   1204       pp_cxx_ws_string (this, "...");
   1205       break;
   1206 
   1207     case UNARY_LEFT_FOLD_EXPR:
   1208       pp_cxx_unary_left_fold_expression (this, t);
   1209       break;
   1210 
   1211     case UNARY_RIGHT_FOLD_EXPR:
   1212       pp_cxx_unary_right_fold_expression (this, t);
   1213     break;
   1214 
   1215     case BINARY_LEFT_FOLD_EXPR:
   1216     case BINARY_RIGHT_FOLD_EXPR:
   1217       pp_cxx_binary_fold_expression (this, t);
   1218       break;
   1219 
   1220     case TEMPLATE_ID_EXPR:
   1221       pp_cxx_template_id (this, t);
   1222       break;
   1223 
   1224     case NONTYPE_ARGUMENT_PACK:
   1225       {
   1226 	tree args = ARGUMENT_PACK_ARGS (t);
   1227 	int i, len = TREE_VEC_LENGTH (args);
   1228 	pp_cxx_left_brace (this);
   1229 	for (i = 0; i < len; ++i)
   1230 	  {
   1231 	    if (i > 0)
   1232 	      pp_cxx_separate_with (this, ',');
   1233 	    expression (TREE_VEC_ELT (args, i));
   1234 	  }
   1235 	pp_cxx_right_brace (this);
   1236       }
   1237       break;
   1238 
   1239     case LAMBDA_EXPR:
   1240       pp_cxx_ws_string (this, "<lambda>");
   1241       break;
   1242 
   1243     case TRAIT_EXPR:
   1244       pp_cxx_trait_expression (this, t);
   1245       break;
   1246 
   1247     case ATOMIC_CONSTR:
   1248     case CHECK_CONSTR:
   1249     case CONJ_CONSTR:
   1250     case DISJ_CONSTR:
   1251       pp_cxx_constraint (this, t);
   1252       break;
   1253 
   1254     case PAREN_EXPR:
   1255       pp_cxx_left_paren (this);
   1256       expression (TREE_OPERAND (t, 0));
   1257       pp_cxx_right_paren (this);
   1258       break;
   1259 
   1260     default:
   1261       c_pretty_printer::expression (t);
   1262       break;
   1263     }
   1264 }
   1265 
   1266 
   1267 /* Declarations.  */
   1268 
   1269 /* function-specifier:
   1270       inline
   1271       virtual
   1272       explicit   */
   1273 
   1274 void
   1275 cxx_pretty_printer::function_specifier (tree t)
   1276 {
   1277   switch (TREE_CODE (t))
   1278     {
   1279     case FUNCTION_DECL:
   1280       if (DECL_VIRTUAL_P (t))
   1281 	pp_cxx_ws_string (this, "virtual");
   1282       else if (DECL_CONSTRUCTOR_P (t) && DECL_NONCONVERTING_P (t))
   1283 	pp_cxx_ws_string (this, "explicit");
   1284       else
   1285         c_pretty_printer::function_specifier (t);
   1286 
   1287     default:
   1288       break;
   1289     }
   1290 }
   1291 
   1292 /* decl-specifier-seq:
   1293       decl-specifier-seq(opt) decl-specifier
   1294 
   1295    decl-specifier:
   1296       storage-class-specifier
   1297       type-specifier
   1298       function-specifier
   1299       friend
   1300       typedef  */
   1301 
   1302 void
   1303 cxx_pretty_printer::declaration_specifiers (tree t)
   1304 {
   1305   switch (TREE_CODE (t))
   1306     {
   1307     case VAR_DECL:
   1308     case PARM_DECL:
   1309     case CONST_DECL:
   1310     case FIELD_DECL:
   1311       storage_class_specifier (t);
   1312       declaration_specifiers (TREE_TYPE (t));
   1313       break;
   1314 
   1315     case TYPE_DECL:
   1316       pp_cxx_ws_string (this, "typedef");
   1317       declaration_specifiers (TREE_TYPE (t));
   1318       break;
   1319 
   1320     case FUNCTION_DECL:
   1321       /* Constructors don't have return types.  And conversion functions
   1322 	 do not have a type-specifier in their return types.  */
   1323       if (DECL_CONSTRUCTOR_P (t) || DECL_CONV_FN_P (t))
   1324 	function_specifier (t);
   1325       else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
   1326 	declaration_specifiers (TREE_TYPE (TREE_TYPE (t)));
   1327       else
   1328         c_pretty_printer::declaration_specifiers (t);
   1329       break;
   1330     default:
   1331         c_pretty_printer::declaration_specifiers (t);
   1332       break;
   1333     }
   1334 }
   1335 
   1336 /* simple-type-specifier:
   1337       ::(opt) nested-name-specifier(opt) type-name
   1338       ::(opt) nested-name-specifier(opt) template(opt) template-id
   1339       decltype-specifier
   1340       char
   1341       wchar_t
   1342       bool
   1343       short
   1344       int
   1345       long
   1346       signed
   1347       unsigned
   1348       float
   1349       double
   1350       void  */
   1351 
   1352 void
   1353 cxx_pretty_printer::simple_type_specifier (tree t)
   1354 {
   1355   switch (TREE_CODE (t))
   1356     {
   1357     case RECORD_TYPE:
   1358     case UNION_TYPE:
   1359     case ENUMERAL_TYPE:
   1360       pp_cxx_qualified_id (this, t);
   1361       break;
   1362 
   1363     case TEMPLATE_TYPE_PARM:
   1364     case TEMPLATE_TEMPLATE_PARM:
   1365     case TEMPLATE_PARM_INDEX:
   1366     case BOUND_TEMPLATE_TEMPLATE_PARM:
   1367       pp_cxx_unqualified_id (this, t);
   1368       if (tree c = PLACEHOLDER_TYPE_CONSTRAINTS (t))
   1369         pp_cxx_constrained_type_spec (this, c);
   1370       break;
   1371 
   1372     case TYPENAME_TYPE:
   1373       pp_cxx_ws_string (this, "typename");
   1374       pp_cxx_nested_name_specifier (this, TYPE_CONTEXT (t));
   1375       pp_cxx_unqualified_id (this, TYPENAME_TYPE_FULLNAME (t));
   1376       break;
   1377 
   1378     case DECLTYPE_TYPE:
   1379       pp_cxx_ws_string (this, "decltype");
   1380       pp_cxx_left_paren (this);
   1381       this->expression (DECLTYPE_TYPE_EXPR (t));
   1382       pp_cxx_right_paren (this);
   1383       break;
   1384 
   1385     case NULLPTR_TYPE:
   1386       pp_cxx_ws_string (this, "std::nullptr_t");
   1387       break;
   1388 
   1389     default:
   1390       c_pretty_printer::simple_type_specifier (t);
   1391       break;
   1392     }
   1393 }
   1394 
   1395 /* type-specifier-seq:
   1396       type-specifier type-specifier-seq(opt)
   1397 
   1398    type-specifier:
   1399       simple-type-specifier
   1400       class-specifier
   1401       enum-specifier
   1402       elaborated-type-specifier
   1403       cv-qualifier   */
   1404 
   1405 static void
   1406 pp_cxx_type_specifier_seq (cxx_pretty_printer *pp, tree t)
   1407 {
   1408   switch (TREE_CODE (t))
   1409     {
   1410     case TEMPLATE_DECL:
   1411     case TEMPLATE_TYPE_PARM:
   1412     case TEMPLATE_TEMPLATE_PARM:
   1413     case TYPE_DECL:
   1414     case BOUND_TEMPLATE_TEMPLATE_PARM:
   1415     case DECLTYPE_TYPE:
   1416     case NULLPTR_TYPE:
   1417       pp_cxx_cv_qualifier_seq (pp, t);
   1418       pp->simple_type_specifier (t);
   1419       break;
   1420 
   1421     case METHOD_TYPE:
   1422       pp_cxx_type_specifier_seq (pp, TREE_TYPE (t));
   1423       pp_cxx_space_for_pointer_operator (pp, TREE_TYPE (t));
   1424       pp_cxx_nested_name_specifier (pp, TYPE_METHOD_BASETYPE (t));
   1425       break;
   1426 
   1427     case RECORD_TYPE:
   1428       if (TYPE_PTRMEMFUNC_P (t))
   1429 	{
   1430 	  tree pfm = TYPE_PTRMEMFUNC_FN_TYPE (t);
   1431 	  pp->declaration_specifiers (TREE_TYPE (TREE_TYPE (pfm)));
   1432 	  pp_cxx_whitespace (pp);
   1433 	  pp_cxx_ptr_operator (pp, t);
   1434 	  break;
   1435 	}
   1436       /* fall through */
   1437 
   1438     case OFFSET_TYPE:
   1439       if (TYPE_PTRDATAMEM_P (t))
   1440 	{
   1441 	  pp_cxx_type_specifier_seq (pp, TREE_TYPE (t));
   1442 	  pp_cxx_whitespace (pp);
   1443 	  pp_cxx_ptr_operator (pp, t);
   1444 	  break;
   1445 	}
   1446       /* fall through */
   1447 
   1448     default:
   1449       if (!(TREE_CODE (t) == FUNCTION_DECL && DECL_CONSTRUCTOR_P (t)))
   1450 	pp_c_specifier_qualifier_list (pp, t);
   1451     }
   1452 }
   1453 
   1454 /* ptr-operator:
   1455       * cv-qualifier-seq(opt)
   1456       &
   1457       ::(opt) nested-name-specifier * cv-qualifier-seq(opt)  */
   1458 
   1459 static void
   1460 pp_cxx_ptr_operator (cxx_pretty_printer *pp, tree t)
   1461 {
   1462   if (!TYPE_P (t) && TREE_CODE (t) != TYPE_DECL)
   1463     t = TREE_TYPE (t);
   1464   switch (TREE_CODE (t))
   1465     {
   1466     case REFERENCE_TYPE:
   1467     case POINTER_TYPE:
   1468       if (TYPE_PTR_OR_PTRMEM_P (TREE_TYPE (t)))
   1469 	pp_cxx_ptr_operator (pp, TREE_TYPE (t));
   1470       pp_c_attributes_display (pp, TYPE_ATTRIBUTES (TREE_TYPE (t)));
   1471       if (TYPE_PTR_P (t))
   1472 	{
   1473 	  pp_star (pp);
   1474 	  pp_cxx_cv_qualifier_seq (pp, t);
   1475 	}
   1476       else
   1477 	pp_ampersand (pp);
   1478       break;
   1479 
   1480     case RECORD_TYPE:
   1481       if (TYPE_PTRMEMFUNC_P (t))
   1482 	{
   1483 	  pp_cxx_left_paren (pp);
   1484 	  pp_cxx_nested_name_specifier (pp, TYPE_PTRMEMFUNC_OBJECT_TYPE (t));
   1485 	  pp_star (pp);
   1486 	  break;
   1487 	}
   1488       /* FALLTHRU */
   1489     case OFFSET_TYPE:
   1490       if (TYPE_PTRMEM_P (t))
   1491 	{
   1492 	  if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
   1493 	    pp_cxx_left_paren (pp);
   1494 	  pp_cxx_nested_name_specifier (pp, TYPE_PTRMEM_CLASS_TYPE (t));
   1495 	  pp_star (pp);
   1496 	  pp_cxx_cv_qualifier_seq (pp, t);
   1497 	  break;
   1498 	}
   1499       /* fall through.  */
   1500 
   1501     default:
   1502       pp_unsupported_tree (pp, t);
   1503       break;
   1504     }
   1505 }
   1506 
   1507 static inline tree
   1508 pp_cxx_implicit_parameter_type (tree mf)
   1509 {
   1510   return class_of_this_parm (TREE_TYPE (mf));
   1511 }
   1512 
   1513 /*
   1514    parameter-declaration:
   1515       decl-specifier-seq declarator
   1516       decl-specifier-seq declarator = assignment-expression
   1517       decl-specifier-seq abstract-declarator(opt)
   1518       decl-specifier-seq abstract-declarator(opt) assignment-expression  */
   1519 
   1520 static inline void
   1521 pp_cxx_parameter_declaration (cxx_pretty_printer *pp, tree t)
   1522 {
   1523   pp->declaration_specifiers (t);
   1524   if (TYPE_P (t))
   1525     pp->abstract_declarator (t);
   1526   else
   1527     pp->declarator (t);
   1528 }
   1529 
   1530 /* parameter-declaration-clause:
   1531       parameter-declaration-list(opt) ...(opt)
   1532       parameter-declaration-list , ...
   1533 
   1534    parameter-declaration-list:
   1535       parameter-declaration
   1536       parameter-declaration-list , parameter-declaration  */
   1537 
   1538 static void
   1539 pp_cxx_parameter_declaration_clause (cxx_pretty_printer *pp, tree t)
   1540 {
   1541   gcc_assert (FUNC_OR_METHOD_TYPE_P (t) || TREE_CODE (t) == FUNCTION_DECL);
   1542   tree types, args;
   1543   if (TYPE_P (t))
   1544     {
   1545       types = TYPE_ARG_TYPES (t);
   1546       args = NULL_TREE;
   1547     }
   1548   else
   1549     {
   1550       types = FUNCTION_FIRST_USER_PARMTYPE (t);
   1551       args = FUNCTION_FIRST_USER_PARM (t);
   1552     }
   1553   bool abstract = !args || (pp->flags & pp_c_flag_abstract);
   1554 
   1555   /* Skip artificial parameter for non-static member functions.  */
   1556   if (TREE_CODE (t) == METHOD_TYPE)
   1557     types = TREE_CHAIN (types);
   1558 
   1559   bool first = true;
   1560   pp_cxx_left_paren (pp);
   1561   for (; types != void_list_node; types = TREE_CHAIN (types))
   1562     {
   1563       if (!first)
   1564 	pp_cxx_separate_with (pp, ',');
   1565       first = false;
   1566       if (!types)
   1567 	{
   1568 	  pp_cxx_ws_string (pp, "...");
   1569 	  break;
   1570 	}
   1571       pp_cxx_parameter_declaration (pp, abstract ? TREE_VALUE (types) : args);
   1572       if (!abstract && pp->flags & pp_cxx_flag_default_argument)
   1573 	{
   1574 	  pp_cxx_whitespace (pp);
   1575 	  pp_equal (pp);
   1576 	  pp_cxx_whitespace (pp);
   1577 	  pp->assignment_expression (TREE_PURPOSE (types));
   1578 	}
   1579       if (!abstract)
   1580 	args = TREE_CHAIN (args);
   1581     }
   1582   pp_cxx_right_paren (pp);
   1583 }
   1584 
   1585 /* exception-specification:
   1586       throw ( type-id-list(opt) )
   1587 
   1588    type-id-list
   1589       type-id
   1590       type-id-list , type-id   */
   1591 
   1592 static void
   1593 pp_cxx_exception_specification (cxx_pretty_printer *pp, tree t)
   1594 {
   1595   tree ex_spec = TYPE_RAISES_EXCEPTIONS (t);
   1596   bool need_comma = false;
   1597 
   1598   if (ex_spec == NULL)
   1599     return;
   1600   if (TREE_PURPOSE (ex_spec))
   1601     {
   1602       pp_cxx_ws_string (pp, "noexcept");
   1603       pp_cxx_whitespace (pp);
   1604       pp_cxx_left_paren (pp);
   1605       if (DEFERRED_NOEXCEPT_SPEC_P (ex_spec))
   1606 	pp_cxx_ws_string (pp, "<uninstantiated>");
   1607       else
   1608 	pp->expression (TREE_PURPOSE (ex_spec));
   1609       pp_cxx_right_paren (pp);
   1610       return;
   1611     }
   1612   pp_cxx_ws_string (pp, "throw");
   1613   pp_cxx_left_paren (pp);
   1614   for (; ex_spec && TREE_VALUE (ex_spec); ex_spec = TREE_CHAIN (ex_spec))
   1615     {
   1616       tree type = TREE_VALUE (ex_spec);
   1617       tree argpack = NULL_TREE;
   1618       int i, len = 1;
   1619 
   1620       if (ARGUMENT_PACK_P (type))
   1621 	{
   1622 	  argpack = ARGUMENT_PACK_ARGS (type);
   1623 	  len = TREE_VEC_LENGTH (argpack);
   1624 	}
   1625 
   1626       for (i = 0; i < len; ++i)
   1627 	{
   1628 	  if (argpack)
   1629 	    type = TREE_VEC_ELT (argpack, i);
   1630 
   1631 	  if (need_comma)
   1632 	    pp_cxx_separate_with (pp, ',');
   1633 	  else
   1634 	    need_comma = true;
   1635 
   1636 	  pp->type_id (type);
   1637 	}
   1638     }
   1639   pp_cxx_right_paren (pp);
   1640 }
   1641 
   1642 /* direct-declarator:
   1643       declarator-id
   1644       direct-declarator ( parameter-declaration-clause ) cv-qualifier-seq(opt)
   1645 					    exception-specification(opt)
   1646       direct-declaration [ constant-expression(opt) ]
   1647       ( declarator )  */
   1648 
   1649 void
   1650 cxx_pretty_printer::direct_declarator (tree t)
   1651 {
   1652   switch (TREE_CODE (t))
   1653     {
   1654     case VAR_DECL:
   1655     case PARM_DECL:
   1656     case CONST_DECL:
   1657     case FIELD_DECL:
   1658       if (DECL_NAME (t))
   1659 	{
   1660 	  pp_cxx_space_for_pointer_operator (this, TREE_TYPE (t));
   1661 
   1662 	  if ((TREE_CODE (t) == PARM_DECL && DECL_PACK_P (t))
   1663 	      || template_parameter_pack_p (t))
   1664 	    /* A function parameter pack or non-type template
   1665 	       parameter pack.  */
   1666 	    pp_cxx_ws_string (this, "...");
   1667 
   1668 	  id_expression (DECL_NAME (t));
   1669 	}
   1670       abstract_declarator (TREE_TYPE (t));
   1671       break;
   1672 
   1673     case FUNCTION_DECL:
   1674       pp_cxx_space_for_pointer_operator (this, TREE_TYPE (TREE_TYPE (t)));
   1675       expression (t);
   1676       pp_cxx_parameter_declaration_clause (this, t);
   1677 
   1678       if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
   1679 	{
   1680 	  padding = pp_before;
   1681 	  pp_cxx_cv_qualifier_seq (this, pp_cxx_implicit_parameter_type (t));
   1682 	}
   1683 
   1684       pp_cxx_exception_specification (this, TREE_TYPE (t));
   1685       break;
   1686 
   1687     case TYPENAME_TYPE:
   1688     case TEMPLATE_DECL:
   1689     case TEMPLATE_TYPE_PARM:
   1690     case TEMPLATE_PARM_INDEX:
   1691     case TEMPLATE_TEMPLATE_PARM:
   1692       break;
   1693 
   1694     default:
   1695       c_pretty_printer::direct_declarator (t);
   1696       break;
   1697     }
   1698 }
   1699 
   1700 /* declarator:
   1701    direct-declarator
   1702    ptr-operator declarator  */
   1703 
   1704 void
   1705 cxx_pretty_printer::declarator (tree t)
   1706 {
   1707   direct_declarator (t);
   1708 
   1709   // Print a requires clause.
   1710   if (flag_concepts)
   1711     if (tree ci = get_constraints (t))
   1712       if (tree reqs = CI_DECLARATOR_REQS (ci))
   1713         pp_cxx_requires_clause (this, reqs);
   1714 }
   1715 
   1716 /* ctor-initializer:
   1717       : mem-initializer-list
   1718 
   1719    mem-initializer-list:
   1720       mem-initializer
   1721       mem-initializer , mem-initializer-list
   1722 
   1723    mem-initializer:
   1724       mem-initializer-id ( expression-list(opt) )
   1725 
   1726    mem-initializer-id:
   1727       ::(opt) nested-name-specifier(opt) class-name
   1728       identifier   */
   1729 
   1730 static void
   1731 pp_cxx_ctor_initializer (cxx_pretty_printer *pp, tree t)
   1732 {
   1733   t = TREE_OPERAND (t, 0);
   1734   pp_cxx_whitespace (pp);
   1735   pp_colon (pp);
   1736   pp_cxx_whitespace (pp);
   1737   for (; t; t = TREE_CHAIN (t))
   1738     {
   1739       tree purpose = TREE_PURPOSE (t);
   1740       bool is_pack = PACK_EXPANSION_P (purpose);
   1741 
   1742       if (is_pack)
   1743 	pp->primary_expression (PACK_EXPANSION_PATTERN (purpose));
   1744       else
   1745 	pp->primary_expression (purpose);
   1746       pp_cxx_call_argument_list (pp, TREE_VALUE (t));
   1747       if (is_pack)
   1748 	pp_cxx_ws_string (pp, "...");
   1749       if (TREE_CHAIN (t))
   1750 	pp_cxx_separate_with (pp, ',');
   1751     }
   1752 }
   1753 
   1754 /* function-definition:
   1755       decl-specifier-seq(opt) declarator ctor-initializer(opt) function-body
   1756       decl-specifier-seq(opt) declarator function-try-block  */
   1757 
   1758 static void
   1759 pp_cxx_function_definition (cxx_pretty_printer *pp, tree t)
   1760 {
   1761   tree saved_scope = pp->enclosing_scope;
   1762   pp->declaration_specifiers (t);
   1763   pp->declarator (t);
   1764   pp_needs_newline (pp) = true;
   1765   pp->enclosing_scope = DECL_CONTEXT (t);
   1766   if (DECL_SAVED_TREE (t))
   1767     pp->statement (DECL_SAVED_TREE (t));
   1768   else
   1769     pp_cxx_semicolon (pp);
   1770   pp_newline_and_flush (pp);
   1771   pp->enclosing_scope = saved_scope;
   1772 }
   1773 
   1774 /* abstract-declarator:
   1775       ptr-operator abstract-declarator(opt)
   1776       direct-abstract-declarator  */
   1777 
   1778 void
   1779 cxx_pretty_printer::abstract_declarator (tree t)
   1780 {
   1781   /* pp_cxx_ptr_operator prints '(' for a pointer-to-member function,
   1782      or a pointer-to-data-member of array type:
   1783 
   1784        void (X::*)()
   1785        int (X::*)[5]
   1786 
   1787      but not for a pointer-to-data-member of non-array type:
   1788 
   1789        int X::*
   1790 
   1791      so be mindful of that.  */
   1792   if (TYPE_PTRMEMFUNC_P (t)
   1793       || (TYPE_PTRDATAMEM_P (t)
   1794 	  && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE))
   1795     pp_cxx_right_paren (this);
   1796   else if (INDIRECT_TYPE_P (t))
   1797     {
   1798       if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE
   1799 	  || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
   1800 	pp_cxx_right_paren (this);
   1801       t = TREE_TYPE (t);
   1802     }
   1803   direct_abstract_declarator (t);
   1804 }
   1805 
   1806 /* direct-abstract-declarator:
   1807       direct-abstract-declarator(opt) ( parameter-declaration-clause )
   1808 			   cv-qualifier-seq(opt) exception-specification(opt)
   1809       direct-abstract-declarator(opt) [ constant-expression(opt) ]
   1810       ( abstract-declarator )  */
   1811 
   1812 void
   1813 cxx_pretty_printer::direct_abstract_declarator (tree t)
   1814 {
   1815   switch (TREE_CODE (t))
   1816     {
   1817     case REFERENCE_TYPE:
   1818       abstract_declarator (t);
   1819       break;
   1820 
   1821     case RECORD_TYPE:
   1822       if (TYPE_PTRMEMFUNC_P (t))
   1823 	direct_abstract_declarator (TYPE_PTRMEMFUNC_FN_TYPE (t));
   1824       break;
   1825 
   1826     case OFFSET_TYPE:
   1827       if (TYPE_PTRDATAMEM_P (t))
   1828 	direct_abstract_declarator (TREE_TYPE (t));
   1829       break;
   1830 
   1831     case METHOD_TYPE:
   1832     case FUNCTION_TYPE:
   1833       pp_cxx_parameter_declaration_clause (this, t);
   1834       direct_abstract_declarator (TREE_TYPE (t));
   1835       if (TREE_CODE (t) == METHOD_TYPE)
   1836 	{
   1837 	  padding = pp_before;
   1838 	  pp_cxx_cv_qualifier_seq (this, class_of_this_parm (t));
   1839 	}
   1840       pp_cxx_exception_specification (this, t);
   1841       break;
   1842 
   1843     case TYPENAME_TYPE:
   1844     case TEMPLATE_TYPE_PARM:
   1845     case TEMPLATE_TEMPLATE_PARM:
   1846     case BOUND_TEMPLATE_TEMPLATE_PARM:
   1847     case UNBOUND_CLASS_TEMPLATE:
   1848     case DECLTYPE_TYPE:
   1849       break;
   1850 
   1851     default:
   1852       c_pretty_printer::direct_abstract_declarator (t);
   1853       break;
   1854     }
   1855 }
   1856 
   1857 /* type-id:
   1858      type-specifier-seq abstract-declarator(opt) */
   1859 
   1860 void
   1861 cxx_pretty_printer::type_id (tree t)
   1862 {
   1863   pp_flags saved_flags = flags;
   1864   flags |= pp_c_flag_abstract;
   1865 
   1866   switch (TREE_CODE (t))
   1867     {
   1868     case TYPE_DECL:
   1869     case UNION_TYPE:
   1870     case RECORD_TYPE:
   1871     case ENUMERAL_TYPE:
   1872     case TYPENAME_TYPE:
   1873     case BOUND_TEMPLATE_TEMPLATE_PARM:
   1874     case UNBOUND_CLASS_TEMPLATE:
   1875     case TEMPLATE_TEMPLATE_PARM:
   1876     case TEMPLATE_TYPE_PARM:
   1877     case TEMPLATE_PARM_INDEX:
   1878     case TEMPLATE_DECL:
   1879     case TYPEOF_TYPE:
   1880     case UNDERLYING_TYPE:
   1881     case DECLTYPE_TYPE:
   1882     case NULLPTR_TYPE:
   1883     case TEMPLATE_ID_EXPR:
   1884     case OFFSET_TYPE:
   1885       pp_cxx_type_specifier_seq (this, t);
   1886       if (TYPE_PTRMEM_P (t))
   1887 	abstract_declarator (t);
   1888       break;
   1889 
   1890     case TYPE_PACK_EXPANSION:
   1891       type_id (PACK_EXPANSION_PATTERN (t));
   1892       pp_cxx_ws_string (this, "...");
   1893       break;
   1894 
   1895     case TYPE_ARGUMENT_PACK:
   1896       {
   1897 	tree args = ARGUMENT_PACK_ARGS (t);
   1898 	int len = TREE_VEC_LENGTH (args);
   1899 	pp_cxx_left_brace (this);
   1900 	for (int i = 0; i < len; ++i)
   1901 	  {
   1902 	    if (i > 0)
   1903 	      pp_cxx_separate_with (this, ',');
   1904 	    type_id (TREE_VEC_ELT (args, i));
   1905 	  }
   1906 	pp_cxx_right_brace (this);
   1907       }
   1908       break;
   1909 
   1910     default:
   1911       c_pretty_printer::type_id (t);
   1912       break;
   1913     }
   1914 
   1915   flags = saved_flags;
   1916 }
   1917 
   1918 /* template-argument-list:
   1919       template-argument ...(opt)
   1920       template-argument-list, template-argument ...(opt)
   1921 
   1922    template-argument:
   1923       assignment-expression
   1924       type-id
   1925       template-name  */
   1926 
   1927 static void
   1928 pp_cxx_template_argument_list (cxx_pretty_printer *pp, tree t)
   1929 {
   1930   int i;
   1931   bool need_comma = false;
   1932 
   1933   if (t == NULL)
   1934     return;
   1935   for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
   1936     {
   1937       tree arg = TREE_VEC_ELT (t, i);
   1938       tree argpack = NULL_TREE;
   1939       int idx, len = 1;
   1940 
   1941       if (ARGUMENT_PACK_P (arg))
   1942 	{
   1943 	  argpack = ARGUMENT_PACK_ARGS (arg);
   1944 	  len = TREE_VEC_LENGTH (argpack);
   1945 	}
   1946 
   1947       for (idx = 0; idx < len; idx++)
   1948 	{
   1949 	  if (argpack)
   1950 	    arg = TREE_VEC_ELT (argpack, idx);
   1951 
   1952 	  if (need_comma)
   1953 	    pp_cxx_separate_with (pp, ',');
   1954 	  else
   1955 	    need_comma = true;
   1956 
   1957 	  if (TYPE_P (arg) || (TREE_CODE (arg) == TEMPLATE_DECL
   1958 			       && TYPE_P (DECL_TEMPLATE_RESULT (arg))))
   1959 	    pp->type_id (arg);
   1960 	  else if (template_parm_object_p (arg))
   1961 	    pp->expression (DECL_INITIAL (arg));
   1962 	  else
   1963 	    pp->expression (arg);
   1964 	}
   1965     }
   1966 }
   1967 
   1968 
   1969 static void
   1970 pp_cxx_exception_declaration (cxx_pretty_printer *pp, tree t)
   1971 {
   1972   t = DECL_EXPR_DECL (t);
   1973   pp_cxx_type_specifier_seq (pp, t);
   1974   if (TYPE_P (t))
   1975     pp->abstract_declarator (t);
   1976   else
   1977     pp->declarator (t);
   1978 }
   1979 
   1980 /* Statements.  */
   1981 
   1982 void
   1983 cxx_pretty_printer::statement (tree t)
   1984 {
   1985   switch (TREE_CODE (t))
   1986     {
   1987     case CTOR_INITIALIZER:
   1988       pp_cxx_ctor_initializer (this, t);
   1989       break;
   1990 
   1991     case USING_STMT:
   1992       pp_cxx_ws_string (this, "using");
   1993       pp_cxx_ws_string (this, "namespace");
   1994       if (DECL_CONTEXT (t))
   1995 	pp_cxx_nested_name_specifier (this, DECL_CONTEXT (t));
   1996       pp_cxx_qualified_id (this, USING_STMT_NAMESPACE (t));
   1997       break;
   1998 
   1999     case USING_DECL:
   2000       pp_cxx_ws_string (this, "using");
   2001       pp_cxx_nested_name_specifier (this, USING_DECL_SCOPE (t));
   2002       pp_cxx_unqualified_id (this, DECL_NAME (t));
   2003       break;
   2004 
   2005     case EH_SPEC_BLOCK:
   2006       break;
   2007 
   2008       /* try-block:
   2009 	    try compound-statement handler-seq  */
   2010     case TRY_BLOCK:
   2011       pp_maybe_newline_and_indent (this, 0);
   2012       pp_cxx_ws_string (this, "try");
   2013       pp_newline_and_indent (this, 3);
   2014       statement (TRY_STMTS (t));
   2015       pp_newline_and_indent (this, -3);
   2016       if (CLEANUP_P (t))
   2017 	;
   2018       else
   2019 	statement (TRY_HANDLERS (t));
   2020       break;
   2021 
   2022       /*
   2023 	 handler-seq:
   2024 	    handler handler-seq(opt)
   2025 
   2026 	 handler:
   2027 	 catch ( exception-declaration ) compound-statement
   2028 
   2029 	 exception-declaration:
   2030 	    type-specifier-seq declarator
   2031 	    type-specifier-seq abstract-declarator
   2032 	    ...   */
   2033     case HANDLER:
   2034       pp_cxx_ws_string (this, "catch");
   2035       pp_cxx_left_paren (this);
   2036       pp_cxx_exception_declaration (this, HANDLER_PARMS (t));
   2037       pp_cxx_right_paren (this);
   2038       pp_indentation (this) += 3;
   2039       pp_needs_newline (this) = true;
   2040       statement (HANDLER_BODY (t));
   2041       pp_indentation (this) -= 3;
   2042       pp_needs_newline (this) = true;
   2043       break;
   2044 
   2045       /* selection-statement:
   2046 	    if ( expression ) statement
   2047 	    if ( expression ) statement else statement  */
   2048     case IF_STMT:
   2049       pp_cxx_ws_string (this, "if");
   2050       pp_cxx_whitespace (this);
   2051       pp_cxx_left_paren (this);
   2052       expression (IF_COND (t));
   2053       pp_cxx_right_paren (this);
   2054       pp_newline_and_indent (this, 2);
   2055       statement (THEN_CLAUSE (t));
   2056       pp_newline_and_indent (this, -2);
   2057       if (ELSE_CLAUSE (t))
   2058 	{
   2059 	  tree else_clause = ELSE_CLAUSE (t);
   2060 	  pp_cxx_ws_string (this, "else");
   2061 	  if (TREE_CODE (else_clause) == IF_STMT)
   2062 	    pp_cxx_whitespace (this);
   2063 	  else
   2064 	    pp_newline_and_indent (this, 2);
   2065 	  statement (else_clause);
   2066 	  if (TREE_CODE (else_clause) != IF_STMT)
   2067 	    pp_newline_and_indent (this, -2);
   2068 	}
   2069       break;
   2070 
   2071     case RANGE_FOR_STMT:
   2072       pp_cxx_ws_string (this, "for");
   2073       pp_space (this);
   2074       pp_cxx_left_paren (this);
   2075       if (RANGE_FOR_INIT_STMT (t))
   2076 	{
   2077 	  statement (RANGE_FOR_INIT_STMT (t));
   2078 	  pp_needs_newline (this) = false;
   2079 	  pp_cxx_whitespace (this);
   2080 	}
   2081       statement (RANGE_FOR_DECL (t));
   2082       pp_space (this);
   2083       pp_needs_newline (this) = false;
   2084       pp_colon (this);
   2085       pp_space (this);
   2086       statement (RANGE_FOR_EXPR (t));
   2087       pp_cxx_right_paren (this);
   2088       pp_newline_and_indent (this, 3);
   2089       statement (FOR_BODY (t));
   2090       pp_indentation (this) -= 3;
   2091       pp_needs_newline (this) = true;
   2092       break;
   2093 
   2094       /* expression-statement:
   2095 	    expression(opt) ;  */
   2096     case EXPR_STMT:
   2097       expression (EXPR_STMT_EXPR (t));
   2098       pp_cxx_semicolon (this);
   2099       pp_needs_newline (this) = true;
   2100       break;
   2101 
   2102     case CLEANUP_STMT:
   2103       pp_cxx_ws_string (this, "try");
   2104       pp_newline_and_indent (this, 2);
   2105       statement (CLEANUP_BODY (t));
   2106       pp_newline_and_indent (this, -2);
   2107       pp_cxx_ws_string (this, CLEANUP_EH_ONLY (t) ? "catch" : "finally");
   2108       pp_newline_and_indent (this, 2);
   2109       statement (CLEANUP_EXPR (t));
   2110       pp_newline_and_indent (this, -2);
   2111       break;
   2112 
   2113     case STATIC_ASSERT:
   2114       declaration (t);
   2115       break;
   2116 
   2117     case OMP_DEPOBJ:
   2118       pp_cxx_ws_string (this, "#pragma omp depobj");
   2119       pp_space (this);
   2120       pp_cxx_left_paren (this);
   2121       expression (OMP_DEPOBJ_DEPOBJ (t));
   2122       pp_cxx_right_paren (this);
   2123       if (OMP_DEPOBJ_CLAUSES (t) && OMP_DEPOBJ_CLAUSES (t) != error_mark_node)
   2124 	{
   2125 	  if (TREE_CODE (OMP_DEPOBJ_CLAUSES (t)) == OMP_CLAUSE)
   2126 	    dump_omp_clauses (this, OMP_DEPOBJ_CLAUSES (t),
   2127 			      pp_indentation (this), TDF_NONE);
   2128 	  else
   2129 	    switch (tree_to_uhwi (OMP_DEPOBJ_CLAUSES (t)))
   2130 	      {
   2131 	      case OMP_CLAUSE_DEPEND_IN:
   2132 		pp_cxx_ws_string (this, " update(in)");
   2133 		break;
   2134 	      case OMP_CLAUSE_DEPEND_INOUT:
   2135 		pp_cxx_ws_string (this, " update(inout)");
   2136 		break;
   2137 	      case OMP_CLAUSE_DEPEND_OUT:
   2138 		pp_cxx_ws_string (this, " update(out)");
   2139 		break;
   2140 	      case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
   2141 		pp_cxx_ws_string (this, " update(mutexinoutset)");
   2142 		break;
   2143 	      case OMP_CLAUSE_DEPEND_LAST:
   2144 		pp_cxx_ws_string (this, " destroy");
   2145 		break;
   2146 	      default:
   2147 		break;
   2148 	      }
   2149 	}
   2150       pp_needs_newline (this) = true;
   2151       break;
   2152 
   2153     default:
   2154       c_pretty_printer::statement (t);
   2155       break;
   2156     }
   2157 }
   2158 
   2159 /* original-namespace-definition:
   2160       namespace identifier { namespace-body }
   2161 
   2162   As an edge case, we also handle unnamed namespace definition here.  */
   2163 
   2164 static void
   2165 pp_cxx_original_namespace_definition (cxx_pretty_printer *pp, tree t)
   2166 {
   2167   pp_cxx_ws_string (pp, "namespace");
   2168   if (DECL_CONTEXT (t))
   2169     pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
   2170   if (DECL_NAME (t))
   2171     pp_cxx_unqualified_id (pp, t);
   2172   pp_cxx_whitespace (pp);
   2173   pp_cxx_left_brace (pp);
   2174   /* We do not print the namespace-body.  */
   2175   pp_cxx_whitespace (pp);
   2176   pp_cxx_right_brace (pp);
   2177 }
   2178 
   2179 /* namespace-alias:
   2180       identifier
   2181 
   2182    namespace-alias-definition:
   2183       namespace identifier = qualified-namespace-specifier ;
   2184 
   2185    qualified-namespace-specifier:
   2186       ::(opt) nested-name-specifier(opt) namespace-name   */
   2187 
   2188 static void
   2189 pp_cxx_namespace_alias_definition (cxx_pretty_printer *pp, tree t)
   2190 {
   2191   pp_cxx_ws_string (pp, "namespace");
   2192   if (DECL_CONTEXT (t))
   2193     pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
   2194   pp_cxx_unqualified_id (pp, t);
   2195   pp_cxx_whitespace (pp);
   2196   pp_equal (pp);
   2197   pp_cxx_whitespace (pp);
   2198   if (DECL_CONTEXT (DECL_NAMESPACE_ALIAS (t)))
   2199     pp_cxx_nested_name_specifier (pp,
   2200 				  DECL_CONTEXT (DECL_NAMESPACE_ALIAS (t)));
   2201   pp_cxx_qualified_id (pp, DECL_NAMESPACE_ALIAS (t));
   2202   pp_cxx_semicolon (pp);
   2203 }
   2204 
   2205 /* simple-declaration:
   2206       decl-specifier-seq(opt) init-declarator-list(opt)  */
   2207 
   2208 static void
   2209 pp_cxx_simple_declaration (cxx_pretty_printer *pp, tree t)
   2210 {
   2211   pp->declaration_specifiers (t);
   2212   pp_cxx_init_declarator (pp, t);
   2213   pp_cxx_semicolon (pp);
   2214   pp_needs_newline (pp) = true;
   2215 }
   2216 
   2217 /*
   2218   template-parameter-list:
   2219      template-parameter
   2220      template-parameter-list , template-parameter  */
   2221 
   2222 static inline void
   2223 pp_cxx_template_parameter_list (cxx_pretty_printer *pp, tree t)
   2224 {
   2225   const int n = TREE_VEC_LENGTH (t);
   2226   int i;
   2227   for (i = 0; i < n; ++i)
   2228     {
   2229       if (i)
   2230 	pp_cxx_separate_with (pp, ',');
   2231       pp_cxx_template_parameter (pp, TREE_VEC_ELT (t, i));
   2232     }
   2233 }
   2234 
   2235 /* template-parameter:
   2236       type-parameter
   2237       parameter-declaration
   2238 
   2239    type-parameter:
   2240      class ...(opt) identifier(opt)
   2241      class identifier(opt) = type-id
   2242      typename identifier(opt)
   2243      typename ...(opt) identifier(opt) = type-id
   2244      template < template-parameter-list > class ...(opt) identifier(opt)
   2245      template < template-parameter-list > class identifier(opt) = template-name  */
   2246 
   2247 static void
   2248 pp_cxx_template_parameter (cxx_pretty_printer *pp, tree t)
   2249 {
   2250   tree parameter =  TREE_VALUE (t);
   2251   switch (TREE_CODE (parameter))
   2252     {
   2253     case TYPE_DECL:
   2254       pp_cxx_ws_string (pp, "class");
   2255       if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (t)))
   2256 	pp_cxx_ws_string (pp, "...");
   2257       if (DECL_NAME (parameter))
   2258 	pp_cxx_tree_identifier (pp, DECL_NAME (parameter));
   2259       /* FIXME: Check if we should print also default argument.  */
   2260       break;
   2261 
   2262     case PARM_DECL:
   2263       pp_cxx_parameter_declaration (pp, parameter);
   2264       break;
   2265 
   2266     case TEMPLATE_DECL:
   2267       break;
   2268 
   2269     default:
   2270       pp_unsupported_tree (pp, t);
   2271       break;
   2272     }
   2273 }
   2274 
   2275 /* Pretty-print a template parameter in the canonical form
   2276    "template-parameter-<level>-<position in parameter list>".  */
   2277 
   2278 void
   2279 pp_cxx_canonical_template_parameter (cxx_pretty_printer *pp, tree parm)
   2280 {
   2281   const enum tree_code code = TREE_CODE (parm);
   2282 
   2283   /* Brings type template parameters to the canonical forms.  */
   2284   if (code == TEMPLATE_TYPE_PARM || code == TEMPLATE_TEMPLATE_PARM
   2285       || code == BOUND_TEMPLATE_TEMPLATE_PARM)
   2286     parm = TEMPLATE_TYPE_PARM_INDEX (parm);
   2287 
   2288   pp_cxx_begin_template_argument_list (pp);
   2289   pp->translate_string ("template-parameter-");
   2290   pp_wide_integer (pp, TEMPLATE_PARM_LEVEL (parm));
   2291   pp_minus (pp);
   2292   pp_wide_integer (pp, TEMPLATE_PARM_IDX (parm) + 1);
   2293   pp_cxx_end_template_argument_list (pp);
   2294 }
   2295 
   2296 /* Print a constrained-type-specifier.  */
   2297 
   2298 void
   2299 pp_cxx_constrained_type_spec (cxx_pretty_printer *pp, tree c)
   2300 {
   2301   pp_cxx_whitespace (pp);
   2302   pp_cxx_left_bracket (pp);
   2303   pp->translate_string ("requires");
   2304   pp_cxx_whitespace (pp);
   2305   if (c == error_mark_node)
   2306     {
   2307       pp_cxx_ws_string(pp, "<unsatisfied-type-constraint>");
   2308       return;
   2309     }
   2310   tree t, a;
   2311   placeholder_extract_concept_and_args (c, t, a);
   2312   pp->id_expression (t);
   2313   pp_cxx_begin_template_argument_list (pp);
   2314   pp_cxx_ws_string (pp, "<placeholder>");
   2315   pp_cxx_separate_with (pp, ',');
   2316   tree args = make_tree_vec (TREE_VEC_LENGTH (a) - 1);
   2317   for (int i = 0; i < TREE_VEC_LENGTH (a) - 1; ++i)
   2318     TREE_VEC_ELT (args, i) = TREE_VEC_ELT (a, i + 1);
   2319   pp_cxx_template_argument_list (pp, args);
   2320   ggc_free (args);
   2321   pp_cxx_end_template_argument_list (pp);
   2322   pp_cxx_right_bracket (pp);
   2323 }
   2324 
   2325 /*
   2326   template-declaration:
   2327      export(opt) template < template-parameter-list > declaration
   2328 
   2329   Concept extensions:
   2330 
   2331   template-declaration:
   2332      export(opt) template < template-parameter-list >
   2333        requires-clause(opt) declaration */
   2334 
   2335 static void
   2336 pp_cxx_template_declaration (cxx_pretty_printer *pp, tree t)
   2337 {
   2338   tree tmpl = most_general_template (t);
   2339   tree level;
   2340 
   2341   pp_maybe_newline_and_indent (pp, 0);
   2342   for (level = DECL_TEMPLATE_PARMS (tmpl); level; level = TREE_CHAIN (level))
   2343     {
   2344       pp_cxx_ws_string (pp, "template");
   2345       pp_cxx_begin_template_argument_list (pp);
   2346       pp_cxx_template_parameter_list (pp, TREE_VALUE (level));
   2347       pp_cxx_end_template_argument_list (pp);
   2348       pp_newline_and_indent (pp, 3);
   2349     }
   2350 
   2351   if (flag_concepts)
   2352     if (tree ci = get_constraints (t))
   2353       if (tree reqs = CI_TEMPLATE_REQS (ci))
   2354          {
   2355             pp_cxx_requires_clause (pp, reqs);
   2356             pp_newline_and_indent (pp, 6);
   2357          }
   2358 
   2359   if (TREE_CODE (t) == FUNCTION_DECL && DECL_SAVED_TREE (t))
   2360     pp_cxx_function_definition (pp, t);
   2361   else if (TREE_CODE (t) == CONCEPT_DECL)
   2362     pp_cxx_concept_definition (pp, t);
   2363   else
   2364     pp_cxx_simple_declaration (pp, t);
   2365 }
   2366 
   2367 static void
   2368 pp_cxx_explicit_specialization (cxx_pretty_printer *pp, tree t)
   2369 {
   2370   pp_unsupported_tree (pp, t);
   2371 }
   2372 
   2373 static void
   2374 pp_cxx_explicit_instantiation (cxx_pretty_printer *pp, tree t)
   2375 {
   2376   pp_unsupported_tree (pp, t);
   2377 }
   2378 
   2379 static void
   2380 pp_cxx_concept_definition (cxx_pretty_printer *pp, tree t)
   2381 {
   2382   pp_cxx_unqualified_id (pp, DECL_NAME (t));
   2383   pp_cxx_whitespace (pp);
   2384   pp_cxx_ws_string (pp, "=");
   2385   pp_cxx_whitespace (pp);
   2386   pp->expression (DECL_INITIAL (t));
   2387   pp_cxx_semicolon (pp);
   2388 }
   2389 
   2390 /*
   2391     declaration:
   2392        block-declaration
   2393        function-definition
   2394        template-declaration
   2395        explicit-instantiation
   2396        explicit-specialization
   2397        linkage-specification
   2398        namespace-definition
   2399 
   2400     block-declaration:
   2401        simple-declaration
   2402        asm-definition
   2403        namespace-alias-definition
   2404        using-declaration
   2405        using-directive
   2406        static_assert-declaration */
   2407 void
   2408 cxx_pretty_printer::declaration (tree t)
   2409 {
   2410   if (TREE_CODE (t) == STATIC_ASSERT)
   2411     {
   2412       pp_cxx_ws_string (this, "static_assert");
   2413       pp_cxx_left_paren (this);
   2414       expression (STATIC_ASSERT_CONDITION (t));
   2415       pp_cxx_separate_with (this, ',');
   2416       expression (STATIC_ASSERT_MESSAGE (t));
   2417       pp_cxx_right_paren (this);
   2418     }
   2419   else if (!DECL_LANG_SPECIFIC (t))
   2420     pp_cxx_simple_declaration (this, t);
   2421   else if (DECL_USE_TEMPLATE (t))
   2422     switch (DECL_USE_TEMPLATE (t))
   2423       {
   2424       case 1:
   2425 	pp_cxx_template_declaration (this, t);
   2426 	break;
   2427 
   2428       case 2:
   2429 	pp_cxx_explicit_specialization (this, t);
   2430 	break;
   2431 
   2432       case 3:
   2433 	pp_cxx_explicit_instantiation (this, t);
   2434 	break;
   2435 
   2436       default:
   2437 	break;
   2438       }
   2439   else switch (TREE_CODE (t))
   2440     {
   2441     case VAR_DECL:
   2442     case TYPE_DECL:
   2443       pp_cxx_simple_declaration (this, t);
   2444       break;
   2445 
   2446     case FUNCTION_DECL:
   2447       if (DECL_SAVED_TREE (t))
   2448 	pp_cxx_function_definition (this, t);
   2449       else
   2450 	pp_cxx_simple_declaration (this, t);
   2451       break;
   2452 
   2453     case NAMESPACE_DECL:
   2454       if (DECL_NAMESPACE_ALIAS (t))
   2455 	pp_cxx_namespace_alias_definition (this, t);
   2456       else
   2457 	pp_cxx_original_namespace_definition (this, t);
   2458       break;
   2459 
   2460     default:
   2461       pp_unsupported_tree (this, t);
   2462       break;
   2463     }
   2464 }
   2465 
   2466 static void
   2467 pp_cxx_typeid_expression (cxx_pretty_printer *pp, tree t)
   2468 {
   2469   t = TREE_OPERAND (t, 0);
   2470   pp_cxx_ws_string (pp, "typeid");
   2471   pp_cxx_left_paren (pp);
   2472   if (TYPE_P (t))
   2473     pp->type_id (t);
   2474   else
   2475     pp->expression (t);
   2476   pp_cxx_right_paren (pp);
   2477 }
   2478 
   2479 void
   2480 pp_cxx_va_arg_expression (cxx_pretty_printer *pp, tree t)
   2481 {
   2482   pp_cxx_ws_string (pp, "va_arg");
   2483   pp_cxx_left_paren (pp);
   2484   pp->assignment_expression (TREE_OPERAND (t, 0));
   2485   pp_cxx_separate_with (pp, ',');
   2486   pp->type_id (TREE_TYPE (t));
   2487   pp_cxx_right_paren (pp);
   2488 }
   2489 
   2490 static bool
   2491 pp_cxx_offsetof_expression_1 (cxx_pretty_printer *pp, tree t)
   2492 {
   2493   switch (TREE_CODE (t))
   2494     {
   2495     case ARROW_EXPR:
   2496       if (TREE_CODE (TREE_OPERAND (t, 0)) == STATIC_CAST_EXPR
   2497 	  && INDIRECT_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0))))
   2498 	{
   2499 	  pp->type_id (TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0))));
   2500 	  pp_cxx_separate_with (pp, ',');
   2501 	  return true;
   2502 	}
   2503       return false;
   2504     case COMPONENT_REF:
   2505       if (!pp_cxx_offsetof_expression_1 (pp, TREE_OPERAND (t, 0)))
   2506 	return false;
   2507       if (TREE_CODE (TREE_OPERAND (t, 0)) != ARROW_EXPR)
   2508 	pp_cxx_dot (pp);
   2509       pp->expression (TREE_OPERAND (t, 1));
   2510       return true;
   2511     case ARRAY_REF:
   2512       if (!pp_cxx_offsetof_expression_1 (pp, TREE_OPERAND (t, 0)))
   2513 	return false;
   2514       pp_left_bracket (pp);
   2515       pp->expression (TREE_OPERAND (t, 1));
   2516       pp_right_bracket (pp);
   2517       return true;
   2518     default:
   2519       return false;
   2520     }
   2521 }
   2522 
   2523 void
   2524 pp_cxx_offsetof_expression (cxx_pretty_printer *pp, tree t)
   2525 {
   2526   pp_cxx_ws_string (pp, "offsetof");
   2527   pp_cxx_left_paren (pp);
   2528   if (!pp_cxx_offsetof_expression_1 (pp, TREE_OPERAND (t, 0)))
   2529     pp->expression (TREE_OPERAND (t, 0));
   2530   pp_cxx_right_paren (pp);
   2531 }
   2532 
   2533 void
   2534 pp_cxx_addressof_expression (cxx_pretty_printer *pp, tree t)
   2535 {
   2536   pp_cxx_ws_string (pp, "__builtin_addressof");
   2537   pp_cxx_left_paren (pp);
   2538   pp->expression (TREE_OPERAND (t, 0));
   2539   pp_cxx_right_paren (pp);
   2540 }
   2541 
   2542 static char const*
   2543 get_fold_operator (tree t)
   2544 {
   2545   ovl_op_info_t *info = OVL_OP_INFO (FOLD_EXPR_MODIFY_P (t),
   2546 				     FOLD_EXPR_OP (t));
   2547   return info->name;
   2548 }
   2549 
   2550 void
   2551 pp_cxx_unary_left_fold_expression (cxx_pretty_printer *pp, tree t)
   2552 {
   2553   char const* op = get_fold_operator (t);
   2554   tree expr = PACK_EXPANSION_PATTERN (FOLD_EXPR_PACK (t));
   2555   pp_cxx_left_paren (pp);
   2556   pp_cxx_ws_string (pp, "...");
   2557   pp_cxx_ws_string (pp, op);
   2558   pp->expression (expr);
   2559   pp_cxx_right_paren (pp);
   2560 }
   2561 
   2562 void
   2563 pp_cxx_unary_right_fold_expression (cxx_pretty_printer *pp, tree t)
   2564 {
   2565   char const* op = get_fold_operator (t);
   2566   tree expr = PACK_EXPANSION_PATTERN (FOLD_EXPR_PACK (t));
   2567   pp_cxx_left_paren (pp);
   2568   pp->expression (expr);
   2569   pp_space (pp);
   2570   pp_cxx_ws_string (pp, op);
   2571   pp_cxx_ws_string (pp, "...");
   2572   pp_cxx_right_paren (pp);
   2573 }
   2574 
   2575 void
   2576 pp_cxx_binary_fold_expression (cxx_pretty_printer *pp, tree t)
   2577 {
   2578   char const* op = get_fold_operator (t);
   2579   tree t1 = TREE_OPERAND (t, 1);
   2580   tree t2 = TREE_OPERAND (t, 2);
   2581   if (t1 == FOLD_EXPR_PACK (t))
   2582     t1 = PACK_EXPANSION_PATTERN (t1);
   2583   else
   2584     t2 = PACK_EXPANSION_PATTERN (t2);
   2585   pp_cxx_left_paren (pp);
   2586   pp->expression (t1);
   2587   pp_cxx_ws_string (pp, op);
   2588   pp_cxx_ws_string (pp, "...");
   2589   pp_cxx_ws_string (pp, op);
   2590   pp->expression (t2);
   2591   pp_cxx_right_paren (pp);
   2592 }
   2593 
   2594 void
   2595 pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t)
   2596 {
   2597   cp_trait_kind kind = TRAIT_EXPR_KIND (t);
   2598 
   2599   switch (kind)
   2600     {
   2601     case CPTK_HAS_NOTHROW_ASSIGN:
   2602       pp_cxx_ws_string (pp, "__has_nothrow_assign");
   2603       break;
   2604     case CPTK_HAS_TRIVIAL_ASSIGN:
   2605       pp_cxx_ws_string (pp, "__has_trivial_assign");
   2606       break;
   2607     case CPTK_HAS_NOTHROW_CONSTRUCTOR:
   2608       pp_cxx_ws_string (pp, "__has_nothrow_constructor");
   2609       break;
   2610     case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
   2611       pp_cxx_ws_string (pp, "__has_trivial_constructor");
   2612       break;
   2613     case CPTK_HAS_NOTHROW_COPY:
   2614       pp_cxx_ws_string (pp, "__has_nothrow_copy");
   2615       break;
   2616     case CPTK_HAS_TRIVIAL_COPY:
   2617       pp_cxx_ws_string (pp, "__has_trivial_copy");
   2618       break;
   2619     case CPTK_HAS_TRIVIAL_DESTRUCTOR:
   2620       pp_cxx_ws_string (pp, "__has_trivial_destructor");
   2621       break;
   2622     case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
   2623       pp_cxx_ws_string (pp, "__has_unique_object_representations");
   2624       break;
   2625     case CPTK_HAS_VIRTUAL_DESTRUCTOR:
   2626       pp_cxx_ws_string (pp, "__has_virtual_destructor");
   2627       break;
   2628     case CPTK_IS_ABSTRACT:
   2629       pp_cxx_ws_string (pp, "__is_abstract");
   2630       break;
   2631     case CPTK_IS_AGGREGATE:
   2632       pp_cxx_ws_string (pp, "__is_aggregate");
   2633       break;
   2634     case CPTK_IS_BASE_OF:
   2635       pp_cxx_ws_string (pp, "__is_base_of");
   2636       break;
   2637     case CPTK_IS_CLASS:
   2638       pp_cxx_ws_string (pp, "__is_class");
   2639       break;
   2640     case CPTK_IS_EMPTY:
   2641       pp_cxx_ws_string (pp, "__is_empty");
   2642       break;
   2643     case CPTK_IS_ENUM:
   2644       pp_cxx_ws_string (pp, "__is_enum");
   2645       break;
   2646     case CPTK_IS_FINAL:
   2647       pp_cxx_ws_string (pp, "__is_final");
   2648       break;
   2649     case CPTK_IS_LAYOUT_COMPATIBLE:
   2650       pp_cxx_ws_string (pp, "__is_layout_compatible");
   2651       break;
   2652     case CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF:
   2653       pp_cxx_ws_string (pp, "__is_pointer_interconvertible_base_of");
   2654       break;
   2655     case CPTK_IS_POD:
   2656       pp_cxx_ws_string (pp, "__is_pod");
   2657       break;
   2658     case CPTK_IS_POLYMORPHIC:
   2659       pp_cxx_ws_string (pp, "__is_polymorphic");
   2660       break;
   2661     case CPTK_IS_SAME_AS:
   2662       pp_cxx_ws_string (pp, "__is_same");
   2663       break;
   2664     case CPTK_IS_STD_LAYOUT:
   2665       pp_cxx_ws_string (pp, "__is_std_layout");
   2666       break;
   2667     case CPTK_IS_TRIVIAL:
   2668       pp_cxx_ws_string (pp, "__is_trivial");
   2669       break;
   2670     case CPTK_IS_TRIVIALLY_ASSIGNABLE:
   2671       pp_cxx_ws_string (pp, "__is_trivially_assignable");
   2672       break;
   2673     case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
   2674       pp_cxx_ws_string (pp, "__is_trivially_constructible");
   2675       break;
   2676     case CPTK_IS_TRIVIALLY_COPYABLE:
   2677       pp_cxx_ws_string (pp, "__is_trivially_copyable");
   2678       break;
   2679     case CPTK_IS_UNION:
   2680       pp_cxx_ws_string (pp, "__is_union");
   2681       break;
   2682     case CPTK_IS_LITERAL_TYPE:
   2683       pp_cxx_ws_string (pp, "__is_literal_type");
   2684       break;
   2685     case CPTK_IS_ASSIGNABLE:
   2686       pp_cxx_ws_string (pp, "__is_assignable");
   2687       break;
   2688     case CPTK_IS_CONSTRUCTIBLE:
   2689       pp_cxx_ws_string (pp, "__is_constructible");
   2690       break;
   2691     case CPTK_IS_NOTHROW_ASSIGNABLE:
   2692       pp_cxx_ws_string (pp, "__is_nothrow_assignable");
   2693       break;
   2694     case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
   2695       pp_cxx_ws_string (pp, "__is_nothrow_constructible");
   2696       break;
   2697 
   2698     default:
   2699       gcc_unreachable ();
   2700     }
   2701 
   2702   pp_cxx_left_paren (pp);
   2703   pp->type_id (TRAIT_EXPR_TYPE1 (t));
   2704 
   2705   if (kind == CPTK_IS_BASE_OF
   2706       || kind == CPTK_IS_SAME_AS
   2707       || kind == CPTK_IS_LAYOUT_COMPATIBLE
   2708       || kind == CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF)
   2709     {
   2710       pp_cxx_separate_with (pp, ',');
   2711       pp->type_id (TRAIT_EXPR_TYPE2 (t));
   2712     }
   2713 
   2714   pp_cxx_right_paren (pp);
   2715 }
   2716 
   2717 // requires-clause:
   2718 //    'requires' logical-or-expression
   2719 void
   2720 pp_cxx_requires_clause (cxx_pretty_printer *pp, tree t)
   2721 {
   2722   if (!t)
   2723     return;
   2724   pp->padding = pp_before;
   2725   pp_cxx_ws_string (pp, "requires");
   2726   pp_space (pp);
   2727   pp->expression (t);
   2728 }
   2729 
   2730 /* requirement:
   2731      simple-requirement
   2732      compound-requirement
   2733      type-requirement
   2734      nested-requirement */
   2735 static void
   2736 pp_cxx_requirement (cxx_pretty_printer *pp, tree t)
   2737 {
   2738   switch (TREE_CODE (t))
   2739     {
   2740     case SIMPLE_REQ:
   2741       pp_cxx_simple_requirement (pp, t);
   2742       break;
   2743 
   2744     case TYPE_REQ:
   2745       pp_cxx_type_requirement (pp, t);
   2746       break;
   2747 
   2748     case COMPOUND_REQ:
   2749       pp_cxx_compound_requirement (pp, t);
   2750       break;
   2751 
   2752     case NESTED_REQ:
   2753       pp_cxx_nested_requirement (pp, t);
   2754       break;
   2755 
   2756     default:
   2757       gcc_unreachable ();
   2758     }
   2759 }
   2760 
   2761 // requirement-list:
   2762 //    requirement
   2763 //    requirement-list ';' requirement[opt]
   2764 //
   2765 static void
   2766 pp_cxx_requirement_list (cxx_pretty_printer *pp, tree t)
   2767 {
   2768   for (; t; t = TREE_CHAIN (t))
   2769     pp_cxx_requirement (pp, TREE_VALUE (t));
   2770 }
   2771 
   2772 // requirement-body:
   2773 //    '{' requirement-list '}'
   2774 static void
   2775 pp_cxx_requirement_body (cxx_pretty_printer *pp, tree t)
   2776 {
   2777   pp_cxx_left_brace (pp);
   2778   pp_cxx_requirement_list (pp, t);
   2779   pp_cxx_right_brace (pp);
   2780 }
   2781 
   2782 // requires-expression:
   2783 //    'requires' requirement-parameter-list requirement-body
   2784 void
   2785 pp_cxx_requires_expr (cxx_pretty_printer *pp, tree t)
   2786 {
   2787   pp_string (pp, "requires");
   2788   if (tree parms = REQUIRES_EXPR_PARMS (t))
   2789     {
   2790       bool first = true;
   2791       pp_cxx_left_paren (pp);
   2792       for (; parms; parms = TREE_CHAIN (parms))
   2793 	{
   2794 	  if (!first)
   2795 	    pp_cxx_separate_with (pp, ',' );
   2796 	  first = false;
   2797 	  pp_cxx_parameter_declaration (pp, parms);
   2798 	}
   2799       pp_cxx_right_paren (pp);
   2800       pp_cxx_whitespace (pp);
   2801     }
   2802   pp_cxx_requirement_body (pp, TREE_OPERAND (t, 1));
   2803 }
   2804 
   2805 /* simple-requirement:
   2806      expression ';' */
   2807 void
   2808 pp_cxx_simple_requirement (cxx_pretty_printer *pp, tree t)
   2809 {
   2810   pp->expression (TREE_OPERAND (t, 0));
   2811   pp_cxx_semicolon (pp);
   2812 }
   2813 
   2814 /* type-requirement:
   2815      typename type-name ';' */
   2816 void
   2817 pp_cxx_type_requirement (cxx_pretty_printer *pp, tree t)
   2818 {
   2819   pp->type_id (TREE_OPERAND (t, 0));
   2820   pp_cxx_semicolon (pp);
   2821 }
   2822 
   2823 /* compound-requirement:
   2824      '{' expression '}' 'noexcept' [opt] trailing-return-type [opt] */
   2825 void
   2826 pp_cxx_compound_requirement (cxx_pretty_printer *pp, tree t)
   2827 {
   2828   pp_cxx_left_brace (pp);
   2829   pp->expression (TREE_OPERAND (t, 0));
   2830   pp_cxx_right_brace (pp);
   2831 
   2832   if (COMPOUND_REQ_NOEXCEPT_P (t))
   2833     pp_cxx_ws_string (pp, "noexcept");
   2834 
   2835   if (tree type = TREE_OPERAND (t, 1))
   2836     {
   2837       pp_cxx_whitespace (pp);
   2838       pp_cxx_ws_string (pp, "->");
   2839       pp->type_id (type);
   2840     }
   2841   pp_cxx_semicolon (pp);
   2842 }
   2843 
   2844 /* nested requirement:
   2845      'requires' constraint-expression */
   2846 void
   2847 pp_cxx_nested_requirement (cxx_pretty_printer *pp, tree t)
   2848 {
   2849   pp_cxx_ws_string (pp, "requires");
   2850   pp->expression (TREE_OPERAND (t, 0));
   2851   pp_cxx_semicolon (pp);
   2852 }
   2853 
   2854 void
   2855 pp_cxx_check_constraint (cxx_pretty_printer *pp, tree t)
   2856 {
   2857   tree decl = CHECK_CONSTR_CONCEPT (t);
   2858   tree tmpl = DECL_TI_TEMPLATE (decl);
   2859   tree args = CHECK_CONSTR_ARGS (t);
   2860   tree id = build_nt (TEMPLATE_ID_EXPR, tmpl, args);
   2861 
   2862   if (TREE_CODE (decl) == CONCEPT_DECL)
   2863     pp->expression (id);
   2864   else if (VAR_P (decl))
   2865     pp->expression (id);
   2866   else if (TREE_CODE (decl) == FUNCTION_DECL)
   2867     {
   2868       tree call = build_vl_exp (CALL_EXPR, 2);
   2869       TREE_OPERAND (call, 0) = integer_two_node;
   2870       TREE_OPERAND (call, 1) = id;
   2871       pp->expression (call);
   2872     }
   2873   else
   2874     gcc_unreachable ();
   2875 }
   2876 
   2877 /* Output the "[with ...]" clause for a parameter mapping of an atomic
   2878    constraint.   */
   2879 
   2880 void
   2881 pp_cxx_parameter_mapping (cxx_pretty_printer *pp, tree map)
   2882 {
   2883   pp_cxx_whitespace (pp);
   2884   pp_cxx_left_bracket (pp);
   2885   pp->translate_string ("with");
   2886   pp_cxx_whitespace (pp);
   2887 
   2888   for (tree p = map; p; p = TREE_CHAIN (p))
   2889     {
   2890       tree parm = TREE_VALUE (p);
   2891       tree arg = TREE_PURPOSE (p);
   2892 
   2893       if (TYPE_P (parm))
   2894 	pp->type_id (parm);
   2895       else if (tree name = DECL_NAME (TEMPLATE_PARM_DECL (parm)))
   2896 	pp_cxx_tree_identifier (pp, name);
   2897       else
   2898 	pp->translate_string ("<unnamed>");
   2899 
   2900       pp_cxx_whitespace (pp);
   2901       pp_equal (pp);
   2902       pp_cxx_whitespace (pp);
   2903 
   2904       if (TYPE_P (arg) || DECL_TEMPLATE_TEMPLATE_PARM_P (arg))
   2905 	pp->type_id (arg);
   2906       else
   2907 	pp->expression (arg);
   2908 
   2909       if (TREE_CHAIN (p) != NULL_TREE)
   2910 	pp_cxx_separate_with (pp, ';');
   2911     }
   2912 
   2913   pp_cxx_right_bracket (pp);
   2914 }
   2915 
   2916 void
   2917 pp_cxx_atomic_constraint (cxx_pretty_printer *pp, tree t)
   2918 {
   2919   /* Emit the expression.  */
   2920   pp->expression (ATOMIC_CONSTR_EXPR (t));
   2921 
   2922   /* Emit the parameter mapping.  */
   2923   tree map = ATOMIC_CONSTR_MAP (t);
   2924   if (map && map != error_mark_node)
   2925     pp_cxx_parameter_mapping (pp, map);
   2926 }
   2927 
   2928 void
   2929 pp_cxx_conjunction (cxx_pretty_printer *pp, tree t)
   2930 {
   2931   pp_cxx_constraint (pp, TREE_OPERAND (t, 0));
   2932   pp_string (pp, " /\\ ");
   2933   pp_cxx_constraint (pp, TREE_OPERAND (t, 1));
   2934 }
   2935 
   2936 void
   2937 pp_cxx_disjunction (cxx_pretty_printer *pp, tree t)
   2938 {
   2939   pp_cxx_constraint (pp, TREE_OPERAND (t, 0));
   2940   pp_string (pp, " \\/ ");
   2941   pp_cxx_constraint (pp, TREE_OPERAND (t, 1));
   2942 }
   2943 
   2944 void
   2945 pp_cxx_constraint (cxx_pretty_printer *pp, tree t)
   2946 {
   2947   if (t == error_mark_node)
   2948     return pp->expression (t);
   2949 
   2950   switch (TREE_CODE (t))
   2951     {
   2952     case ATOMIC_CONSTR:
   2953       pp_cxx_atomic_constraint (pp, t);
   2954       break;
   2955 
   2956     case CHECK_CONSTR:
   2957       pp_cxx_check_constraint (pp, t);
   2958       break;
   2959 
   2960     case CONJ_CONSTR:
   2961       pp_cxx_conjunction (pp, t);
   2962       break;
   2963 
   2964     case DISJ_CONSTR:
   2965       pp_cxx_disjunction (pp, t);
   2966       break;
   2967 
   2968     case EXPR_PACK_EXPANSION:
   2969       pp->expression (TREE_OPERAND (t, 0));
   2970       break;
   2971 
   2972     default:
   2973       gcc_unreachable ();
   2974     }
   2975 }
   2976 
   2977 
   2978 typedef c_pretty_print_fn pp_fun;
   2980 
   2981 /* Initialization of a C++ pretty-printer object.  */
   2982 
   2983 cxx_pretty_printer::cxx_pretty_printer ()
   2984   : c_pretty_printer (),
   2985     enclosing_scope (global_namespace)
   2986 {
   2987   type_specifier_seq = (pp_fun) pp_cxx_type_specifier_seq;
   2988   parameter_list = (pp_fun) pp_cxx_parameter_declaration_clause;
   2989 }
   2990 
   2991 /* cxx_pretty_printer's implementation of pretty_printer::clone vfunc.  */
   2992 
   2993 pretty_printer *
   2994 cxx_pretty_printer::clone () const
   2995 {
   2996   return new cxx_pretty_printer (*this);
   2997 }
   2998