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