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