示例#1
0
static void
pp_cxx_simple_type_specifier (cxx_pretty_printer *pp, tree t)
{
  switch (TREE_CODE (t))
    {
    case RECORD_TYPE:
    case UNION_TYPE:
    case ENUMERAL_TYPE:
      pp_cxx_qualified_id (pp, t);
      break;

    case TEMPLATE_TYPE_PARM:
    case TEMPLATE_TEMPLATE_PARM:
    case TEMPLATE_PARM_INDEX:
      pp_cxx_unqualified_id (pp, t);
      break;

    case TYPENAME_TYPE:
      pp_cxx_identifier (pp, "typename");
      pp_cxx_nested_name_specifier (pp, TYPE_CONTEXT (t));
      pp_cxx_unqualified_id (pp, TYPE_NAME (t));
      break;

    default:
      pp_c_type_specifier (pp_c_base (pp), t);
      break;
    }
}
示例#2
0
static void
pp_cxx_qualified_id (cxx_pretty_printer *pp, tree t)
{
  switch (TREE_CODE (t))
    {
      /* A pointer-to-member is always qualified.  */
    case PTRMEM_CST:
      pp_cxx_nested_name_specifier (pp, PTRMEM_CST_CLASS (t));
      pp_cxx_unqualified_id (pp, PTRMEM_CST_MEMBER (t));
      break;

      /* In Standard C++, functions cannot possibly be used as
	 nested-name-specifiers.  However, there are situations where
	 is "makes sense" to output the surrounding function name for the
	 purpose of emphasizing on the scope kind.  Just printing the
	 function name might not be sufficient as it may be overloaded; so,
	 we decorate the function with its signature too.
	 FIXME:  This is probably the wrong pretty-printing for conversion
	 functions and some function templates.  */
    case OVERLOAD:
      t = OVL_CURRENT (t);
    case FUNCTION_DECL:
      if (DECL_FUNCTION_MEMBER_P (t))
	pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
      pp_cxx_unqualified_id
	(pp, DECL_CONSTRUCTOR_P (t) ? DECL_CONTEXT (t) : t);
      pp_cxx_parameter_declaration_clause (pp, TREE_TYPE (t));
      break;

    case OFFSET_REF:
    case SCOPE_REF:
      pp_cxx_nested_name_specifier (pp, TREE_OPERAND (t, 0));
      pp_cxx_unqualified_id (pp, TREE_OPERAND (t, 1));
      break;

    default:
      {
	tree scope = TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t);
	if (scope != pp->enclosing_scope)
	  {
	    pp_cxx_nested_name_specifier (pp, scope);
	    pp_cxx_template_keyword_if_needed (pp, scope, t);
	  }
	pp_cxx_unqualified_id (pp, t);
      }
      break;
    }
}
示例#3
0
/* primary-expression:
     literal
     this
     :: identifier
     :: operator-function-id
     :: qualifier-id
     ( expression )
     id-expression   */
static void
pp_cxx_primary_expression (cxx_pretty_printer *pp, tree t)
{
  switch (TREE_CODE (t))
    {
    case STRING_CST:
    case INTEGER_CST:
    case REAL_CST:
      pp_c_constant (pp_c_base (pp), t);
      break;

    case BASELINK:
      t = BASELINK_FUNCTIONS (t);
    case VAR_DECL:
    case PARM_DECL:
    case FIELD_DECL:
    case FUNCTION_DECL:
    case OVERLOAD:
    case CONST_DECL:
    case TEMPLATE_DECL:
      pp_cxx_id_expression (pp, t);
      break;

    case RESULT_DECL:
    case TEMPLATE_TYPE_PARM:
    case TEMPLATE_PARM_INDEX:
      pp_cxx_unqualified_id (pp, t);
      break;

    default:
      pp_c_primary_expression (pp_c_base (pp), t);
      break;
    }
}
示例#4
0
static inline void
pp_cxx_template_id (cxx_pretty_printer *pp, tree t)
{
  pp_cxx_unqualified_id (pp, TREE_OPERAND (t, 0));
  pp_cxx_begin_template_argument_list (pp);
  pp_cxx_template_argument_list (pp, TREE_OPERAND (t, 1));
  pp_cxx_end_template_argument_list (pp);
}
示例#5
0
static inline void
pp_cxx_id_expression (cxx_pretty_printer *pp, tree t)
{
  if (TREE_CODE (t) == OVERLOAD)
    t = OVL_CURRENT (t);
  if (DECL_P (t) && DECL_CONTEXT (t))
    pp_cxx_qualified_id (pp, t);
  else
    pp_cxx_unqualified_id (pp, t);
}
示例#6
0
static void
pp_cxx_namespace_alias_definition (cxx_pretty_printer *pp, tree t)
{
  pp_cxx_identifier (pp, "namespace");
  pp_cxx_unqualified_id (pp, t);
  pp_cxx_whitespace (pp);
  pp_equal (pp);
  pp_cxx_whitespace (pp);
  pp_cxx_qualified_id (pp, DECL_NAMESPACE_ALIAS (t));
  pp_cxx_semicolon (pp);
}
示例#7
0
static void
pp_cxx_nested_name_specifier (cxx_pretty_printer *pp, tree t)
{
  if (t != NULL && t != pp->enclosing_scope)
    {
      tree scope = TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t);
      pp_cxx_nested_name_specifier (pp, scope);
      pp_cxx_template_keyword_if_needed (pp, scope, t);
      pp_cxx_unqualified_id (pp, t);
      pp_cxx_colon_colon (pp);
    }
}
示例#8
0
static void
pp_cxx_original_namespace_definition (cxx_pretty_printer *pp, tree t)
{
  pp_cxx_identifier (pp, "namespace");
  if (DECL_NAME (t))
    pp_cxx_unqualified_id (pp, t);
  pp_cxx_whitespace (pp);
  pp_cxx_left_brace (pp);
  /* We do not print the namespace-body.  */
  pp_cxx_whitespace (pp);
  pp_cxx_right_brace (pp);
}
示例#9
0
/* qualified-id:
      nested-name-specifier template(opt) unqualified-id  */
static void
pp_cxx_qualified_id (cxx_pretty_printer *pp, tree t)
{
  switch (TREE_CODE (t))
    {
    case PTRMEM_CST:
      pp_cxx_nested_name_specifier (pp, PTRMEM_CST_CLASS (t));
      pp_cxx_unqualified_id (pp, PTRMEM_CST_MEMBER (t));
      break;

    case OVERLOAD:
      t = OVL_CURRENT (t);
    case FUNCTION_DECL:
      if (DECL_FUNCTION_MEMBER_P (t))
        pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
      pp_cxx_unqualified_id
        (pp, DECL_CONSTRUCTOR_P (t) ? DECL_CONTEXT (t) : t);
      break;

    case OFFSET_REF:
    case SCOPE_REF:
      pp_cxx_nested_name_specifier (pp, TREE_OPERAND (t, 0));
      pp_cxx_unqualified_id (pp, TREE_OPERAND (t, 1));
      break;

    default:
      {
        tree scope = TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t);
        if (scope != pp->enclosing_scope)
          {
            pp_cxx_nested_name_specifier (pp, scope);
            pp_cxx_template_keyword_if_needed (pp, scope, t);
          }
        pp_cxx_unqualified_id (pp, t);
      }
      break;
    }
}
示例#10
0
static void
pp_cxx_expression (cxx_pretty_printer *pp, tree t)
{
  switch (TREE_CODE (t))
    {
    case STRING_CST:
    case INTEGER_CST:
    case REAL_CST:
      pp_c_constant (pp_c_base (pp), t);
      break;

    case RESULT_DECL:
      pp_cxx_unqualified_id (pp, t);
      break;

#if 0
    case OFFSET_REF:
#endif
    case SCOPE_REF:
    case PTRMEM_CST:
      pp_cxx_qualified_id (pp, t);
      break;

    case OVERLOAD:
      t = OVL_CURRENT (t);
    case VAR_DECL:
    case PARM_DECL:
    case FIELD_DECL:
    case CONST_DECL:
    case FUNCTION_DECL:
    case BASELINK:
    case TEMPLATE_DECL:
    case TEMPLATE_TYPE_PARM:
    case TEMPLATE_PARM_INDEX:
    case TEMPLATE_TEMPLATE_PARM:
    case STMT_EXPR:
      pp_cxx_primary_expression (pp, t);
      break;

    case CALL_EXPR:
    case DYNAMIC_CAST_EXPR:
    case STATIC_CAST_EXPR:
    case REINTERPRET_CAST_EXPR:
    case CONST_CAST_EXPR:
#if 0
    case MEMBER_REF:
#endif
    case EMPTY_CLASS_EXPR:
    case TYPEID_EXPR:
    case PSEUDO_DTOR_EXPR:
    case AGGR_INIT_EXPR:
    case ARROW_EXPR:
      pp_cxx_postfix_expression (pp, t);
      break;

    case NEW_EXPR:
    case VEC_NEW_EXPR:
      pp_cxx_new_expression (pp, t);
      break;

    case DELETE_EXPR:
    case VEC_DELETE_EXPR:
      pp_cxx_delete_expression (pp, t);
      break;

    case SIZEOF_EXPR:
    case ALIGNOF_EXPR:
      pp_cxx_unary_expression (pp, t);
      break;

    case CAST_EXPR:
      pp_cxx_cast_expression (pp, t);
      break;

    case OFFSET_REF:
    case MEMBER_REF:
    case DOTSTAR_EXPR:
      pp_cxx_pm_expression (pp, t);
      break;

    case MULT_EXPR:
    case TRUNC_DIV_EXPR:
    case TRUNC_MOD_EXPR:
      pp_cxx_multiplicative_expression (pp, t);
      break;

    case COND_EXPR:
      pp_cxx_conditional_expression (pp, t);
      break;

    case MODIFY_EXPR:
    case INIT_EXPR:
    case THROW_EXPR:
    case MODOP_EXPR:
      pp_cxx_assignment_expression (pp, t);
      break;

    case NON_DEPENDENT_EXPR:
    case MUST_NOT_THROW_EXPR:
      pp_cxx_expression (pp, t);
      break;

    default:
      pp_c_expression (pp_c_base (pp), t);
      break;
    }
}
示例#11
0
static void
pp_cxx_postfix_expression (cxx_pretty_printer *pp, tree t)
{
  enum tree_code code = TREE_CODE (t);

  switch (code)
    {
    case AGGR_INIT_EXPR:
    case CALL_EXPR:
      {
	tree fun = TREE_OPERAND (t, 0);
	tree args = TREE_OPERAND (t, 1);
	tree saved_scope = pp->enclosing_scope;

	if (TREE_CODE (fun) == ADDR_EXPR)
	  fun = TREE_OPERAND (fun, 0);

	/* In templates, where there is no way to tell whether a given
	   call uses an actual member function.  So the parser builds
	   FUN as a COMPONENT_REF or a plain IDENTIFIER_NODE until
	   instantiation time.  */
	if (TREE_CODE (fun) != FUNCTION_DECL)
	  ;
	else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun))
	  {
	    tree object = code == AGGR_INIT_EXPR && AGGR_INIT_VIA_CTOR_P (t)
	      ? TREE_OPERAND (t, 2)
	      : TREE_VALUE (args);

	    while (TREE_CODE (object) == NOP_EXPR)
	      object = TREE_OPERAND (object, 0);

	    if (TREE_CODE (object) == ADDR_EXPR)
	      object = TREE_OPERAND (object, 0);

	    if (TREE_CODE (TREE_TYPE (object)) != POINTER_TYPE)
	      {
		pp_cxx_postfix_expression (pp, object);
		pp_cxx_dot (pp);
	      }
	    else
	      {
		pp_cxx_postfix_expression (pp, object);
		pp_cxx_arrow (pp);
	      }
	    args = TREE_CHAIN (args);
	    pp->enclosing_scope = strip_pointer_operator (TREE_TYPE (object));
	  }

	pp_cxx_postfix_expression (pp, fun);
	pp->enclosing_scope = saved_scope;
	pp_cxx_call_argument_list (pp, args);
      }
      if (code == AGGR_INIT_EXPR && AGGR_INIT_VIA_CTOR_P (t))
	{
	  pp_cxx_separate_with (pp, ',');
	  pp_cxx_postfix_expression (pp, TREE_OPERAND (t, 2));
	}
      break;

    case BASELINK:
    case VAR_DECL:
    case PARM_DECL:
    case FIELD_DECL:
    case FUNCTION_DECL:
    case OVERLOAD:
    case CONST_DECL:
    case TEMPLATE_DECL:
    case RESULT_DECL:
      pp_cxx_primary_expression (pp, t);
      break;

    case DYNAMIC_CAST_EXPR:
    case STATIC_CAST_EXPR:
    case REINTERPRET_CAST_EXPR:
    case CONST_CAST_EXPR:
      if (code == DYNAMIC_CAST_EXPR)
	pp_cxx_identifier (pp, "dynamic_cast");
      else if (code == STATIC_CAST_EXPR)
	pp_cxx_identifier (pp, "static_cast");
      else if (code == REINTERPRET_CAST_EXPR)
	pp_cxx_identifier (pp, "reinterpret_cast");
      else
	pp_cxx_identifier (pp, "const_cast");
      pp_cxx_begin_template_argument_list (pp);
      pp_cxx_type_id (pp, TREE_TYPE (t));
      pp_cxx_end_template_argument_list (pp);
      pp_left_paren (pp);
      pp_cxx_expression (pp, TREE_OPERAND (t, 0));
      pp_right_paren (pp);
      break;

    case EMPTY_CLASS_EXPR:
      pp_cxx_type_id (pp, TREE_TYPE (t));
      pp_left_paren (pp);
      pp_right_paren (pp);
      break;

    case TYPEID_EXPR:
      t = TREE_OPERAND (t, 0);
      pp_cxx_identifier (pp, "typeid");
      pp_left_paren (pp);
      if (TYPE_P (t))
	pp_cxx_type_id (pp, t);
      else
	pp_cxx_expression (pp, t);
      pp_right_paren (pp);
      break;

    case PSEUDO_DTOR_EXPR:
      pp_cxx_postfix_expression (pp, TREE_OPERAND (t, 0));
      pp_cxx_dot (pp);
      pp_cxx_qualified_id (pp, TREE_OPERAND (t, 1));
      pp_cxx_colon_colon (pp);
      pp_complement (pp);
      pp_cxx_unqualified_id (pp, TREE_OPERAND (t, 2));
      break;

    case ARROW_EXPR:
      pp_cxx_postfix_expression (pp, TREE_OPERAND (t, 0));
      pp_cxx_arrow (pp);
      break;

    default:
      pp_c_postfix_expression (pp_c_base (pp), t);
      break;
    }
}
示例#12
0
static void
pp_cxx_statement (cxx_pretty_printer *pp, tree t)
{
  switch (TREE_CODE (t))
    {
    case CTOR_INITIALIZER:
      pp_cxx_ctor_initializer (pp, t);
      break;

    case USING_STMT:
      pp_cxx_identifier (pp, "using");
      pp_cxx_identifier (pp, "namespace");
      if (DECL_CONTEXT (t))
	pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
      pp_cxx_qualified_id (pp, USING_STMT_NAMESPACE (t));
      break;

    case USING_DECL:
      pp_cxx_identifier (pp, "using");
      pp_cxx_nested_name_specifier (pp, USING_DECL_SCOPE (t));
      pp_cxx_unqualified_id (pp, DECL_NAME (t));
      break;

    case EH_SPEC_BLOCK:
      break;

      /* try-block:
	    try compound-statement handler-seq  */
    case TRY_BLOCK:
      pp_maybe_newline_and_indent (pp, 0);
      pp_cxx_identifier (pp, "try");
      pp_newline_and_indent (pp, 3);
      pp_cxx_statement (pp, TRY_STMTS (t));
      pp_newline_and_indent (pp, -3);
      if (CLEANUP_P (t))
	;
      else
	pp_cxx_statement (pp, TRY_HANDLERS (t));
      break;

      /*
	 handler-seq:
	    handler handler-seq(opt)

	 handler:
	 catch ( exception-declaration ) compound-statement

	 exception-declaration:
	    type-specifier-seq declarator
	    type-specifier-seq abstract-declarator
	    ...   */
    case HANDLER:
      pp_cxx_identifier (pp, "catch");
      pp_cxx_left_paren (pp);
      pp_cxx_exception_declaration (pp, HANDLER_PARMS (t));
      pp_cxx_right_paren (pp);
      pp_indentation (pp) += 3;
      pp_needs_newline (pp) = true;
      pp_cxx_statement (pp, HANDLER_BODY (t));
      pp_indentation (pp) -= 3;
      pp_needs_newline (pp) = true;
      break;

      /* selection-statement:
	    if ( expression ) statement
	    if ( expression ) statement else statement  */
    case IF_STMT:
      pp_cxx_identifier (pp, "if");
      pp_cxx_whitespace (pp);
      pp_cxx_left_paren (pp);
      pp_cxx_expression (pp, IF_COND (t));
      pp_cxx_right_paren (pp);
      pp_newline_and_indent (pp, 2);
      pp_cxx_statement (pp, THEN_CLAUSE (t));
      pp_newline_and_indent (pp, -2);
      if (ELSE_CLAUSE (t))
	{
	  tree else_clause = ELSE_CLAUSE (t);
	  pp_cxx_identifier (pp, "else");
	  if (TREE_CODE (else_clause) == IF_STMT)
	    pp_cxx_whitespace (pp);
	  else
	    pp_newline_and_indent (pp, 2);
	  pp_cxx_statement (pp, else_clause);
	  if (TREE_CODE (else_clause) != IF_STMT)
	    pp_newline_and_indent (pp, -2);
	}
      break;

    case SWITCH_STMT:
      pp_cxx_identifier (pp, "switch");
      pp_space (pp);
      pp_cxx_left_paren (pp);
      pp_cxx_expression (pp, SWITCH_STMT_COND (t));
      pp_cxx_right_paren (pp);
      pp_indentation (pp) += 3;
      pp_needs_newline (pp) = true;
      pp_cxx_statement (pp, SWITCH_STMT_BODY (t));
      pp_newline_and_indent (pp, -3);
      break;

      /* iteration-statement:
	    while ( expression ) statement
	    do statement while ( expression ) ;
	    for ( expression(opt) ; expression(opt) ; expression(opt) ) statement
	    for ( declaration expression(opt) ; expression(opt) ) statement  */
    case WHILE_STMT:
      pp_cxx_identifier (pp, "while");
      pp_space (pp);
      pp_cxx_left_paren (pp);
      pp_cxx_expression (pp, WHILE_COND (t));
      pp_cxx_right_paren (pp);
      pp_newline_and_indent (pp, 3);
      pp_cxx_statement (pp, WHILE_BODY (t));
      pp_indentation (pp) -= 3;
      pp_needs_newline (pp) = true;
      break;

    case DO_STMT:
      pp_cxx_identifier (pp, "do");
      pp_newline_and_indent (pp, 3);
      pp_cxx_statement (pp, DO_BODY (t));
      pp_newline_and_indent (pp, -3);
      pp_cxx_identifier (pp, "while");
      pp_space (pp);
      pp_cxx_left_paren (pp);
      pp_cxx_expression (pp, DO_COND (t));
      pp_cxx_right_paren (pp);
      pp_cxx_semicolon (pp);
      pp_needs_newline (pp) = true;
      break;

    case FOR_STMT:
      pp_cxx_identifier (pp, "for");
      pp_space (pp);
      pp_cxx_left_paren (pp);
      if (FOR_INIT_STMT (t))
	pp_cxx_statement (pp, FOR_INIT_STMT (t));
      else
	pp_cxx_semicolon (pp);
      pp_needs_newline (pp) = false;
      pp_cxx_whitespace (pp);
      if (FOR_COND (t))
	pp_cxx_expression (pp, FOR_COND (t));
      pp_cxx_semicolon (pp);
      pp_needs_newline (pp) = false;
      pp_cxx_whitespace (pp);
      if (FOR_EXPR (t))
	pp_cxx_expression (pp, FOR_EXPR (t));
      pp_cxx_right_paren (pp);
      pp_newline_and_indent (pp, 3);
      pp_cxx_statement (pp, FOR_BODY (t));
      pp_indentation (pp) -= 3;
      pp_needs_newline (pp) = true;
      break;

      /* jump-statement:
	    goto identifier;
	    continue ;
	    return expression(opt) ;  */
    case BREAK_STMT:
    case CONTINUE_STMT:
      pp_identifier (pp, TREE_CODE (t) == BREAK_STMT ? "break" : "continue");
      pp_cxx_semicolon (pp);
      pp_needs_newline (pp) = true;
      break;

      /* expression-statement:
	    expression(opt) ;  */
    case EXPR_STMT:
      pp_cxx_expression (pp, EXPR_STMT_EXPR (t));
      pp_cxx_semicolon (pp);
      pp_needs_newline (pp) = true;
      break;

    case CLEANUP_STMT:
      pp_cxx_identifier (pp, "try");
      pp_newline_and_indent (pp, 2);
      pp_cxx_statement (pp, CLEANUP_BODY (t));
      pp_newline_and_indent (pp, -2);
      pp_cxx_identifier (pp, CLEANUP_EH_ONLY (t) ? "catch" : "finally");
      pp_newline_and_indent (pp, 2);
      pp_cxx_statement (pp, CLEANUP_EXPR (t));
      pp_newline_and_indent (pp, -2);
      break;

    default:
      pp_c_statement (pp_c_base (pp), t);
      break;
    }
}
示例#13
0
static void
pp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t)
{
  enum tree_code code = TREE_CODE (t);
  switch (code)
    {
    case RESULT_DECL:
      pp_cxx_identifier (pp, "<return-value>");
      break;

    case OVERLOAD:
      t = OVL_CURRENT (t);
    case VAR_DECL:
    case PARM_DECL:
    case CONST_DECL:
    case TYPE_DECL:
    case FUNCTION_DECL:
    case NAMESPACE_DECL:
    case FIELD_DECL:
    case LABEL_DECL:
    case USING_DECL:
    case TEMPLATE_DECL:
      t = DECL_NAME (t);

    case IDENTIFIER_NODE:
      if (t == NULL)
	pp_cxx_identifier (pp, "<unnamed>");
      else if (IDENTIFIER_TYPENAME_P (t))
	pp_cxx_conversion_function_id (pp, t);
      else
	{
	  if (is_destructor_name (t))
	    {
	      pp_complement (pp);
	      /* FIXME: Why is this necessary? */
	      if (TREE_TYPE (t))
		t = constructor_name (TREE_TYPE (t));
	    }
	  pp_cxx_tree_identifier (pp, t);
	}
      break;

    case TEMPLATE_ID_EXPR:
      pp_cxx_template_id (pp, t);
      break;

    case BASELINK:
      pp_cxx_unqualified_id (pp, BASELINK_FUNCTIONS (t));
      break;

    case RECORD_TYPE:
    case UNION_TYPE:
    case ENUMERAL_TYPE:
      pp_cxx_unqualified_id (pp, TYPE_NAME (t));
      break;

    case TEMPLATE_TYPE_PARM:
    case TEMPLATE_TEMPLATE_PARM:
      if (TYPE_IDENTIFIER (t))
	pp_cxx_unqualified_id (pp, TYPE_IDENTIFIER (t));
      else
	pp_cxx_canonical_template_parameter (pp, t);
      break;

    case TEMPLATE_PARM_INDEX:
      pp_cxx_unqualified_id (pp, TEMPLATE_PARM_DECL (t));
      break;

    default:
      pp_unsupported_tree (pp, t);
      break;
    }
}
示例#14
0
void
pp_cxx_statement (cxx_pretty_printer *pp, tree t)
{
  switch (TREE_CODE (t))
    {
    case USING_STMT:
      pp_cxx_identifier (pp, "using");
      pp_cxx_identifier (pp, "namespace");
      pp_cxx_qualified_id (pp, USING_STMT_NAMESPACE (t));
      break;

    case USING_DECL:
      pp_cxx_identifier (pp, "using");
      pp_cxx_nested_name_specifier (pp, DECL_INITIAL (t));
      pp_cxx_unqualified_id (pp, DECL_NAME (t));
      break;

    case EH_SPEC_BLOCK:
      break;

      /* try-block:
            try compound-statement handler-seq  */
    case TRY_BLOCK:
      pp_maybe_newline_and_indent (pp, 0);
      pp_cxx_identifier (pp, "try");
      pp_newline_and_indent (pp, 3);
      pp_cxx_statement (pp, TRY_STMTS (t));
      pp_newline_and_indent (pp, -3);
      if (CLEANUP_P (t))
        ;
      else
        pp_cxx_statement (pp, TRY_HANDLERS (t));
      break;

      /*
         handler-seq:
            handler handler-seq(opt)

         handler:
         catch ( exception-declaration ) compound-statement 

         exception-declaration:
            type-specifier-seq declarator
            type-specifier-seq abstract-declarator
            ...   */
    case HANDLER:
      pp_cxx_identifier (pp, "catch");
      pp_cxx_left_paren (pp);
      pp_cxx_exception_declaration (pp, HANDLER_PARMS (t));
      pp_cxx_right_paren (pp);
      pp_indentation (pp) += 3;
      pp_needs_newline (pp) = true;
      pp_cxx_statement (pp, HANDLER_BODY (t));
      pp_indentation (pp) -= 3;
      pp_needs_newline (pp) = true;
      break;

    default:
      pp_c_statement (pp_c_base (pp), t);
      break;
    }
}