1132718Skan/* Implementation of subroutines for the GNU C++ pretty-printer.
2169689Skan   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
3132718Skan   Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
4132718Skan
5132718SkanThis file is part of GCC.
6132718Skan
7132718SkanGCC is free software; you can redistribute it and/or modify it under
8132718Skanthe terms of the GNU General Public License as published by the Free
9132718SkanSoftware Foundation; either version 2, or (at your option) any later
10132718Skanversion.
11132718Skan
12132718SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
13132718SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or
14132718SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15132718Skanfor more details.
16132718Skan
17132718SkanYou should have received a copy of the GNU General Public License
18132718Skanalong with GCC; see the file COPYING.  If not, write to the Free
19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169689Skan02110-1301, USA.  */
21132718Skan
22132718Skan#include "config.h"
23132718Skan#include "system.h"
24132718Skan#include "coretypes.h"
25132718Skan#include "tm.h"
26132718Skan#include "real.h"
27132718Skan#include "cxx-pretty-print.h"
28132718Skan#include "cp-tree.h"
29132718Skan#include "toplev.h"
30132718Skan
31132718Skanstatic void pp_cxx_unqualified_id (cxx_pretty_printer *, tree);
32132718Skanstatic void pp_cxx_nested_name_specifier (cxx_pretty_printer *, tree);
33132718Skanstatic void pp_cxx_qualified_id (cxx_pretty_printer *, tree);
34132718Skanstatic void pp_cxx_assignment_expression (cxx_pretty_printer *, tree);
35132718Skanstatic void pp_cxx_expression (cxx_pretty_printer *, tree);
36132718Skanstatic void pp_cxx_template_argument_list (cxx_pretty_printer *, tree);
37132718Skanstatic void pp_cxx_type_specifier_seq (cxx_pretty_printer *, tree);
38132718Skanstatic void pp_cxx_ptr_operator (cxx_pretty_printer *, tree);
39132718Skanstatic void pp_cxx_type_id (cxx_pretty_printer *, tree);
40132718Skanstatic void pp_cxx_direct_abstract_declarator (cxx_pretty_printer *, tree);
41132718Skanstatic void pp_cxx_declarator (cxx_pretty_printer *, tree);
42169689Skanstatic void pp_cxx_parameter_declaration_clause (cxx_pretty_printer *, tree);
43132718Skanstatic void pp_cxx_abstract_declarator (cxx_pretty_printer *, tree);
44169689Skanstatic void pp_cxx_statement (cxx_pretty_printer *, tree);
45132718Skanstatic void pp_cxx_template_parameter (cxx_pretty_printer *, tree);
46169689Skanstatic void pp_cxx_cast_expression (cxx_pretty_printer *, tree);
47132718Skan
48132718Skan
49132718Skanstatic inline void
50132718Skanpp_cxx_nonconsecutive_character (cxx_pretty_printer *pp, int c)
51132718Skan{
52132718Skan  const char *p = pp_last_position_in_text (pp);
53132718Skan
54132718Skan  if (p != NULL && *p == c)
55132718Skan    pp_cxx_whitespace (pp);
56132718Skan  pp_character (pp, c);
57132718Skan  pp_base (pp)->padding = pp_none;
58132718Skan}
59132718Skan
60132718Skan#define pp_cxx_storage_class_specifier(PP, T) \
61132718Skan   pp_c_storage_class_specifier (pp_c_base (PP), T)
62132718Skan#define pp_cxx_expression_list(PP, T)    \
63132718Skan   pp_c_expression_list (pp_c_base (PP), T)
64132718Skan#define pp_cxx_space_for_pointer_operator(PP, T)  \
65132718Skan   pp_c_space_for_pointer_operator (pp_c_base (PP), T)
66132718Skan#define pp_cxx_init_declarator(PP, T)    \
67132718Skan   pp_c_init_declarator (pp_c_base (PP), T)
68132718Skan#define pp_cxx_call_argument_list(PP, T) \
69132718Skan   pp_c_call_argument_list (pp_c_base (PP), T)
70132718Skan
71169689Skanvoid
72132718Skanpp_cxx_colon_colon (cxx_pretty_printer *pp)
73132718Skan{
74132718Skan  pp_colon_colon (pp);
75132718Skan  pp_base (pp)->padding = pp_none;
76132718Skan}
77132718Skan
78169689Skanvoid
79169689Skanpp_cxx_begin_template_argument_list (cxx_pretty_printer *pp)
80169689Skan{
81169689Skan  pp_cxx_nonconsecutive_character (pp, '<');
82169689Skan}
83132718Skan
84169689Skanvoid
85169689Skanpp_cxx_end_template_argument_list (cxx_pretty_printer *pp)
86169689Skan{
87169689Skan  pp_cxx_nonconsecutive_character (pp, '>');
88169689Skan}
89169689Skan
90169689Skanvoid
91169689Skanpp_cxx_separate_with (cxx_pretty_printer *pp, int c)
92169689Skan{
93169689Skan  pp_separate_with (pp, c);
94169689Skan  pp_base (pp)->padding = pp_none;
95169689Skan}
96169689Skan
97132718Skan/* Expressions.  */
98132718Skan
99132718Skanstatic inline bool
100132718Skanis_destructor_name (tree name)
101132718Skan{
102132718Skan  return name == complete_dtor_identifier
103132718Skan    || name == base_dtor_identifier
104132718Skan    || name == deleting_dtor_identifier;
105132718Skan}
106132718Skan
107132718Skan/* conversion-function-id:
108132718Skan      operator conversion-type-id
109132718Skan
110132718Skan   conversion-type-id:
111132718Skan      type-specifier-seq conversion-declarator(opt)
112132718Skan
113132718Skan   conversion-declarator:
114132718Skan      ptr-operator conversion-declarator(opt)  */
115169689Skan
116132718Skanstatic inline void
117132718Skanpp_cxx_conversion_function_id (cxx_pretty_printer *pp, tree t)
118132718Skan{
119132718Skan  pp_cxx_identifier (pp, "operator");
120132718Skan  pp_cxx_type_specifier_seq (pp, TREE_TYPE (t));
121132718Skan}
122132718Skan
123132718Skanstatic inline void
124132718Skanpp_cxx_template_id (cxx_pretty_printer *pp, tree t)
125132718Skan{
126132718Skan  pp_cxx_unqualified_id (pp, TREE_OPERAND (t, 0));
127132718Skan  pp_cxx_begin_template_argument_list (pp);
128132718Skan  pp_cxx_template_argument_list (pp, TREE_OPERAND (t, 1));
129132718Skan  pp_cxx_end_template_argument_list (pp);
130132718Skan}
131132718Skan
132132718Skan/* unqualified-id:
133132718Skan     identifier
134132718Skan     operator-function-id
135132718Skan     conversion-function-id
136132718Skan     ~ class-name
137132718Skan     template-id  */
138169689Skan
139132718Skanstatic void
140132718Skanpp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t)
141132718Skan{
142132718Skan  enum tree_code code = TREE_CODE (t);
143132718Skan  switch (code)
144132718Skan    {
145132718Skan    case RESULT_DECL:
146132718Skan      pp_cxx_identifier (pp, "<return-value>");
147132718Skan      break;
148132718Skan
149132718Skan    case OVERLOAD:
150169689Skan      t = OVL_CURRENT (t);
151132718Skan    case VAR_DECL:
152132718Skan    case PARM_DECL:
153132718Skan    case CONST_DECL:
154132718Skan    case TYPE_DECL:
155132718Skan    case FUNCTION_DECL:
156132718Skan    case NAMESPACE_DECL:
157132718Skan    case FIELD_DECL:
158132718Skan    case LABEL_DECL:
159132718Skan    case USING_DECL:
160132718Skan    case TEMPLATE_DECL:
161132718Skan      t = DECL_NAME (t);
162169689Skan
163132718Skan    case IDENTIFIER_NODE:
164132718Skan      if (t == NULL)
165169689Skan	pp_cxx_identifier (pp, "<unnamed>");
166132718Skan      else if (IDENTIFIER_TYPENAME_P (t))
167169689Skan	pp_cxx_conversion_function_id (pp, t);
168132718Skan      else
169169689Skan	{
170169689Skan	  if (is_destructor_name (t))
171169689Skan	    {
172169689Skan	      pp_complement (pp);
173169689Skan	      /* FIXME: Why is this necessary? */
174169689Skan	      if (TREE_TYPE (t))
175169689Skan		t = constructor_name (TREE_TYPE (t));
176169689Skan	    }
177169689Skan	  pp_cxx_tree_identifier (pp, t);
178169689Skan	}
179132718Skan      break;
180132718Skan
181132718Skan    case TEMPLATE_ID_EXPR:
182132718Skan      pp_cxx_template_id (pp, t);
183132718Skan      break;
184132718Skan
185146895Skan    case BASELINK:
186146895Skan      pp_cxx_unqualified_id (pp, BASELINK_FUNCTIONS (t));
187146895Skan      break;
188146895Skan
189132718Skan    case RECORD_TYPE:
190132718Skan    case UNION_TYPE:
191132718Skan    case ENUMERAL_TYPE:
192132718Skan      pp_cxx_unqualified_id (pp, TYPE_NAME (t));
193132718Skan      break;
194132718Skan
195132718Skan    case TEMPLATE_TYPE_PARM:
196169689Skan    case TEMPLATE_TEMPLATE_PARM:
197169689Skan      if (TYPE_IDENTIFIER (t))
198169689Skan	pp_cxx_unqualified_id (pp, TYPE_IDENTIFIER (t));
199169689Skan      else
200169689Skan	pp_cxx_canonical_template_parameter (pp, t);
201169689Skan      break;
202169689Skan
203132718Skan    case TEMPLATE_PARM_INDEX:
204132718Skan      pp_cxx_unqualified_id (pp, TEMPLATE_PARM_DECL (t));
205132718Skan      break;
206132718Skan
207220150Smm    case UNBOUND_CLASS_TEMPLATE:
208220150Smm      pp_cxx_unqualified_id (pp, TYPE_NAME (t));
209220150Smm      break;
210220150Smm
211132718Skan    default:
212132718Skan      pp_unsupported_tree (pp, t);
213132718Skan      break;
214132718Skan    }
215132718Skan}
216132718Skan
217169689Skan/* Pretty-print out the token sequence ":: template" in template codes
218169689Skan   where it is needed to "inline declare" the (following) member as
219169689Skan   a template.  This situation arises when SCOPE of T is dependent
220169689Skan   on template parameters.  */
221169689Skan
222132718Skanstatic inline void
223132718Skanpp_cxx_template_keyword_if_needed (cxx_pretty_printer *pp, tree scope, tree t)
224132718Skan{
225132718Skan  if (TREE_CODE (t) == TEMPLATE_ID_EXPR
226132718Skan      && TYPE_P (scope) && dependent_type_p (scope))
227132718Skan    pp_cxx_identifier (pp, "template");
228132718Skan}
229132718Skan
230132718Skan/* nested-name-specifier:
231132718Skan      class-or-namespace-name :: nested-name-specifier(opt)
232132718Skan      class-or-namespace-name :: template nested-name-specifier   */
233169689Skan
234132718Skanstatic void
235132718Skanpp_cxx_nested_name_specifier (cxx_pretty_printer *pp, tree t)
236132718Skan{
237132718Skan  if (t != NULL && t != pp->enclosing_scope)
238132718Skan    {
239132718Skan      tree scope = TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t);
240132718Skan      pp_cxx_nested_name_specifier (pp, scope);
241132718Skan      pp_cxx_template_keyword_if_needed (pp, scope, t);
242132718Skan      pp_cxx_unqualified_id (pp, t);
243132718Skan      pp_cxx_colon_colon (pp);
244132718Skan    }
245132718Skan}
246132718Skan
247132718Skan/* qualified-id:
248132718Skan      nested-name-specifier template(opt) unqualified-id  */
249169689Skan
250132718Skanstatic void
251132718Skanpp_cxx_qualified_id (cxx_pretty_printer *pp, tree t)
252132718Skan{
253132718Skan  switch (TREE_CODE (t))
254132718Skan    {
255169689Skan      /* A pointer-to-member is always qualified.  */
256132718Skan    case PTRMEM_CST:
257132718Skan      pp_cxx_nested_name_specifier (pp, PTRMEM_CST_CLASS (t));
258132718Skan      pp_cxx_unqualified_id (pp, PTRMEM_CST_MEMBER (t));
259132718Skan      break;
260132718Skan
261169689Skan      /* In Standard C++, functions cannot possibly be used as
262169689Skan	 nested-name-specifiers.  However, there are situations where
263169689Skan	 is "makes sense" to output the surrounding function name for the
264169689Skan	 purpose of emphasizing on the scope kind.  Just printing the
265169689Skan	 function name might not be sufficient as it may be overloaded; so,
266169689Skan	 we decorate the function with its signature too.
267169689Skan	 FIXME:  This is probably the wrong pretty-printing for conversion
268169689Skan	 functions and some function templates.  */
269132718Skan    case OVERLOAD:
270132718Skan      t = OVL_CURRENT (t);
271132718Skan    case FUNCTION_DECL:
272132718Skan      if (DECL_FUNCTION_MEMBER_P (t))
273169689Skan	pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
274132718Skan      pp_cxx_unqualified_id
275169689Skan	(pp, DECL_CONSTRUCTOR_P (t) ? DECL_CONTEXT (t) : t);
276169689Skan      pp_cxx_parameter_declaration_clause (pp, TREE_TYPE (t));
277132718Skan      break;
278132718Skan
279132718Skan    case OFFSET_REF:
280132718Skan    case SCOPE_REF:
281132718Skan      pp_cxx_nested_name_specifier (pp, TREE_OPERAND (t, 0));
282132718Skan      pp_cxx_unqualified_id (pp, TREE_OPERAND (t, 1));
283132718Skan      break;
284132718Skan
285132718Skan    default:
286132718Skan      {
287169689Skan	tree scope = TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t);
288169689Skan	if (scope != pp->enclosing_scope)
289169689Skan	  {
290169689Skan	    pp_cxx_nested_name_specifier (pp, scope);
291169689Skan	    pp_cxx_template_keyword_if_needed (pp, scope, t);
292169689Skan	  }
293169689Skan	pp_cxx_unqualified_id (pp, t);
294132718Skan      }
295132718Skan      break;
296132718Skan    }
297132718Skan}
298132718Skan
299169689Skan
300169689Skanstatic void
301169689Skanpp_cxx_constant (cxx_pretty_printer *pp, tree t)
302169689Skan{
303169689Skan  switch (TREE_CODE (t))
304169689Skan    {
305169689Skan    case STRING_CST:
306169689Skan      {
307169689Skan	const bool in_parens = PAREN_STRING_LITERAL_P (t);
308169689Skan	if (in_parens)
309169689Skan	  pp_cxx_left_paren (pp);
310169689Skan	pp_c_constant (pp_c_base (pp), t);
311169689Skan	if (in_parens)
312169689Skan	  pp_cxx_right_paren (pp);
313169689Skan      }
314169689Skan      break;
315169689Skan
316169689Skan    default:
317169689Skan      pp_c_constant (pp_c_base (pp), t);
318169689Skan      break;
319169689Skan    }
320169689Skan}
321169689Skan
322132718Skan/* id-expression:
323132718Skan      unqualified-id
324132718Skan      qualified-id   */
325169689Skan
326132718Skanstatic inline void
327132718Skanpp_cxx_id_expression (cxx_pretty_printer *pp, tree t)
328132718Skan{
329132718Skan  if (TREE_CODE (t) == OVERLOAD)
330132718Skan    t = OVL_CURRENT (t);
331132718Skan  if (DECL_P (t) && DECL_CONTEXT (t))
332132718Skan    pp_cxx_qualified_id (pp, t);
333132718Skan  else
334132718Skan    pp_cxx_unqualified_id (pp, t);
335132718Skan}
336132718Skan
337132718Skan/* primary-expression:
338132718Skan     literal
339132718Skan     this
340132718Skan     :: identifier
341132718Skan     :: operator-function-id
342132718Skan     :: qualifier-id
343132718Skan     ( expression )
344132718Skan     id-expression   */
345169689Skan
346132718Skanstatic void
347132718Skanpp_cxx_primary_expression (cxx_pretty_printer *pp, tree t)
348132718Skan{
349132718Skan  switch (TREE_CODE (t))
350132718Skan    {
351132718Skan    case INTEGER_CST:
352132718Skan    case REAL_CST:
353169689Skan    case STRING_CST:
354169689Skan      pp_cxx_constant (pp, t);
355132718Skan      break;
356132718Skan
357132718Skan    case BASELINK:
358132718Skan      t = BASELINK_FUNCTIONS (t);
359132718Skan    case VAR_DECL:
360132718Skan    case PARM_DECL:
361132718Skan    case FIELD_DECL:
362132718Skan    case FUNCTION_DECL:
363132718Skan    case OVERLOAD:
364132718Skan    case CONST_DECL:
365132718Skan    case TEMPLATE_DECL:
366132718Skan      pp_cxx_id_expression (pp, t);
367132718Skan      break;
368132718Skan
369132718Skan    case RESULT_DECL:
370132718Skan    case TEMPLATE_TYPE_PARM:
371169689Skan    case TEMPLATE_TEMPLATE_PARM:
372132718Skan    case TEMPLATE_PARM_INDEX:
373132718Skan      pp_cxx_unqualified_id (pp, t);
374132718Skan      break;
375132718Skan
376169689Skan    case STMT_EXPR:
377169689Skan      pp_cxx_left_paren (pp);
378169689Skan      pp_cxx_statement (pp, STMT_EXPR_STMT (t));
379169689Skan      pp_cxx_right_paren (pp);
380169689Skan      break;
381169689Skan
382132718Skan    default:
383132718Skan      pp_c_primary_expression (pp_c_base (pp), t);
384132718Skan      break;
385132718Skan    }
386132718Skan}
387132718Skan
388132718Skan/* postfix-expression:
389132718Skan     primary-expression
390132718Skan     postfix-expression [ expression ]
391132718Skan     postfix-expression ( expression-list(opt) )
392132718Skan     simple-type-specifier ( expression-list(opt) )
393132718Skan     typename ::(opt) nested-name-specifier identifier ( expression-list(opt) )
394132718Skan     typename ::(opt) nested-name-specifier template(opt)
395169689Skan				       template-id ( expression-list(opt) )
396132718Skan     postfix-expression . template(opt) ::(opt) id-expression
397132718Skan     postfix-expression -> template(opt) ::(opt) id-expression
398132718Skan     postfix-expression . pseudo-destructor-name
399132718Skan     postfix-expression -> pseudo-destructor-name
400132718Skan     postfix-expression ++
401132718Skan     postfix-expression --
402132718Skan     dynamic_cast < type-id > ( expression )
403132718Skan     static_cast < type-id > ( expression )
404132718Skan     reinterpret_cast < type-id > ( expression )
405132718Skan     const_cast < type-id > ( expression )
406132718Skan     typeid ( expression )
407132718Skan     typeif ( type-id )  */
408132718Skan
409132718Skanstatic void
410132718Skanpp_cxx_postfix_expression (cxx_pretty_printer *pp, tree t)
411132718Skan{
412132718Skan  enum tree_code code = TREE_CODE (t);
413169689Skan
414132718Skan  switch (code)
415132718Skan    {
416132718Skan    case AGGR_INIT_EXPR:
417132718Skan    case CALL_EXPR:
418132718Skan      {
419169689Skan	tree fun = TREE_OPERAND (t, 0);
420169689Skan	tree args = TREE_OPERAND (t, 1);
421169689Skan	tree saved_scope = pp->enclosing_scope;
422132718Skan
423169689Skan	if (TREE_CODE (fun) == ADDR_EXPR)
424169689Skan	  fun = TREE_OPERAND (fun, 0);
425132718Skan
426169689Skan	/* In templates, where there is no way to tell whether a given
427169689Skan	   call uses an actual member function.  So the parser builds
428169689Skan	   FUN as a COMPONENT_REF or a plain IDENTIFIER_NODE until
429169689Skan	   instantiation time.  */
430169689Skan	if (TREE_CODE (fun) != FUNCTION_DECL)
431169689Skan	  ;
432169689Skan	else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun))
433169689Skan	  {
434169689Skan	    tree object = code == AGGR_INIT_EXPR && AGGR_INIT_VIA_CTOR_P (t)
435169689Skan	      ? TREE_OPERAND (t, 2)
436169689Skan	      : TREE_VALUE (args);
437132718Skan
438169689Skan	    while (TREE_CODE (object) == NOP_EXPR)
439169689Skan	      object = TREE_OPERAND (object, 0);
440132718Skan
441169689Skan	    if (TREE_CODE (object) == ADDR_EXPR)
442169689Skan	      object = TREE_OPERAND (object, 0);
443169689Skan
444169689Skan	    if (TREE_CODE (TREE_TYPE (object)) != POINTER_TYPE)
445169689Skan	      {
446169689Skan		pp_cxx_postfix_expression (pp, object);
447169689Skan		pp_cxx_dot (pp);
448169689Skan	      }
449169689Skan	    else
450169689Skan	      {
451169689Skan		pp_cxx_postfix_expression (pp, object);
452169689Skan		pp_cxx_arrow (pp);
453169689Skan	      }
454169689Skan	    args = TREE_CHAIN (args);
455169689Skan	    pp->enclosing_scope = strip_pointer_operator (TREE_TYPE (object));
456169689Skan	  }
457169689Skan
458169689Skan	pp_cxx_postfix_expression (pp, fun);
459169689Skan	pp->enclosing_scope = saved_scope;
460169689Skan	pp_cxx_call_argument_list (pp, args);
461132718Skan      }
462132718Skan      if (code == AGGR_INIT_EXPR && AGGR_INIT_VIA_CTOR_P (t))
463169689Skan	{
464169689Skan	  pp_cxx_separate_with (pp, ',');
465169689Skan	  pp_cxx_postfix_expression (pp, TREE_OPERAND (t, 2));
466169689Skan	}
467132718Skan      break;
468132718Skan
469132718Skan    case BASELINK:
470132718Skan    case VAR_DECL:
471132718Skan    case PARM_DECL:
472132718Skan    case FIELD_DECL:
473132718Skan    case FUNCTION_DECL:
474132718Skan    case OVERLOAD:
475132718Skan    case CONST_DECL:
476132718Skan    case TEMPLATE_DECL:
477132718Skan    case RESULT_DECL:
478132718Skan      pp_cxx_primary_expression (pp, t);
479132718Skan      break;
480132718Skan
481132718Skan    case DYNAMIC_CAST_EXPR:
482132718Skan    case STATIC_CAST_EXPR:
483132718Skan    case REINTERPRET_CAST_EXPR:
484132718Skan    case CONST_CAST_EXPR:
485132718Skan      if (code == DYNAMIC_CAST_EXPR)
486169689Skan	pp_cxx_identifier (pp, "dynamic_cast");
487132718Skan      else if (code == STATIC_CAST_EXPR)
488169689Skan	pp_cxx_identifier (pp, "static_cast");
489132718Skan      else if (code == REINTERPRET_CAST_EXPR)
490169689Skan	pp_cxx_identifier (pp, "reinterpret_cast");
491132718Skan      else
492169689Skan	pp_cxx_identifier (pp, "const_cast");
493132718Skan      pp_cxx_begin_template_argument_list (pp);
494132718Skan      pp_cxx_type_id (pp, TREE_TYPE (t));
495132718Skan      pp_cxx_end_template_argument_list (pp);
496132718Skan      pp_left_paren (pp);
497132718Skan      pp_cxx_expression (pp, TREE_OPERAND (t, 0));
498132718Skan      pp_right_paren (pp);
499132718Skan      break;
500132718Skan
501132718Skan    case EMPTY_CLASS_EXPR:
502132718Skan      pp_cxx_type_id (pp, TREE_TYPE (t));
503132718Skan      pp_left_paren (pp);
504132718Skan      pp_right_paren (pp);
505132718Skan      break;
506132718Skan
507132718Skan    case TYPEID_EXPR:
508132718Skan      t = TREE_OPERAND (t, 0);
509132718Skan      pp_cxx_identifier (pp, "typeid");
510132718Skan      pp_left_paren (pp);
511132718Skan      if (TYPE_P (t))
512169689Skan	pp_cxx_type_id (pp, t);
513132718Skan      else
514169689Skan	pp_cxx_expression (pp, t);
515132718Skan      pp_right_paren (pp);
516132718Skan      break;
517132718Skan
518132718Skan    case PSEUDO_DTOR_EXPR:
519132718Skan      pp_cxx_postfix_expression (pp, TREE_OPERAND (t, 0));
520132718Skan      pp_cxx_dot (pp);
521132718Skan      pp_cxx_qualified_id (pp, TREE_OPERAND (t, 1));
522132718Skan      pp_cxx_colon_colon (pp);
523132718Skan      pp_complement (pp);
524132718Skan      pp_cxx_unqualified_id (pp, TREE_OPERAND (t, 2));
525132718Skan      break;
526132718Skan
527169689Skan    case ARROW_EXPR:
528169689Skan      pp_cxx_postfix_expression (pp, TREE_OPERAND (t, 0));
529169689Skan      pp_cxx_arrow (pp);
530169689Skan      break;
531169689Skan
532132718Skan    default:
533132718Skan      pp_c_postfix_expression (pp_c_base (pp), t);
534132718Skan      break;
535132718Skan    }
536132718Skan}
537132718Skan
538132718Skan/* new-expression:
539132718Skan      ::(opt) new new-placement(opt) new-type-id new-initializer(opt)
540132718Skan      ::(opt) new new-placement(opt) ( type-id ) new-initializer(opt)
541132718Skan
542132718Skan   new-placement:
543132718Skan      ( expression-list )
544132718Skan
545132718Skan   new-type-id:
546132718Skan      type-specifier-seq new-declarator(opt)
547132718Skan
548132718Skan   new-declarator:
549132718Skan      ptr-operator new-declarator(opt)
550132718Skan      direct-new-declarator
551132718Skan
552132718Skan   direct-new-declarator
553132718Skan      [ expression ]
554132718Skan      direct-new-declarator [ constant-expression ]
555132718Skan
556132718Skan   new-initializer:
557132718Skan      ( expression-list(opt) )  */
558169689Skan
559132718Skanstatic void
560132718Skanpp_cxx_new_expression (cxx_pretty_printer *pp, tree t)
561132718Skan{
562132718Skan  enum tree_code code = TREE_CODE (t);
563132718Skan  switch (code)
564132718Skan    {
565132718Skan    case NEW_EXPR:
566132718Skan    case VEC_NEW_EXPR:
567132718Skan      if (NEW_EXPR_USE_GLOBAL (t))
568169689Skan	pp_cxx_colon_colon (pp);
569132718Skan      pp_cxx_identifier (pp, "new");
570132718Skan      if (TREE_OPERAND (t, 0))
571169689Skan	{
572169689Skan	  pp_cxx_call_argument_list (pp, TREE_OPERAND (t, 0));
573169689Skan	  pp_space (pp);
574169689Skan	}
575132718Skan      /* FIXME: array-types are built with one more element.  */
576132718Skan      pp_cxx_type_id (pp, TREE_OPERAND (t, 1));
577132718Skan      if (TREE_OPERAND (t, 2))
578169689Skan	{
579169689Skan	  pp_left_paren (pp);
580169689Skan	  t = TREE_OPERAND (t, 2);
581169689Skan	  if (TREE_CODE (t) == TREE_LIST)
582169689Skan	    pp_c_expression_list (pp_c_base (pp), t);
583169689Skan	  else if (t == void_zero_node)
584169689Skan	    ;			/* OK, empty initializer list.  */
585169689Skan	  else
586169689Skan	    pp_cxx_expression (pp, t);
587169689Skan	  pp_right_paren (pp);
588169689Skan	}
589132718Skan      break;
590132718Skan
591132718Skan    default:
592132718Skan      pp_unsupported_tree (pp, t);
593132718Skan    }
594132718Skan}
595132718Skan
596132718Skan/* delete-expression:
597132718Skan      ::(opt) delete cast-expression
598132718Skan      ::(opt) delete [ ] cast-expression   */
599169689Skan
600132718Skanstatic void
601132718Skanpp_cxx_delete_expression (cxx_pretty_printer *pp, tree t)
602132718Skan{
603132718Skan  enum tree_code code = TREE_CODE (t);
604132718Skan  switch (code)
605132718Skan    {
606132718Skan    case DELETE_EXPR:
607132718Skan    case VEC_DELETE_EXPR:
608132718Skan      if (DELETE_EXPR_USE_GLOBAL (t))
609169689Skan	pp_cxx_colon_colon (pp);
610132718Skan      pp_cxx_identifier (pp, "delete");
611132718Skan      if (code == VEC_DELETE_EXPR)
612169689Skan	{
613169689Skan	  pp_left_bracket (pp);
614169689Skan	  pp_right_bracket (pp);
615169689Skan	}
616132718Skan      pp_c_cast_expression (pp_c_base (pp), TREE_OPERAND (t, 0));
617169689Skan      break;
618169689Skan
619132718Skan    default:
620132718Skan      pp_unsupported_tree (pp, t);
621132718Skan    }
622132718Skan}
623132718Skan
624132718Skan/* unary-expression:
625132718Skan      postfix-expression
626132718Skan      ++ cast-expression
627132718Skan      -- cast-expression
628132718Skan      unary-operator cast-expression
629132718Skan      sizeof unary-expression
630132718Skan      sizeof ( type-id )
631132718Skan      new-expression
632132718Skan      delete-expression
633132718Skan
634132718Skan   unary-operator: one of
635132718Skan      *   &   +   -  !
636132718Skan
637132718Skan   GNU extensions:
638132718Skan      __alignof__ unary-expression
639132718Skan      __alignof__ ( type-id )  */
640169689Skan
641132718Skanstatic void
642132718Skanpp_cxx_unary_expression (cxx_pretty_printer *pp, tree t)
643132718Skan{
644132718Skan  enum tree_code code = TREE_CODE (t);
645132718Skan  switch (code)
646132718Skan    {
647132718Skan    case NEW_EXPR:
648132718Skan    case VEC_NEW_EXPR:
649132718Skan      pp_cxx_new_expression (pp, t);
650132718Skan      break;
651132718Skan
652132718Skan    case DELETE_EXPR:
653132718Skan    case VEC_DELETE_EXPR:
654132718Skan      pp_cxx_delete_expression (pp, t);
655132718Skan      break;
656169689Skan
657169689Skan    case SIZEOF_EXPR:
658169689Skan    case ALIGNOF_EXPR:
659169689Skan      pp_cxx_identifier (pp, code == SIZEOF_EXPR ? "sizeof" : "__alignof__");
660169689Skan      pp_cxx_whitespace (pp);
661169689Skan      if (TYPE_P (TREE_OPERAND (t, 0)))
662169689Skan	{
663169689Skan	  pp_cxx_left_paren (pp);
664169689Skan	  pp_cxx_type_id (pp, TREE_OPERAND (t, 0));
665169689Skan	  pp_cxx_right_paren (pp);
666169689Skan	}
667169689Skan      else
668169689Skan	pp_unary_expression (pp, TREE_OPERAND (t, 0));
669169689Skan      break;
670169689Skan
671169689Skan    case UNARY_PLUS_EXPR:
672169689Skan      pp_plus (pp);
673169689Skan      pp_cxx_cast_expression (pp, TREE_OPERAND (t, 0));
674169689Skan      break;
675169689Skan
676132718Skan    default:
677132718Skan      pp_c_unary_expression (pp_c_base (pp), t);
678132718Skan      break;
679132718Skan    }
680132718Skan}
681132718Skan
682132718Skan/* cast-expression:
683132718Skan      unary-expression
684132718Skan      ( type-id ) cast-expression  */
685169689Skan
686132718Skanstatic void
687132718Skanpp_cxx_cast_expression (cxx_pretty_printer *pp, tree t)
688132718Skan{
689132718Skan  switch (TREE_CODE (t))
690132718Skan    {
691132718Skan    case CAST_EXPR:
692132718Skan      pp_cxx_type_id (pp, TREE_TYPE (t));
693132718Skan      pp_cxx_call_argument_list (pp, TREE_OPERAND (t, 0));
694132718Skan      break;
695132718Skan
696132718Skan    default:
697132718Skan      pp_c_cast_expression (pp_c_base (pp), t);
698132718Skan      break;
699132718Skan    }
700132718Skan}
701132718Skan
702132718Skan/* pm-expression:
703132718Skan      cast-expression
704132718Skan      pm-expression .* cast-expression
705132718Skan      pm-expression ->* cast-expression  */
706169689Skan
707132718Skanstatic void
708132718Skanpp_cxx_pm_expression (cxx_pretty_printer *pp, tree t)
709132718Skan{
710132718Skan  switch (TREE_CODE (t))
711132718Skan    {
712132718Skan      /* Handle unfortunate OFFESET_REF overloading here.  */
713132718Skan    case OFFSET_REF:
714132718Skan      if (TYPE_P (TREE_OPERAND (t, 0)))
715169689Skan	{
716169689Skan	  pp_cxx_qualified_id (pp, t);
717169689Skan	  break;
718169689Skan	}
719132718Skan      /* Else fall through.  */
720132718Skan    case MEMBER_REF:
721132718Skan    case DOTSTAR_EXPR:
722132718Skan      pp_cxx_pm_expression (pp, TREE_OPERAND (t, 0));
723132718Skan      pp_cxx_dot (pp);
724132718Skan      pp_star(pp);
725132718Skan      pp_cxx_cast_expression (pp, TREE_OPERAND (t, 1));
726132718Skan      break;
727132718Skan
728132718Skan
729132718Skan    default:
730132718Skan      pp_cxx_cast_expression (pp, t);
731132718Skan      break;
732132718Skan    }
733132718Skan}
734132718Skan
735132718Skan/* multiplicative-expression:
736132718Skan      pm-expression
737132718Skan      multiplicative-expression * pm-expression
738132718Skan      multiplicative-expression / pm-expression
739132718Skan      multiplicative-expression % pm-expression  */
740169689Skan
741132718Skanstatic void
742132718Skanpp_cxx_multiplicative_expression (cxx_pretty_printer *pp, tree e)
743132718Skan{
744132718Skan  enum tree_code code = TREE_CODE (e);
745132718Skan  switch (code)
746132718Skan    {
747132718Skan    case MULT_EXPR:
748132718Skan    case TRUNC_DIV_EXPR:
749132718Skan    case TRUNC_MOD_EXPR:
750132718Skan      pp_cxx_multiplicative_expression (pp, TREE_OPERAND (e, 0));
751132718Skan      pp_space (pp);
752132718Skan      if (code == MULT_EXPR)
753132718Skan	pp_star (pp);
754132718Skan      else if (code == TRUNC_DIV_EXPR)
755132718Skan	pp_slash (pp);
756132718Skan      else
757132718Skan	pp_modulo (pp);
758132718Skan      pp_space (pp);
759132718Skan      pp_cxx_pm_expression (pp, TREE_OPERAND (e, 1));
760132718Skan      break;
761132718Skan
762132718Skan    default:
763132718Skan      pp_cxx_pm_expression (pp, e);
764132718Skan      break;
765132718Skan    }
766132718Skan}
767132718Skan
768132718Skan/* conditional-expression:
769132718Skan      logical-or-expression
770132718Skan      logical-or-expression ?  expression  : assignment-expression  */
771169689Skan
772132718Skanstatic void
773132718Skanpp_cxx_conditional_expression (cxx_pretty_printer *pp, tree e)
774132718Skan{
775132718Skan  if (TREE_CODE (e) == COND_EXPR)
776132718Skan    {
777132718Skan      pp_c_logical_or_expression (pp_c_base (pp), TREE_OPERAND (e, 0));
778132718Skan      pp_space (pp);
779132718Skan      pp_question (pp);
780132718Skan      pp_space (pp);
781132718Skan      pp_cxx_expression (pp, TREE_OPERAND (e, 1));
782132718Skan      pp_space (pp);
783132718Skan      pp_cxx_assignment_expression (pp, TREE_OPERAND (e, 2));
784132718Skan    }
785132718Skan  else
786132718Skan    pp_c_logical_or_expression (pp_c_base (pp), e);
787132718Skan}
788132718Skan
789169689Skan/* Pretty-print a compound assignment operator token as indicated by T.  */
790169689Skan
791132718Skanstatic void
792132718Skanpp_cxx_assignment_operator (cxx_pretty_printer *pp, tree t)
793132718Skan{
794132718Skan  const char *op;
795132718Skan
796132718Skan  switch (TREE_CODE (t))
797132718Skan    {
798132718Skan    case NOP_EXPR:
799132718Skan      op = "=";
800132718Skan      break;
801132718Skan
802132718Skan    case PLUS_EXPR:
803132718Skan      op = "+=";
804132718Skan      break;
805132718Skan
806132718Skan    case MINUS_EXPR:
807132718Skan      op = "-=";
808132718Skan      break;
809132718Skan
810132718Skan    case TRUNC_DIV_EXPR:
811132718Skan      op = "/=";
812132718Skan      break;
813132718Skan
814132718Skan    case TRUNC_MOD_EXPR:
815132718Skan      op = "%=";
816132718Skan      break;
817132718Skan
818132718Skan    default:
819132718Skan      op = tree_code_name[TREE_CODE (t)];
820132718Skan      break;
821132718Skan    }
822132718Skan
823132718Skan  pp_cxx_identifier (pp, op);
824132718Skan}
825132718Skan
826132718Skan
827132718Skan/* assignment-expression:
828132718Skan      conditional-expression
829132718Skan      logical-or-expression assignment-operator assignment-expression
830132718Skan      throw-expression
831132718Skan
832132718Skan   throw-expression:
833132718Skan       throw assignment-expression(opt)
834132718Skan
835132718Skan   assignment-operator: one of
836132718Skan      =    *=    /=    %=    +=    -=    >>=    <<=    &=    ^=    |=  */
837169689Skan
838132718Skanstatic void
839132718Skanpp_cxx_assignment_expression (cxx_pretty_printer *pp, tree e)
840132718Skan{
841132718Skan  switch (TREE_CODE (e))
842132718Skan    {
843132718Skan    case MODIFY_EXPR:
844132718Skan    case INIT_EXPR:
845132718Skan      pp_c_logical_or_expression (pp_c_base (pp), TREE_OPERAND (e, 0));
846132718Skan      pp_space (pp);
847132718Skan      pp_equal (pp);
848132718Skan      pp_space (pp);
849132718Skan      pp_cxx_assignment_expression (pp, TREE_OPERAND (e, 1));
850132718Skan      break;
851132718Skan
852132718Skan    case THROW_EXPR:
853132718Skan      pp_cxx_identifier (pp, "throw");
854132718Skan      if (TREE_OPERAND (e, 0))
855169689Skan	pp_cxx_assignment_expression (pp, TREE_OPERAND (e, 0));
856132718Skan      break;
857132718Skan
858132718Skan    case MODOP_EXPR:
859132718Skan      pp_c_logical_or_expression (pp_c_base (pp), TREE_OPERAND (e, 0));
860132718Skan      pp_cxx_assignment_operator (pp, TREE_OPERAND (e, 1));
861132718Skan      pp_cxx_assignment_expression (pp, TREE_OPERAND (e, 2));
862132718Skan      break;
863132718Skan
864132718Skan    default:
865132718Skan      pp_cxx_conditional_expression (pp, e);
866132718Skan      break;
867132718Skan    }
868132718Skan}
869132718Skan
870132718Skanstatic void
871132718Skanpp_cxx_expression (cxx_pretty_printer *pp, tree t)
872132718Skan{
873132718Skan  switch (TREE_CODE (t))
874132718Skan    {
875132718Skan    case STRING_CST:
876132718Skan    case INTEGER_CST:
877132718Skan    case REAL_CST:
878169689Skan      pp_cxx_constant (pp, t);
879132718Skan      break;
880132718Skan
881132718Skan    case RESULT_DECL:
882132718Skan      pp_cxx_unqualified_id (pp, t);
883132718Skan      break;
884132718Skan
885169689Skan#if 0
886132718Skan    case OFFSET_REF:
887169689Skan#endif
888132718Skan    case SCOPE_REF:
889132718Skan    case PTRMEM_CST:
890132718Skan      pp_cxx_qualified_id (pp, t);
891132718Skan      break;
892132718Skan
893132718Skan    case OVERLOAD:
894132718Skan      t = OVL_CURRENT (t);
895132718Skan    case VAR_DECL:
896132718Skan    case PARM_DECL:
897132718Skan    case FIELD_DECL:
898132718Skan    case CONST_DECL:
899132718Skan    case FUNCTION_DECL:
900132718Skan    case BASELINK:
901132718Skan    case TEMPLATE_DECL:
902132718Skan    case TEMPLATE_TYPE_PARM:
903132718Skan    case TEMPLATE_PARM_INDEX:
904169689Skan    case TEMPLATE_TEMPLATE_PARM:
905169689Skan    case STMT_EXPR:
906132718Skan      pp_cxx_primary_expression (pp, t);
907132718Skan      break;
908132718Skan
909132718Skan    case CALL_EXPR:
910132718Skan    case DYNAMIC_CAST_EXPR:
911132718Skan    case STATIC_CAST_EXPR:
912132718Skan    case REINTERPRET_CAST_EXPR:
913132718Skan    case CONST_CAST_EXPR:
914169689Skan#if 0
915132718Skan    case MEMBER_REF:
916169689Skan#endif
917132718Skan    case EMPTY_CLASS_EXPR:
918132718Skan    case TYPEID_EXPR:
919132718Skan    case PSEUDO_DTOR_EXPR:
920132718Skan    case AGGR_INIT_EXPR:
921169689Skan    case ARROW_EXPR:
922132718Skan      pp_cxx_postfix_expression (pp, t);
923132718Skan      break;
924132718Skan
925132718Skan    case NEW_EXPR:
926132718Skan    case VEC_NEW_EXPR:
927132718Skan      pp_cxx_new_expression (pp, t);
928132718Skan      break;
929132718Skan
930132718Skan    case DELETE_EXPR:
931132718Skan    case VEC_DELETE_EXPR:
932132718Skan      pp_cxx_delete_expression (pp, t);
933132718Skan      break;
934132718Skan
935169689Skan    case SIZEOF_EXPR:
936169689Skan    case ALIGNOF_EXPR:
937169689Skan      pp_cxx_unary_expression (pp, t);
938169689Skan      break;
939169689Skan
940132718Skan    case CAST_EXPR:
941132718Skan      pp_cxx_cast_expression (pp, t);
942132718Skan      break;
943132718Skan
944132718Skan    case OFFSET_REF:
945132718Skan    case MEMBER_REF:
946132718Skan    case DOTSTAR_EXPR:
947132718Skan      pp_cxx_pm_expression (pp, t);
948132718Skan      break;
949132718Skan
950132718Skan    case MULT_EXPR:
951132718Skan    case TRUNC_DIV_EXPR:
952132718Skan    case TRUNC_MOD_EXPR:
953132718Skan      pp_cxx_multiplicative_expression (pp, t);
954132718Skan      break;
955132718Skan
956132718Skan    case COND_EXPR:
957132718Skan      pp_cxx_conditional_expression (pp, t);
958132718Skan      break;
959132718Skan
960132718Skan    case MODIFY_EXPR:
961132718Skan    case INIT_EXPR:
962132718Skan    case THROW_EXPR:
963132718Skan    case MODOP_EXPR:
964132718Skan      pp_cxx_assignment_expression (pp, t);
965132718Skan      break;
966132718Skan
967169689Skan    case NON_DEPENDENT_EXPR:
968169689Skan    case MUST_NOT_THROW_EXPR:
969169689Skan      pp_cxx_expression (pp, t);
970169689Skan      break;
971169689Skan
972132718Skan    default:
973132718Skan      pp_c_expression (pp_c_base (pp), t);
974169689Skan      break;
975132718Skan    }
976132718Skan}
977132718Skan
978132718Skan
979132718Skan/* Declarations.  */
980132718Skan
981132718Skan/* function-specifier:
982132718Skan      inline
983132718Skan      virtual
984132718Skan      explicit   */
985169689Skan
986132718Skanstatic void
987132718Skanpp_cxx_function_specifier (cxx_pretty_printer *pp, tree t)
988132718Skan{
989132718Skan  switch (TREE_CODE (t))
990132718Skan    {
991132718Skan    case FUNCTION_DECL:
992132718Skan      if (DECL_VIRTUAL_P (t))
993169689Skan	pp_cxx_identifier (pp, "virtual");
994132718Skan      else if (DECL_CONSTRUCTOR_P (t) && DECL_NONCONVERTING_P (t))
995169689Skan	pp_cxx_identifier (pp, "explicit");
996132718Skan      else
997169689Skan	pp_c_function_specifier (pp_c_base (pp), t);
998132718Skan
999132718Skan    default:
1000132718Skan      break;
1001132718Skan    }
1002132718Skan}
1003132718Skan
1004132718Skan/* decl-specifier-seq:
1005132718Skan      decl-specifier-seq(opt) decl-specifier
1006132718Skan
1007132718Skan   decl-specifier:
1008132718Skan      storage-class-specifier
1009132718Skan      type-specifier
1010132718Skan      function-specifier
1011132718Skan      friend
1012132718Skan      typedef  */
1013169689Skan
1014132718Skanstatic void
1015132718Skanpp_cxx_decl_specifier_seq (cxx_pretty_printer *pp, tree t)
1016132718Skan{
1017132718Skan  switch (TREE_CODE (t))
1018132718Skan    {
1019132718Skan    case VAR_DECL:
1020132718Skan    case PARM_DECL:
1021132718Skan    case CONST_DECL:
1022132718Skan    case FIELD_DECL:
1023132718Skan      pp_cxx_storage_class_specifier (pp, t);
1024132718Skan      pp_cxx_decl_specifier_seq (pp, TREE_TYPE (t));
1025132718Skan      break;
1026169689Skan
1027132718Skan    case TYPE_DECL:
1028132718Skan      pp_cxx_identifier (pp, "typedef");
1029132718Skan      pp_cxx_decl_specifier_seq (pp, TREE_TYPE (t));
1030132718Skan      break;
1031132718Skan
1032132718Skan    case RECORD_TYPE:
1033132718Skan      if (TYPE_PTRMEMFUNC_P (t))
1034169689Skan	{
1035169689Skan	  tree pfm = TYPE_PTRMEMFUNC_FN_TYPE (t);
1036169689Skan	  pp_cxx_decl_specifier_seq (pp, TREE_TYPE (TREE_TYPE (pfm)));
1037169689Skan	  pp_cxx_whitespace (pp);
1038169689Skan	  pp_cxx_ptr_operator (pp, t);
1039169689Skan	}
1040132718Skan      break;
1041132718Skan
1042132718Skan    case FUNCTION_DECL:
1043132718Skan      /* Constructors don't have return types.  And conversion functions
1044169689Skan	 do not have a type-specifier in their return types.  */
1045132718Skan      if (DECL_CONSTRUCTOR_P (t) || DECL_CONV_FN_P (t))
1046169689Skan	pp_cxx_function_specifier (pp, t);
1047132718Skan      else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
1048169689Skan	pp_cxx_decl_specifier_seq (pp, TREE_TYPE (TREE_TYPE (t)));
1049132718Skan      else
1050169689Skan	default:
1051132718Skan      pp_c_declaration_specifiers (pp_c_base (pp), t);
1052132718Skan      break;
1053132718Skan    }
1054132718Skan}
1055132718Skan
1056132718Skan/* simple-type-specifier:
1057132718Skan      ::(opt) nested-name-specifier(opt) type-name
1058132718Skan      ::(opt) nested-name-specifier(opt) template(opt) template-id
1059132718Skan      char
1060132718Skan      wchar_t
1061132718Skan      bool
1062132718Skan      short
1063132718Skan      int
1064132718Skan      long
1065132718Skan      signed
1066132718Skan      unsigned
1067132718Skan      float
1068132718Skan      double
1069132718Skan      void  */
1070169689Skan
1071132718Skanstatic void
1072132718Skanpp_cxx_simple_type_specifier (cxx_pretty_printer *pp, tree t)
1073132718Skan{
1074132718Skan  switch (TREE_CODE (t))
1075132718Skan    {
1076132718Skan    case RECORD_TYPE:
1077132718Skan    case UNION_TYPE:
1078132718Skan    case ENUMERAL_TYPE:
1079132718Skan      pp_cxx_qualified_id (pp, t);
1080132718Skan      break;
1081132718Skan
1082132718Skan    case TEMPLATE_TYPE_PARM:
1083169689Skan    case TEMPLATE_TEMPLATE_PARM:
1084132718Skan    case TEMPLATE_PARM_INDEX:
1085132718Skan      pp_cxx_unqualified_id (pp, t);
1086132718Skan      break;
1087132718Skan
1088132718Skan    case TYPENAME_TYPE:
1089132718Skan      pp_cxx_identifier (pp, "typename");
1090132718Skan      pp_cxx_nested_name_specifier (pp, TYPE_CONTEXT (t));
1091132718Skan      pp_cxx_unqualified_id (pp, TYPE_NAME (t));
1092132718Skan      break;
1093132718Skan
1094132718Skan    default:
1095132718Skan      pp_c_type_specifier (pp_c_base (pp), t);
1096132718Skan      break;
1097132718Skan    }
1098132718Skan}
1099132718Skan
1100132718Skan/* type-specifier-seq:
1101132718Skan      type-specifier type-specifier-seq(opt)
1102132718Skan
1103132718Skan   type-specifier:
1104132718Skan      simple-type-specifier
1105132718Skan      class-specifier
1106132718Skan      enum-specifier
1107132718Skan      elaborated-type-specifier
1108132718Skan      cv-qualifier   */
1109132718Skan
1110132718Skanstatic void
1111132718Skanpp_cxx_type_specifier_seq (cxx_pretty_printer *pp, tree t)
1112132718Skan{
1113132718Skan  switch (TREE_CODE (t))
1114132718Skan    {
1115132718Skan    case TEMPLATE_DECL:
1116132718Skan    case TEMPLATE_TYPE_PARM:
1117169689Skan    case TEMPLATE_TEMPLATE_PARM:
1118132718Skan    case TYPE_DECL:
1119132718Skan    case BOUND_TEMPLATE_TEMPLATE_PARM:
1120169689Skan      pp_cxx_cv_qualifier_seq (pp, t);
1121132718Skan      pp_cxx_simple_type_specifier (pp, t);
1122132718Skan      break;
1123132718Skan
1124132718Skan    case METHOD_TYPE:
1125132718Skan      pp_cxx_type_specifier_seq (pp, TREE_TYPE (t));
1126132718Skan      pp_cxx_space_for_pointer_operator (pp, TREE_TYPE (t));
1127132718Skan      pp_cxx_nested_name_specifier (pp, TYPE_METHOD_BASETYPE (t));
1128132718Skan      break;
1129132718Skan
1130132718Skan    default:
1131132718Skan      if (!(TREE_CODE (t) == FUNCTION_DECL && DECL_CONSTRUCTOR_P (t)))
1132169689Skan	pp_c_specifier_qualifier_list (pp_c_base (pp), t);
1133132718Skan    }
1134132718Skan}
1135132718Skan
1136132718Skan/* ptr-operator:
1137132718Skan      * cv-qualifier-seq(opt)
1138132718Skan      &
1139132718Skan      ::(opt) nested-name-specifier * cv-qualifier-seq(opt)  */
1140132718Skan
1141132718Skanstatic void
1142132718Skanpp_cxx_ptr_operator (cxx_pretty_printer *pp, tree t)
1143132718Skan{
1144132718Skan  if (!TYPE_P (t) && TREE_CODE (t) != TYPE_DECL)
1145132718Skan    t = TREE_TYPE (t);
1146132718Skan  switch (TREE_CODE (t))
1147132718Skan    {
1148132718Skan    case REFERENCE_TYPE:
1149132718Skan    case POINTER_TYPE:
1150132718Skan      if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE
1151169689Skan	  || TYPE_PTR_TO_MEMBER_P (TREE_TYPE (t)))
1152169689Skan	pp_cxx_ptr_operator (pp, TREE_TYPE (t));
1153132718Skan      if (TREE_CODE (t) == POINTER_TYPE)
1154169689Skan	{
1155169689Skan	  pp_star (pp);
1156169689Skan	  pp_cxx_cv_qualifier_seq (pp, t);
1157169689Skan	}
1158132718Skan      else
1159169689Skan	pp_ampersand (pp);
1160132718Skan      break;
1161132718Skan
1162132718Skan    case RECORD_TYPE:
1163132718Skan      if (TYPE_PTRMEMFUNC_P (t))
1164169689Skan	{
1165169689Skan	  pp_cxx_left_paren (pp);
1166169689Skan	  pp_cxx_nested_name_specifier (pp, TYPE_PTRMEMFUNC_OBJECT_TYPE (t));
1167169689Skan	  pp_star (pp);
1168169689Skan	  break;
1169169689Skan	}
1170132718Skan    case OFFSET_TYPE:
1171132718Skan      if (TYPE_PTR_TO_MEMBER_P (t))
1172169689Skan	{
1173169689Skan	  if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
1174169689Skan	    pp_cxx_left_paren (pp);
1175169689Skan	  pp_cxx_nested_name_specifier (pp, TYPE_PTRMEM_CLASS_TYPE (t));
1176169689Skan	  pp_star (pp);
1177169689Skan	  pp_cxx_cv_qualifier_seq (pp, t);
1178169689Skan	  break;
1179169689Skan	}
1180132718Skan      /* else fall through.  */
1181132718Skan
1182132718Skan    default:
1183132718Skan      pp_unsupported_tree (pp, t);
1184132718Skan      break;
1185132718Skan    }
1186132718Skan}
1187132718Skan
1188132718Skanstatic inline tree
1189132718Skanpp_cxx_implicit_parameter_type (tree mf)
1190132718Skan{
1191132718Skan  return TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (mf))));
1192132718Skan}
1193132718Skan
1194132718Skan/*
1195132718Skan   parameter-declaration:
1196132718Skan      decl-specifier-seq declarator
1197132718Skan      decl-specifier-seq declarator = assignment-expression
1198132718Skan      decl-specifier-seq abstract-declarator(opt)
1199132718Skan      decl-specifier-seq abstract-declarator(opt) assignment-expression  */
1200169689Skan
1201132718Skanstatic inline void
1202132718Skanpp_cxx_parameter_declaration (cxx_pretty_printer *pp, tree t)
1203132718Skan{
1204132718Skan  pp_cxx_decl_specifier_seq (pp, t);
1205132718Skan  if (TYPE_P (t))
1206132718Skan    pp_cxx_abstract_declarator (pp, t);
1207132718Skan  else
1208132718Skan    pp_cxx_declarator (pp, t);
1209132718Skan}
1210132718Skan
1211132718Skan/* parameter-declaration-clause:
1212132718Skan      parameter-declaration-list(opt) ...(opt)
1213132718Skan      parameter-declaration-list , ...
1214132718Skan
1215132718Skan   parameter-declaration-list:
1216132718Skan      parameter-declaration
1217132718Skan      parameter-declaration-list , parameter-declaration  */
1218169689Skan
1219132718Skanstatic void
1220132718Skanpp_cxx_parameter_declaration_clause (cxx_pretty_printer *pp, tree t)
1221132718Skan{
1222132718Skan  tree args = TYPE_P (t) ? NULL : FUNCTION_FIRST_USER_PARM (t);
1223169689Skan  tree types =
1224169689Skan    TYPE_P (t) ? TYPE_ARG_TYPES (t) : FUNCTION_FIRST_USER_PARMTYPE (t);
1225132718Skan  const bool abstract = args == NULL
1226132718Skan    || pp_c_base (pp)->flags & pp_c_flag_abstract;
1227132718Skan  bool first = true;
1228132718Skan
1229132718Skan  /* Skip artificial parameter for nonstatic member functions.  */
1230132718Skan  if (TREE_CODE (t) == METHOD_TYPE)
1231132718Skan    types = TREE_CHAIN (types);
1232132718Skan
1233132718Skan  pp_cxx_left_paren (pp);
1234132718Skan  for (; args; args = TREE_CHAIN (args), types = TREE_CHAIN (types))
1235132718Skan    {
1236132718Skan      if (!first)
1237169689Skan	pp_cxx_separate_with (pp, ',');
1238132718Skan      first = false;
1239132718Skan      pp_cxx_parameter_declaration (pp, abstract ? TREE_VALUE (types) : args);
1240132718Skan      if (!abstract && pp_c_base (pp)->flags & pp_cxx_flag_default_argument)
1241169689Skan	{
1242169689Skan	  pp_cxx_whitespace (pp);
1243169689Skan	  pp_equal (pp);
1244169689Skan	  pp_cxx_whitespace (pp);
1245169689Skan	  pp_cxx_assignment_expression (pp, TREE_PURPOSE (types));
1246169689Skan	}
1247132718Skan    }
1248132718Skan  pp_cxx_right_paren (pp);
1249132718Skan}
1250132718Skan
1251132718Skan/* exception-specification:
1252132718Skan      throw ( type-id-list(opt) )
1253132718Skan
1254132718Skan   type-id-list
1255132718Skan      type-id
1256132718Skan      type-id-list , type-id   */
1257169689Skan
1258132718Skanstatic void
1259132718Skanpp_cxx_exception_specification (cxx_pretty_printer *pp, tree t)
1260132718Skan{
1261132718Skan  tree ex_spec = TYPE_RAISES_EXCEPTIONS (t);
1262132718Skan
1263132718Skan  if (!TYPE_NOTHROW_P (t) && ex_spec == NULL)
1264132718Skan    return;
1265132718Skan  pp_cxx_identifier (pp, "throw");
1266132718Skan  pp_cxx_left_paren (pp);
1267132718Skan  for (; ex_spec && TREE_VALUE (ex_spec); ex_spec = TREE_CHAIN (ex_spec))
1268132718Skan    {
1269132718Skan      pp_cxx_type_id (pp, TREE_VALUE (ex_spec));
1270132718Skan      if (TREE_CHAIN (ex_spec))
1271169689Skan	pp_cxx_separate_with (pp, ',');
1272132718Skan    }
1273132718Skan  pp_cxx_right_paren (pp);
1274132718Skan}
1275132718Skan
1276132718Skan/* direct-declarator:
1277132718Skan      declarator-id
1278132718Skan      direct-declarator ( parameter-declaration-clause ) cv-qualifier-seq(opt)
1279169689Skan					    exception-specification(opt)
1280132718Skan      direct-declaration [ constant-expression(opt) ]
1281132718Skan      ( declarator )  */
1282169689Skan
1283132718Skanstatic void
1284132718Skanpp_cxx_direct_declarator (cxx_pretty_printer *pp, tree t)
1285132718Skan{
1286132718Skan  switch (TREE_CODE (t))
1287132718Skan    {
1288132718Skan    case VAR_DECL:
1289132718Skan    case PARM_DECL:
1290132718Skan    case CONST_DECL:
1291132718Skan    case FIELD_DECL:
1292132718Skan      if (DECL_NAME (t))
1293169689Skan	{
1294169689Skan	  pp_cxx_space_for_pointer_operator (pp, TREE_TYPE (t));
1295169689Skan	  pp_cxx_id_expression (pp, DECL_NAME (t));
1296169689Skan	}
1297132718Skan      pp_cxx_abstract_declarator (pp, TREE_TYPE (t));
1298132718Skan      break;
1299169689Skan
1300132718Skan    case FUNCTION_DECL:
1301132718Skan      pp_cxx_space_for_pointer_operator (pp, TREE_TYPE (TREE_TYPE (t)));
1302132718Skan      pp_cxx_id_expression (pp, t);
1303132718Skan      pp_cxx_parameter_declaration_clause (pp, t);
1304169689Skan
1305132718Skan      if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
1306169689Skan	{
1307169689Skan	  pp_base (pp)->padding = pp_before;
1308169689Skan	  pp_cxx_cv_qualifier_seq (pp, pp_cxx_implicit_parameter_type (t));
1309169689Skan	}
1310132718Skan
1311132718Skan      pp_cxx_exception_specification (pp, TREE_TYPE (t));
1312132718Skan      break;
1313132718Skan
1314132718Skan    case TYPENAME_TYPE:
1315132718Skan    case TEMPLATE_DECL:
1316132718Skan    case TEMPLATE_TYPE_PARM:
1317132718Skan    case TEMPLATE_PARM_INDEX:
1318169689Skan    case TEMPLATE_TEMPLATE_PARM:
1319132718Skan      break;
1320132718Skan
1321132718Skan    default:
1322132718Skan      pp_c_direct_declarator (pp_c_base (pp), t);
1323132718Skan      break;
1324132718Skan    }
1325132718Skan}
1326132718Skan
1327132718Skan/* declarator:
1328132718Skan   direct-declarator
1329132718Skan   ptr-operator declarator  */
1330169689Skan
1331132718Skanstatic void
1332132718Skanpp_cxx_declarator (cxx_pretty_printer *pp, tree t)
1333132718Skan{
1334132718Skan  pp_cxx_direct_declarator (pp, t);
1335132718Skan}
1336132718Skan
1337132718Skan/* ctor-initializer:
1338132718Skan      : mem-initializer-list
1339132718Skan
1340132718Skan   mem-initializer-list:
1341132718Skan      mem-initializer
1342132718Skan      mem-initializer , mem-initializer-list
1343132718Skan
1344132718Skan   mem-initializer:
1345132718Skan      mem-initializer-id ( expression-list(opt) )
1346132718Skan
1347132718Skan   mem-initializer-id:
1348132718Skan      ::(opt) nested-name-specifier(opt) class-name
1349132718Skan      identifier   */
1350169689Skan
1351132718Skanstatic void
1352132718Skanpp_cxx_ctor_initializer (cxx_pretty_printer *pp, tree t)
1353132718Skan{
1354132718Skan  t = TREE_OPERAND (t, 0);
1355132718Skan  pp_cxx_whitespace (pp);
1356132718Skan  pp_colon (pp);
1357132718Skan  pp_cxx_whitespace (pp);
1358132718Skan  for (; t; t = TREE_CHAIN (t))
1359132718Skan    {
1360132718Skan      pp_cxx_primary_expression (pp, TREE_PURPOSE (t));
1361132718Skan      pp_cxx_call_argument_list (pp, TREE_VALUE (t));
1362132718Skan      if (TREE_CHAIN (t))
1363169689Skan	pp_cxx_separate_with (pp, ',');
1364132718Skan    }
1365132718Skan}
1366132718Skan
1367132718Skan/* function-definition:
1368132718Skan      decl-specifier-seq(opt) declarator ctor-initializer(opt) function-body
1369132718Skan      decl-specifier-seq(opt) declarator function-try-block  */
1370132718Skan
1371169689Skanstatic void
1372132718Skanpp_cxx_function_definition (cxx_pretty_printer *pp, tree t)
1373132718Skan{
1374132718Skan  tree saved_scope = pp->enclosing_scope;
1375132718Skan  pp_cxx_decl_specifier_seq (pp, t);
1376132718Skan  pp_cxx_declarator (pp, t);
1377132718Skan  pp_needs_newline (pp) = true;
1378132718Skan  pp->enclosing_scope = DECL_CONTEXT (t);
1379132718Skan  if (DECL_SAVED_TREE (t))
1380169689Skan    pp_cxx_statement (pp, DECL_SAVED_TREE (t));
1381132718Skan  else
1382132718Skan    {
1383132718Skan      pp_cxx_semicolon (pp);
1384132718Skan      pp_needs_newline (pp) = true;
1385132718Skan    }
1386132718Skan  pp_flush (pp);
1387132718Skan  pp->enclosing_scope = saved_scope;
1388132718Skan}
1389132718Skan
1390132718Skan/* abstract-declarator:
1391132718Skan      ptr-operator abstract-declarator(opt)
1392132718Skan      direct-abstract-declarator  */
1393169689Skan
1394132718Skanstatic void
1395132718Skanpp_cxx_abstract_declarator (cxx_pretty_printer *pp, tree t)
1396132718Skan{
1397132718Skan  if (TYPE_PTRMEM_P (t) || TYPE_PTRMEMFUNC_P (t))
1398132718Skan    pp_cxx_right_paren (pp);
1399132718Skan  else if (POINTER_TYPE_P (t))
1400132718Skan    {
1401132718Skan      if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE
1402169689Skan	  || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
1403169689Skan	pp_cxx_right_paren (pp);
1404132718Skan      t = TREE_TYPE (t);
1405132718Skan    }
1406132718Skan  pp_cxx_direct_abstract_declarator (pp, t);
1407132718Skan}
1408132718Skan
1409132718Skan/* direct-abstract-declarator:
1410132718Skan      direct-abstract-declarator(opt) ( parameter-declaration-clause )
1411169689Skan			   cv-qualifier-seq(opt) exception-specification(opt)
1412132718Skan      direct-abstract-declarator(opt) [ constant-expression(opt) ]
1413132718Skan      ( abstract-declarator )  */
1414169689Skan
1415132718Skanstatic void
1416132718Skanpp_cxx_direct_abstract_declarator (cxx_pretty_printer *pp, tree t)
1417132718Skan{
1418132718Skan  switch (TREE_CODE (t))
1419132718Skan    {
1420132718Skan    case REFERENCE_TYPE:
1421132718Skan      pp_cxx_abstract_declarator (pp, t);
1422132718Skan      break;
1423132718Skan
1424132718Skan    case RECORD_TYPE:
1425132718Skan      if (TYPE_PTRMEMFUNC_P (t))
1426169689Skan	pp_cxx_direct_abstract_declarator (pp, TYPE_PTRMEMFUNC_FN_TYPE (t));
1427132718Skan      break;
1428132718Skan
1429132718Skan    case METHOD_TYPE:
1430132718Skan    case FUNCTION_TYPE:
1431132718Skan      pp_cxx_parameter_declaration_clause (pp, t);
1432132718Skan      pp_cxx_direct_abstract_declarator (pp, TREE_TYPE (t));
1433132718Skan      if (TREE_CODE (t) == METHOD_TYPE)
1434169689Skan	{
1435169689Skan	  pp_base (pp)->padding = pp_before;
1436169689Skan	  pp_cxx_cv_qualifier_seq
1437169689Skan	    (pp, TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))));
1438169689Skan	}
1439132718Skan      pp_cxx_exception_specification (pp, t);
1440132718Skan      break;
1441132718Skan
1442132718Skan    case TYPENAME_TYPE:
1443132718Skan    case TEMPLATE_TYPE_PARM:
1444132718Skan    case TEMPLATE_TEMPLATE_PARM:
1445132718Skan    case BOUND_TEMPLATE_TEMPLATE_PARM:
1446132718Skan    case UNBOUND_CLASS_TEMPLATE:
1447132718Skan      break;
1448132718Skan
1449132718Skan    default:
1450132718Skan      pp_c_direct_abstract_declarator (pp_c_base (pp), t);
1451169689Skan      break;
1452132718Skan    }
1453132718Skan}
1454132718Skan
1455132718Skan/* type-id:
1456132718Skan     type-specifier-seq abstract-declarator(opt) */
1457169689Skan
1458132718Skanstatic void
1459132718Skanpp_cxx_type_id (cxx_pretty_printer *pp, tree t)
1460132718Skan{
1461132718Skan  pp_flags saved_flags = pp_c_base (pp)->flags;
1462132718Skan  pp_c_base (pp)->flags |= pp_c_flag_abstract;
1463132718Skan
1464132718Skan  switch (TREE_CODE (t))
1465132718Skan    {
1466132718Skan    case TYPE_DECL:
1467132718Skan    case UNION_TYPE:
1468132718Skan    case RECORD_TYPE:
1469132718Skan    case ENUMERAL_TYPE:
1470132718Skan    case TYPENAME_TYPE:
1471132718Skan    case BOUND_TEMPLATE_TEMPLATE_PARM:
1472132718Skan    case UNBOUND_CLASS_TEMPLATE:
1473132718Skan    case TEMPLATE_TEMPLATE_PARM:
1474132718Skan    case TEMPLATE_TYPE_PARM:
1475132718Skan    case TEMPLATE_PARM_INDEX:
1476132718Skan    case TEMPLATE_DECL:
1477132718Skan    case TYPEOF_TYPE:
1478132718Skan    case TEMPLATE_ID_EXPR:
1479132718Skan      pp_cxx_type_specifier_seq (pp, t);
1480132718Skan      break;
1481132718Skan
1482132718Skan    default:
1483132718Skan      pp_c_type_id (pp_c_base (pp), t);
1484132718Skan      break;
1485132718Skan    }
1486132718Skan
1487132718Skan  pp_c_base (pp)->flags = saved_flags;
1488132718Skan}
1489132718Skan
1490132718Skan/* template-argument-list:
1491132718Skan      template-argument
1492132718Skan      template-argument-list, template-argument
1493132718Skan
1494132718Skan   template-argument:
1495132718Skan      assignment-expression
1496132718Skan      type-id
1497132718Skan      template-name   */
1498169689Skan
1499132718Skanstatic void
1500132718Skanpp_cxx_template_argument_list (cxx_pretty_printer *pp, tree t)
1501132718Skan{
1502132718Skan  int i;
1503132718Skan  if (t == NULL)
1504132718Skan    return;
1505132718Skan  for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
1506132718Skan    {
1507132718Skan      tree arg = TREE_VEC_ELT (t, i);
1508132718Skan      if (i != 0)
1509169689Skan	pp_cxx_separate_with (pp, ',');
1510132718Skan      if (TYPE_P (arg) || (TREE_CODE (arg) == TEMPLATE_DECL
1511169689Skan			   && TYPE_P (DECL_TEMPLATE_RESULT (arg))))
1512169689Skan	pp_cxx_type_id (pp, arg);
1513132718Skan      else
1514169689Skan	pp_cxx_expression (pp, arg);
1515132718Skan    }
1516132718Skan}
1517132718Skan
1518132718Skan
1519132718Skanstatic void
1520132718Skanpp_cxx_exception_declaration (cxx_pretty_printer *pp, tree t)
1521132718Skan{
1522169689Skan  t = DECL_EXPR_DECL (t);
1523132718Skan  pp_cxx_type_specifier_seq (pp, t);
1524132718Skan  if (TYPE_P (t))
1525132718Skan    pp_cxx_abstract_declarator (pp, t);
1526132718Skan  else
1527132718Skan    pp_cxx_declarator (pp, t);
1528132718Skan}
1529132718Skan
1530132718Skan/* Statements.  */
1531132718Skan
1532169689Skanstatic void
1533132718Skanpp_cxx_statement (cxx_pretty_printer *pp, tree t)
1534132718Skan{
1535132718Skan  switch (TREE_CODE (t))
1536132718Skan    {
1537169689Skan    case CTOR_INITIALIZER:
1538169689Skan      pp_cxx_ctor_initializer (pp, t);
1539169689Skan      break;
1540169689Skan
1541132718Skan    case USING_STMT:
1542132718Skan      pp_cxx_identifier (pp, "using");
1543132718Skan      pp_cxx_identifier (pp, "namespace");
1544169689Skan      if (DECL_CONTEXT (t))
1545169689Skan	pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
1546132718Skan      pp_cxx_qualified_id (pp, USING_STMT_NAMESPACE (t));
1547132718Skan      break;
1548132718Skan
1549132718Skan    case USING_DECL:
1550132718Skan      pp_cxx_identifier (pp, "using");
1551169689Skan      pp_cxx_nested_name_specifier (pp, USING_DECL_SCOPE (t));
1552132718Skan      pp_cxx_unqualified_id (pp, DECL_NAME (t));
1553132718Skan      break;
1554132718Skan
1555132718Skan    case EH_SPEC_BLOCK:
1556132718Skan      break;
1557132718Skan
1558132718Skan      /* try-block:
1559169689Skan	    try compound-statement handler-seq  */
1560132718Skan    case TRY_BLOCK:
1561132718Skan      pp_maybe_newline_and_indent (pp, 0);
1562132718Skan      pp_cxx_identifier (pp, "try");
1563132718Skan      pp_newline_and_indent (pp, 3);
1564132718Skan      pp_cxx_statement (pp, TRY_STMTS (t));
1565132718Skan      pp_newline_and_indent (pp, -3);
1566132718Skan      if (CLEANUP_P (t))
1567169689Skan	;
1568132718Skan      else
1569169689Skan	pp_cxx_statement (pp, TRY_HANDLERS (t));
1570132718Skan      break;
1571132718Skan
1572132718Skan      /*
1573169689Skan	 handler-seq:
1574169689Skan	    handler handler-seq(opt)
1575132718Skan
1576169689Skan	 handler:
1577169689Skan	 catch ( exception-declaration ) compound-statement
1578132718Skan
1579169689Skan	 exception-declaration:
1580169689Skan	    type-specifier-seq declarator
1581169689Skan	    type-specifier-seq abstract-declarator
1582169689Skan	    ...   */
1583132718Skan    case HANDLER:
1584132718Skan      pp_cxx_identifier (pp, "catch");
1585132718Skan      pp_cxx_left_paren (pp);
1586132718Skan      pp_cxx_exception_declaration (pp, HANDLER_PARMS (t));
1587132718Skan      pp_cxx_right_paren (pp);
1588132718Skan      pp_indentation (pp) += 3;
1589132718Skan      pp_needs_newline (pp) = true;
1590132718Skan      pp_cxx_statement (pp, HANDLER_BODY (t));
1591132718Skan      pp_indentation (pp) -= 3;
1592132718Skan      pp_needs_newline (pp) = true;
1593132718Skan      break;
1594132718Skan
1595169689Skan      /* selection-statement:
1596169689Skan	    if ( expression ) statement
1597169689Skan	    if ( expression ) statement else statement  */
1598169689Skan    case IF_STMT:
1599169689Skan      pp_cxx_identifier (pp, "if");
1600169689Skan      pp_cxx_whitespace (pp);
1601169689Skan      pp_cxx_left_paren (pp);
1602169689Skan      pp_cxx_expression (pp, IF_COND (t));
1603169689Skan      pp_cxx_right_paren (pp);
1604169689Skan      pp_newline_and_indent (pp, 2);
1605169689Skan      pp_cxx_statement (pp, THEN_CLAUSE (t));
1606169689Skan      pp_newline_and_indent (pp, -2);
1607169689Skan      if (ELSE_CLAUSE (t))
1608169689Skan	{
1609169689Skan	  tree else_clause = ELSE_CLAUSE (t);
1610169689Skan	  pp_cxx_identifier (pp, "else");
1611169689Skan	  if (TREE_CODE (else_clause) == IF_STMT)
1612169689Skan	    pp_cxx_whitespace (pp);
1613169689Skan	  else
1614169689Skan	    pp_newline_and_indent (pp, 2);
1615169689Skan	  pp_cxx_statement (pp, else_clause);
1616169689Skan	  if (TREE_CODE (else_clause) != IF_STMT)
1617169689Skan	    pp_newline_and_indent (pp, -2);
1618169689Skan	}
1619169689Skan      break;
1620169689Skan
1621169689Skan    case SWITCH_STMT:
1622169689Skan      pp_cxx_identifier (pp, "switch");
1623169689Skan      pp_space (pp);
1624169689Skan      pp_cxx_left_paren (pp);
1625169689Skan      pp_cxx_expression (pp, SWITCH_STMT_COND (t));
1626169689Skan      pp_cxx_right_paren (pp);
1627169689Skan      pp_indentation (pp) += 3;
1628169689Skan      pp_needs_newline (pp) = true;
1629169689Skan      pp_cxx_statement (pp, SWITCH_STMT_BODY (t));
1630169689Skan      pp_newline_and_indent (pp, -3);
1631169689Skan      break;
1632169689Skan
1633169689Skan      /* iteration-statement:
1634169689Skan	    while ( expression ) statement
1635169689Skan	    do statement while ( expression ) ;
1636169689Skan	    for ( expression(opt) ; expression(opt) ; expression(opt) ) statement
1637169689Skan	    for ( declaration expression(opt) ; expression(opt) ) statement  */
1638169689Skan    case WHILE_STMT:
1639169689Skan      pp_cxx_identifier (pp, "while");
1640169689Skan      pp_space (pp);
1641169689Skan      pp_cxx_left_paren (pp);
1642169689Skan      pp_cxx_expression (pp, WHILE_COND (t));
1643169689Skan      pp_cxx_right_paren (pp);
1644169689Skan      pp_newline_and_indent (pp, 3);
1645169689Skan      pp_cxx_statement (pp, WHILE_BODY (t));
1646169689Skan      pp_indentation (pp) -= 3;
1647169689Skan      pp_needs_newline (pp) = true;
1648169689Skan      break;
1649169689Skan
1650169689Skan    case DO_STMT:
1651169689Skan      pp_cxx_identifier (pp, "do");
1652169689Skan      pp_newline_and_indent (pp, 3);
1653169689Skan      pp_cxx_statement (pp, DO_BODY (t));
1654169689Skan      pp_newline_and_indent (pp, -3);
1655169689Skan      pp_cxx_identifier (pp, "while");
1656169689Skan      pp_space (pp);
1657169689Skan      pp_cxx_left_paren (pp);
1658169689Skan      pp_cxx_expression (pp, DO_COND (t));
1659169689Skan      pp_cxx_right_paren (pp);
1660169689Skan      pp_cxx_semicolon (pp);
1661169689Skan      pp_needs_newline (pp) = true;
1662169689Skan      break;
1663169689Skan
1664169689Skan    case FOR_STMT:
1665169689Skan      pp_cxx_identifier (pp, "for");
1666169689Skan      pp_space (pp);
1667169689Skan      pp_cxx_left_paren (pp);
1668169689Skan      if (FOR_INIT_STMT (t))
1669169689Skan	pp_cxx_statement (pp, FOR_INIT_STMT (t));
1670169689Skan      else
1671169689Skan	pp_cxx_semicolon (pp);
1672169689Skan      pp_needs_newline (pp) = false;
1673169689Skan      pp_cxx_whitespace (pp);
1674169689Skan      if (FOR_COND (t))
1675169689Skan	pp_cxx_expression (pp, FOR_COND (t));
1676169689Skan      pp_cxx_semicolon (pp);
1677169689Skan      pp_needs_newline (pp) = false;
1678169689Skan      pp_cxx_whitespace (pp);
1679169689Skan      if (FOR_EXPR (t))
1680169689Skan	pp_cxx_expression (pp, FOR_EXPR (t));
1681169689Skan      pp_cxx_right_paren (pp);
1682169689Skan      pp_newline_and_indent (pp, 3);
1683169689Skan      pp_cxx_statement (pp, FOR_BODY (t));
1684169689Skan      pp_indentation (pp) -= 3;
1685169689Skan      pp_needs_newline (pp) = true;
1686169689Skan      break;
1687169689Skan
1688169689Skan      /* jump-statement:
1689169689Skan	    goto identifier;
1690169689Skan	    continue ;
1691169689Skan	    return expression(opt) ;  */
1692169689Skan    case BREAK_STMT:
1693169689Skan    case CONTINUE_STMT:
1694169689Skan      pp_identifier (pp, TREE_CODE (t) == BREAK_STMT ? "break" : "continue");
1695169689Skan      pp_cxx_semicolon (pp);
1696169689Skan      pp_needs_newline (pp) = true;
1697169689Skan      break;
1698169689Skan
1699169689Skan      /* expression-statement:
1700169689Skan	    expression(opt) ;  */
1701169689Skan    case EXPR_STMT:
1702169689Skan      pp_cxx_expression (pp, EXPR_STMT_EXPR (t));
1703169689Skan      pp_cxx_semicolon (pp);
1704169689Skan      pp_needs_newline (pp) = true;
1705169689Skan      break;
1706169689Skan
1707169689Skan    case CLEANUP_STMT:
1708169689Skan      pp_cxx_identifier (pp, "try");
1709169689Skan      pp_newline_and_indent (pp, 2);
1710169689Skan      pp_cxx_statement (pp, CLEANUP_BODY (t));
1711169689Skan      pp_newline_and_indent (pp, -2);
1712169689Skan      pp_cxx_identifier (pp, CLEANUP_EH_ONLY (t) ? "catch" : "finally");
1713169689Skan      pp_newline_and_indent (pp, 2);
1714169689Skan      pp_cxx_statement (pp, CLEANUP_EXPR (t));
1715169689Skan      pp_newline_and_indent (pp, -2);
1716169689Skan      break;
1717169689Skan
1718132718Skan    default:
1719132718Skan      pp_c_statement (pp_c_base (pp), t);
1720132718Skan      break;
1721132718Skan    }
1722132718Skan}
1723132718Skan
1724132718Skan/* original-namespace-definition:
1725132718Skan      namespace identifier { namespace-body }
1726132718Skan
1727132718Skan  As an edge case, we also handle unnamed namespace definition here.  */
1728132718Skan
1729132718Skanstatic void
1730132718Skanpp_cxx_original_namespace_definition (cxx_pretty_printer *pp, tree t)
1731132718Skan{
1732132718Skan  pp_cxx_identifier (pp, "namespace");
1733169689Skan  if (DECL_CONTEXT (t))
1734169689Skan    pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
1735132718Skan  if (DECL_NAME (t))
1736132718Skan    pp_cxx_unqualified_id (pp, t);
1737132718Skan  pp_cxx_whitespace (pp);
1738132718Skan  pp_cxx_left_brace (pp);
1739132718Skan  /* We do not print the namespace-body.  */
1740132718Skan  pp_cxx_whitespace (pp);
1741132718Skan  pp_cxx_right_brace (pp);
1742132718Skan}
1743132718Skan
1744132718Skan/* namespace-alias:
1745132718Skan      identifier
1746132718Skan
1747132718Skan   namespace-alias-definition:
1748132718Skan      namespace identifier = qualified-namespace-specifier ;
1749132718Skan
1750132718Skan   qualified-namespace-specifier:
1751132718Skan      ::(opt) nested-name-specifier(opt) namespace-name   */
1752132718Skan
1753132718Skanstatic void
1754132718Skanpp_cxx_namespace_alias_definition (cxx_pretty_printer *pp, tree t)
1755132718Skan{
1756132718Skan  pp_cxx_identifier (pp, "namespace");
1757169689Skan  if (DECL_CONTEXT (t))
1758169689Skan    pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
1759132718Skan  pp_cxx_unqualified_id (pp, t);
1760132718Skan  pp_cxx_whitespace (pp);
1761132718Skan  pp_equal (pp);
1762132718Skan  pp_cxx_whitespace (pp);
1763169689Skan  if (DECL_CONTEXT (DECL_NAMESPACE_ALIAS (t)))
1764169689Skan    pp_cxx_nested_name_specifier (pp,
1765169689Skan				  DECL_CONTEXT (DECL_NAMESPACE_ALIAS (t)));
1766132718Skan  pp_cxx_qualified_id (pp, DECL_NAMESPACE_ALIAS (t));
1767132718Skan  pp_cxx_semicolon (pp);
1768132718Skan}
1769132718Skan
1770132718Skan/* simple-declaration:
1771132718Skan      decl-specifier-seq(opt) init-declarator-list(opt)  */
1772169689Skan
1773132718Skanstatic void
1774132718Skanpp_cxx_simple_declaration (cxx_pretty_printer *pp, tree t)
1775132718Skan{
1776132718Skan  pp_cxx_decl_specifier_seq (pp, t);
1777132718Skan  pp_cxx_init_declarator (pp, t);
1778132718Skan  pp_cxx_semicolon (pp);
1779132718Skan  pp_needs_newline (pp) = true;
1780132718Skan}
1781132718Skan
1782132718Skan/*
1783132718Skan  template-parameter-list:
1784132718Skan     template-parameter
1785132718Skan     template-parameter-list , template-parameter  */
1786132718Skan
1787132718Skanstatic inline void
1788132718Skanpp_cxx_template_parameter_list (cxx_pretty_printer *pp, tree t)
1789132718Skan{
1790132718Skan  const int n = TREE_VEC_LENGTH (t);
1791132718Skan  int i;
1792132718Skan  for (i = 0; i < n; ++i)
1793132718Skan    {
1794132718Skan      if (i)
1795169689Skan	pp_cxx_separate_with (pp, ',');
1796132718Skan      pp_cxx_template_parameter (pp, TREE_VEC_ELT (t, i));
1797132718Skan    }
1798132718Skan}
1799132718Skan
1800132718Skan/* template-parameter:
1801132718Skan      type-parameter
1802132718Skan      parameter-declaration
1803132718Skan
1804132718Skan   type-parameter:
1805132718Skan     class identifier(opt)
1806132718Skan     class identifier(op) = type-id
1807132718Skan     typename identifier(opt)
1808132718Skan     typename identifier(opt) = type-id
1809132718Skan     template < template-parameter-list > class identifier(opt)
1810169689Skan     template < template-parameter-list > class identifier(opt) = template-name  */
1811169689Skan
1812132718Skanstatic void
1813132718Skanpp_cxx_template_parameter (cxx_pretty_printer *pp, tree t)
1814132718Skan{
1815132718Skan  tree parameter =  TREE_VALUE (t);
1816132718Skan  switch (TREE_CODE (parameter))
1817132718Skan    {
1818132718Skan    case TYPE_DECL:
1819132718Skan      pp_cxx_identifier (pp, "class");
1820132718Skan      if (DECL_NAME (parameter))
1821169689Skan	pp_cxx_tree_identifier (pp, DECL_NAME (parameter));
1822132718Skan      /* FIXME: Chech if we should print also default argument.  */
1823132718Skan      break;
1824132718Skan
1825132718Skan    case PARM_DECL:
1826132718Skan      pp_cxx_parameter_declaration (pp, parameter);
1827132718Skan      break;
1828132718Skan
1829132718Skan    case TEMPLATE_DECL:
1830132718Skan      break;
1831132718Skan
1832132718Skan    default:
1833132718Skan      pp_unsupported_tree (pp, t);
1834132718Skan      break;
1835132718Skan    }
1836132718Skan}
1837132718Skan
1838132718Skan/* Pretty-print a template parameter in the canonical form
1839132718Skan   "template-parameter-<level>-<position in parameter list>".  */
1840132718Skan
1841132718Skanvoid
1842132718Skanpp_cxx_canonical_template_parameter (cxx_pretty_printer *pp, tree parm)
1843132718Skan{
1844132718Skan  const enum tree_code code = TREE_CODE (parm);
1845132718Skan
1846132718Skan  /* Brings type template parameters to the canonical forms.  */
1847132718Skan  if (code == TEMPLATE_TYPE_PARM || code == TEMPLATE_TEMPLATE_PARM
1848132718Skan      || code == BOUND_TEMPLATE_TEMPLATE_PARM)
1849132718Skan    parm = TEMPLATE_TYPE_PARM_INDEX (parm);
1850169689Skan
1851132718Skan  pp_cxx_begin_template_argument_list (pp);
1852132718Skan  pp_cxx_identifier (pp, "template-parameter-");
1853132718Skan  pp_wide_integer (pp, TEMPLATE_PARM_LEVEL (parm));
1854132718Skan  pp_minus (pp);
1855132718Skan  pp_wide_integer (pp, TEMPLATE_PARM_IDX (parm) + 1);
1856132718Skan  pp_cxx_end_template_argument_list (pp);
1857132718Skan}
1858132718Skan
1859132718Skan/*
1860132718Skan  template-declaration:
1861132718Skan     export(opt) template < template-parameter-list > declaration   */
1862169689Skan
1863132718Skanstatic void
1864132718Skanpp_cxx_template_declaration (cxx_pretty_printer *pp, tree t)
1865132718Skan{
1866132718Skan  tree tmpl = most_general_template (t);
1867132718Skan  tree level;
1868132718Skan  int i = 0;
1869132718Skan
1870132718Skan  pp_maybe_newline_and_indent (pp, 0);
1871132718Skan  for (level = DECL_TEMPLATE_PARMS (tmpl); level; level = TREE_CHAIN (level))
1872132718Skan    {
1873132718Skan      pp_cxx_identifier (pp, "template");
1874132718Skan      pp_cxx_begin_template_argument_list (pp);
1875132718Skan      pp_cxx_template_parameter_list (pp, TREE_VALUE (level));
1876132718Skan      pp_cxx_end_template_argument_list (pp);
1877132718Skan      pp_newline_and_indent (pp, 3);
1878132718Skan      i += 3;
1879132718Skan    }
1880132718Skan  if (TREE_CODE (t) == FUNCTION_DECL && DECL_SAVED_TREE (t))
1881132718Skan    pp_cxx_function_definition (pp, t);
1882132718Skan  else
1883132718Skan    pp_cxx_simple_declaration (pp, t);
1884132718Skan}
1885132718Skan
1886132718Skanstatic void
1887132718Skanpp_cxx_explicit_specialization (cxx_pretty_printer *pp, tree t)
1888132718Skan{
1889132718Skan  pp_unsupported_tree (pp, t);
1890132718Skan}
1891132718Skan
1892132718Skanstatic void
1893132718Skanpp_cxx_explicit_instantiation (cxx_pretty_printer *pp, tree t)
1894132718Skan{
1895132718Skan  pp_unsupported_tree (pp, t);
1896132718Skan}
1897132718Skan
1898132718Skan/*
1899132718Skan    declaration:
1900132718Skan       block-declaration
1901132718Skan       function-definition
1902132718Skan       template-declaration
1903132718Skan       explicit-instantiation
1904132718Skan       explicit-specialization
1905132718Skan       linkage-specification
1906132718Skan       namespace-definition
1907132718Skan
1908132718Skan    block-declaration:
1909132718Skan       simple-declaration
1910132718Skan       asm-definition
1911132718Skan       namespace-alias-definition
1912132718Skan       using-declaration
1913132718Skan       using-directive  */
1914132718Skanvoid
1915132718Skanpp_cxx_declaration (cxx_pretty_printer *pp, tree t)
1916132718Skan{
1917132718Skan  if (!DECL_LANG_SPECIFIC (t))
1918132718Skan    pp_cxx_simple_declaration (pp, t);
1919132718Skan  else if (DECL_USE_TEMPLATE (t))
1920132718Skan    switch (DECL_USE_TEMPLATE (t))
1921132718Skan      {
1922132718Skan      case 1:
1923169689Skan	pp_cxx_template_declaration (pp, t);
1924169689Skan	break;
1925169689Skan
1926132718Skan      case 2:
1927169689Skan	pp_cxx_explicit_specialization (pp, t);
1928169689Skan	break;
1929132718Skan
1930132718Skan      case 3:
1931169689Skan	pp_cxx_explicit_instantiation (pp, t);
1932169689Skan	break;
1933132718Skan
1934132718Skan      default:
1935169689Skan	break;
1936132718Skan      }
1937132718Skan  else switch (TREE_CODE (t))
1938132718Skan    {
1939132718Skan    case VAR_DECL:
1940132718Skan    case TYPE_DECL:
1941132718Skan      pp_cxx_simple_declaration (pp, t);
1942132718Skan      break;
1943169689Skan
1944132718Skan    case FUNCTION_DECL:
1945132718Skan      if (DECL_SAVED_TREE (t))
1946169689Skan	pp_cxx_function_definition (pp, t);
1947132718Skan      else
1948169689Skan	pp_cxx_simple_declaration (pp, t);
1949132718Skan      break;
1950132718Skan
1951132718Skan    case NAMESPACE_DECL:
1952132718Skan      if (DECL_NAMESPACE_ALIAS (t))
1953169689Skan	pp_cxx_namespace_alias_definition (pp, t);
1954132718Skan      else
1955169689Skan	pp_cxx_original_namespace_definition (pp, t);
1956132718Skan      break;
1957132718Skan
1958132718Skan    default:
1959132718Skan      pp_unsupported_tree (pp, t);
1960132718Skan      break;
1961132718Skan    }
1962132718Skan}
1963132718Skan
1964132718Skan
1965132718Skantypedef c_pretty_print_fn pp_fun;
1966132718Skan
1967169689Skan/* Initialization of a C++ pretty-printer object.  */
1968169689Skan
1969132718Skanvoid
1970132718Skanpp_cxx_pretty_printer_init (cxx_pretty_printer *pp)
1971132718Skan{
1972132718Skan  pp_c_pretty_printer_init (pp_c_base (pp));
1973132718Skan  pp_set_line_maximum_length (pp, 0);
1974132718Skan
1975132718Skan  pp->c_base.declaration = (pp_fun) pp_cxx_declaration;
1976132718Skan  pp->c_base.declaration_specifiers = (pp_fun) pp_cxx_decl_specifier_seq;
1977132718Skan  pp->c_base.function_specifier = (pp_fun) pp_cxx_function_specifier;
1978132718Skan  pp->c_base.type_specifier_seq = (pp_fun) pp_cxx_type_specifier_seq;
1979132718Skan  pp->c_base.declarator = (pp_fun) pp_cxx_declarator;
1980132718Skan  pp->c_base.direct_declarator = (pp_fun) pp_cxx_direct_declarator;
1981132718Skan  pp->c_base.parameter_list = (pp_fun) pp_cxx_parameter_declaration_clause;
1982132718Skan  pp->c_base.type_id = (pp_fun) pp_cxx_type_id;
1983132718Skan  pp->c_base.abstract_declarator = (pp_fun) pp_cxx_abstract_declarator;
1984132718Skan  pp->c_base.direct_abstract_declarator =
1985132718Skan    (pp_fun) pp_cxx_direct_abstract_declarator;
1986132718Skan  pp->c_base.simple_type_specifier = (pp_fun)pp_cxx_simple_type_specifier;
1987132718Skan
1988132718Skan  /* pp->c_base.statement = (pp_fun) pp_cxx_statement;  */
1989132718Skan
1990169689Skan  pp->c_base.constant = (pp_fun) pp_cxx_constant;
1991132718Skan  pp->c_base.id_expression = (pp_fun) pp_cxx_id_expression;
1992132718Skan  pp->c_base.primary_expression = (pp_fun) pp_cxx_primary_expression;
1993132718Skan  pp->c_base.postfix_expression = (pp_fun) pp_cxx_postfix_expression;
1994132718Skan  pp->c_base.unary_expression = (pp_fun) pp_cxx_unary_expression;
1995132718Skan  pp->c_base.multiplicative_expression = (pp_fun) pp_cxx_multiplicative_expression;
1996132718Skan  pp->c_base.conditional_expression = (pp_fun) pp_cxx_conditional_expression;
1997132718Skan  pp->c_base.assignment_expression = (pp_fun) pp_cxx_assignment_expression;
1998132718Skan  pp->c_base.expression = (pp_fun) pp_cxx_expression;
1999132718Skan  pp->enclosing_scope = global_namespace;
2000132718Skan}
2001