1742 lines
45 KiB
C
1742 lines
45 KiB
C
/* Implementation of subroutines for the GNU C++ pretty-printer.
|
||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||
Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
|
||
|
||
This file is part of GCC.
|
||
|
||
GCC is free software; you can redistribute it and/or modify it under
|
||
the terms of the GNU General Public License as published by the Free
|
||
Software Foundation; either version 2, or (at your option) any later
|
||
version.
|
||
|
||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||
for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with GCC; see the file COPYING. If not, write to the Free
|
||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||
02111-1307, USA. */
|
||
|
||
#include "config.h"
|
||
#include "system.h"
|
||
#include "coretypes.h"
|
||
#include "tm.h"
|
||
#include "real.h"
|
||
#include "cxx-pretty-print.h"
|
||
#include "cp-tree.h"
|
||
#include "toplev.h"
|
||
|
||
static void pp_cxx_unqualified_id (cxx_pretty_printer *, tree);
|
||
static void pp_cxx_nested_name_specifier (cxx_pretty_printer *, tree);
|
||
static void pp_cxx_qualified_id (cxx_pretty_printer *, tree);
|
||
static void pp_cxx_assignment_expression (cxx_pretty_printer *, tree);
|
||
static void pp_cxx_expression (cxx_pretty_printer *, tree);
|
||
static void pp_cxx_template_argument_list (cxx_pretty_printer *, tree);
|
||
static void pp_cxx_type_specifier_seq (cxx_pretty_printer *, tree);
|
||
static void pp_cxx_ptr_operator (cxx_pretty_printer *, tree);
|
||
static void pp_cxx_type_id (cxx_pretty_printer *, tree);
|
||
static void pp_cxx_direct_abstract_declarator (cxx_pretty_printer *, tree);
|
||
static void pp_cxx_declarator (cxx_pretty_printer *, tree);
|
||
static void pp_cxx_abstract_declarator (cxx_pretty_printer *, tree);
|
||
static void pp_cxx_template_parameter (cxx_pretty_printer *, tree);
|
||
|
||
#define pp_cxx_whitespace(PP) pp_c_whitespace (pp_c_base (PP))
|
||
#define pp_cxx_left_paren(PP) pp_c_left_paren (pp_c_base (PP))
|
||
#define pp_cxx_right_paren(PP) pp_c_right_paren (pp_c_base (PP))
|
||
#define pp_cxx_left_brace(PP) pp_c_left_brace (pp_c_base (PP))
|
||
#define pp_cxx_right_brace(PP) pp_c_right_brace (pp_c_base (PP))
|
||
#define pp_cxx_dot(PP) pp_c_dot (pp_c_base (PP))
|
||
#define pp_cxx_arrow(PP) pp_c_arrow (pp_c_base (PP))
|
||
#define pp_cxx_semicolon(PP) pp_c_semicolon (pp_c_base (PP))
|
||
|
||
static inline void
|
||
pp_cxx_nonconsecutive_character (cxx_pretty_printer *pp, int c)
|
||
{
|
||
const char *p = pp_last_position_in_text (pp);
|
||
|
||
if (p != NULL && *p == c)
|
||
pp_cxx_whitespace (pp);
|
||
pp_character (pp, c);
|
||
pp_base (pp)->padding = pp_none;
|
||
}
|
||
|
||
#define pp_cxx_begin_template_argument_list(PP) \
|
||
pp_cxx_nonconsecutive_character (PP, '<')
|
||
#define pp_cxx_end_template_argument_list(PP) \
|
||
pp_cxx_nonconsecutive_character (PP, '>')
|
||
|
||
#define pp_cxx_identifier(PP, ID) pp_c_identifier (pp_c_base (PP), ID)
|
||
#define pp_cxx_tree_identifier(PP, T) pp_c_tree_identifier (pp_c_base (PP), T)
|
||
|
||
#define pp_cxx_cv_qualifier_seq(PP, T) \
|
||
pp_c_type_qualifier_list (pp_c_base (PP), T)
|
||
#define pp_cxx_storage_class_specifier(PP, T) \
|
||
pp_c_storage_class_specifier (pp_c_base (PP), T)
|
||
#define pp_cxx_expression_list(PP, T) \
|
||
pp_c_expression_list (pp_c_base (PP), T)
|
||
#define pp_cxx_space_for_pointer_operator(PP, T) \
|
||
pp_c_space_for_pointer_operator (pp_c_base (PP), T)
|
||
#define pp_cxx_init_declarator(PP, T) \
|
||
pp_c_init_declarator (pp_c_base (PP), T)
|
||
#define pp_cxx_call_argument_list(PP, T) \
|
||
pp_c_call_argument_list (pp_c_base (PP), T)
|
||
|
||
static void
|
||
pp_cxx_colon_colon (cxx_pretty_printer *pp)
|
||
{
|
||
pp_colon_colon (pp);
|
||
pp_base (pp)->padding = pp_none;
|
||
}
|
||
|
||
|
||
/* Expressions. */
|
||
|
||
static inline bool
|
||
is_destructor_name (tree name)
|
||
{
|
||
return name == complete_dtor_identifier
|
||
|| name == base_dtor_identifier
|
||
|| name == deleting_dtor_identifier;
|
||
}
|
||
|
||
/* conversion-function-id:
|
||
operator conversion-type-id
|
||
|
||
conversion-type-id:
|
||
type-specifier-seq conversion-declarator(opt)
|
||
|
||
conversion-declarator:
|
||
ptr-operator conversion-declarator(opt) */
|
||
static inline void
|
||
pp_cxx_conversion_function_id (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
pp_cxx_identifier (pp, "operator");
|
||
pp_cxx_type_specifier_seq (pp, TREE_TYPE (t));
|
||
}
|
||
|
||
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);
|
||
}
|
||
|
||
/* unqualified-id:
|
||
identifier
|
||
operator-function-id
|
||
conversion-function-id
|
||
~ class-name
|
||
template-id */
|
||
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, "<anonymous>");
|
||
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:
|
||
t = TYPE_FIELDS (t);
|
||
case TEMPLATE_PARM_INDEX:
|
||
pp_cxx_unqualified_id (pp, TEMPLATE_PARM_DECL (t));
|
||
break;
|
||
|
||
default:
|
||
pp_unsupported_tree (pp, t);
|
||
break;
|
||
}
|
||
}
|
||
|
||
static inline void
|
||
pp_cxx_template_keyword_if_needed (cxx_pretty_printer *pp, tree scope, tree t)
|
||
{
|
||
if (TREE_CODE (t) == TEMPLATE_ID_EXPR
|
||
&& TYPE_P (scope) && dependent_type_p (scope))
|
||
pp_cxx_identifier (pp, "template");
|
||
}
|
||
|
||
/* nested-name-specifier:
|
||
class-or-namespace-name :: nested-name-specifier(opt)
|
||
class-or-namespace-name :: template nested-name-specifier */
|
||
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);
|
||
}
|
||
}
|
||
|
||
/* 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;
|
||
}
|
||
}
|
||
|
||
/* id-expression:
|
||
unqualified-id
|
||
qualified-id */
|
||
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);
|
||
}
|
||
|
||
/* 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;
|
||
}
|
||
}
|
||
|
||
/* postfix-expression:
|
||
primary-expression
|
||
postfix-expression [ expression ]
|
||
postfix-expression ( expression-list(opt) )
|
||
simple-type-specifier ( expression-list(opt) )
|
||
typename ::(opt) nested-name-specifier identifier ( expression-list(opt) )
|
||
typename ::(opt) nested-name-specifier template(opt)
|
||
template-id ( expression-list(opt) )
|
||
postfix-expression . template(opt) ::(opt) id-expression
|
||
postfix-expression -> template(opt) ::(opt) id-expression
|
||
postfix-expression . pseudo-destructor-name
|
||
postfix-expression -> pseudo-destructor-name
|
||
postfix-expression ++
|
||
postfix-expression --
|
||
dynamic_cast < type-id > ( expression )
|
||
static_cast < type-id > ( expression )
|
||
reinterpret_cast < type-id > ( expression )
|
||
const_cast < type-id > ( expression )
|
||
typeid ( expression )
|
||
typeif ( type-id ) */
|
||
|
||
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_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_identifier (pp, "dynamic_cast");
|
||
else if (code == STATIC_CAST_EXPR)
|
||
pp_identifier (pp, "static_cast");
|
||
else if (code == REINTERPRET_CAST_EXPR)
|
||
pp_identifier (pp, "reinterpret_cast");
|
||
else
|
||
pp_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;
|
||
|
||
default:
|
||
pp_c_postfix_expression (pp_c_base (pp), t);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* new-expression:
|
||
::(opt) new new-placement(opt) new-type-id new-initializer(opt)
|
||
::(opt) new new-placement(opt) ( type-id ) new-initializer(opt)
|
||
|
||
new-placement:
|
||
( expression-list )
|
||
|
||
new-type-id:
|
||
type-specifier-seq new-declarator(opt)
|
||
|
||
new-declarator:
|
||
ptr-operator new-declarator(opt)
|
||
direct-new-declarator
|
||
|
||
direct-new-declarator
|
||
[ expression ]
|
||
direct-new-declarator [ constant-expression ]
|
||
|
||
new-initializer:
|
||
( expression-list(opt) ) */
|
||
static void
|
||
pp_cxx_new_expression (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
enum tree_code code = TREE_CODE (t);
|
||
switch (code)
|
||
{
|
||
case NEW_EXPR:
|
||
case VEC_NEW_EXPR:
|
||
if (NEW_EXPR_USE_GLOBAL (t))
|
||
pp_cxx_colon_colon (pp);
|
||
pp_cxx_identifier (pp, "new");
|
||
if (TREE_OPERAND (t, 0))
|
||
{
|
||
pp_cxx_call_argument_list (pp, TREE_OPERAND (t, 0));
|
||
pp_space (pp);
|
||
}
|
||
/* FIXME: array-types are built with one more element. */
|
||
pp_cxx_type_id (pp, TREE_OPERAND (t, 1));
|
||
if (TREE_OPERAND (t, 2))
|
||
{
|
||
pp_left_paren (pp);
|
||
t = TREE_OPERAND (t, 2);
|
||
if (TREE_CODE (t) == TREE_LIST)
|
||
pp_c_expression_list (pp_c_base (pp), t);
|
||
else if (t == void_zero_node)
|
||
; /* OK, empty initializer list. */
|
||
else
|
||
pp_cxx_expression (pp, t);
|
||
pp_right_paren (pp);
|
||
}
|
||
break;
|
||
|
||
default:
|
||
pp_unsupported_tree (pp, t);
|
||
}
|
||
}
|
||
|
||
/* delete-expression:
|
||
::(opt) delete cast-expression
|
||
::(opt) delete [ ] cast-expression */
|
||
static void
|
||
pp_cxx_delete_expression (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
enum tree_code code = TREE_CODE (t);
|
||
switch (code)
|
||
{
|
||
case DELETE_EXPR:
|
||
case VEC_DELETE_EXPR:
|
||
if (DELETE_EXPR_USE_GLOBAL (t))
|
||
pp_cxx_colon_colon (pp);
|
||
pp_cxx_identifier (pp, "delete");
|
||
if (code == VEC_DELETE_EXPR)
|
||
{
|
||
pp_left_bracket (pp);
|
||
pp_right_bracket (pp);
|
||
}
|
||
pp_c_cast_expression (pp_c_base (pp), TREE_OPERAND (t, 0));
|
||
break;
|
||
|
||
default:
|
||
pp_unsupported_tree (pp, t);
|
||
}
|
||
}
|
||
|
||
/* unary-expression:
|
||
postfix-expression
|
||
++ cast-expression
|
||
-- cast-expression
|
||
unary-operator cast-expression
|
||
sizeof unary-expression
|
||
sizeof ( type-id )
|
||
new-expression
|
||
delete-expression
|
||
|
||
unary-operator: one of
|
||
* & + - !
|
||
|
||
GNU extensions:
|
||
__alignof__ unary-expression
|
||
__alignof__ ( type-id ) */
|
||
static void
|
||
pp_cxx_unary_expression (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
enum tree_code code = TREE_CODE (t);
|
||
switch (code)
|
||
{
|
||
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;
|
||
|
||
default:
|
||
pp_c_unary_expression (pp_c_base (pp), t);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* cast-expression:
|
||
unary-expression
|
||
( type-id ) cast-expression */
|
||
static void
|
||
pp_cxx_cast_expression (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
switch (TREE_CODE (t))
|
||
{
|
||
case CAST_EXPR:
|
||
pp_cxx_type_id (pp, TREE_TYPE (t));
|
||
pp_cxx_call_argument_list (pp, TREE_OPERAND (t, 0));
|
||
break;
|
||
|
||
default:
|
||
pp_c_cast_expression (pp_c_base (pp), t);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* pm-expression:
|
||
cast-expression
|
||
pm-expression .* cast-expression
|
||
pm-expression ->* cast-expression */
|
||
static void
|
||
pp_cxx_pm_expression (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
switch (TREE_CODE (t))
|
||
{
|
||
/* Handle unfortunate OFFESET_REF overloading here. */
|
||
case OFFSET_REF:
|
||
if (TYPE_P (TREE_OPERAND (t, 0)))
|
||
{
|
||
pp_cxx_qualified_id (pp, t);
|
||
break;
|
||
}
|
||
/* Else fall through. */
|
||
case MEMBER_REF:
|
||
case DOTSTAR_EXPR:
|
||
pp_cxx_pm_expression (pp, TREE_OPERAND (t, 0));
|
||
pp_cxx_dot (pp);
|
||
pp_star(pp);
|
||
pp_cxx_cast_expression (pp, TREE_OPERAND (t, 1));
|
||
break;
|
||
|
||
|
||
default:
|
||
pp_cxx_cast_expression (pp, t);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* multiplicative-expression:
|
||
pm-expression
|
||
multiplicative-expression * pm-expression
|
||
multiplicative-expression / pm-expression
|
||
multiplicative-expression % pm-expression */
|
||
static void
|
||
pp_cxx_multiplicative_expression (cxx_pretty_printer *pp, tree e)
|
||
{
|
||
enum tree_code code = TREE_CODE (e);
|
||
switch (code)
|
||
{
|
||
case MULT_EXPR:
|
||
case TRUNC_DIV_EXPR:
|
||
case TRUNC_MOD_EXPR:
|
||
pp_cxx_multiplicative_expression (pp, TREE_OPERAND (e, 0));
|
||
pp_space (pp);
|
||
if (code == MULT_EXPR)
|
||
pp_star (pp);
|
||
else if (code == TRUNC_DIV_EXPR)
|
||
pp_slash (pp);
|
||
else
|
||
pp_modulo (pp);
|
||
pp_space (pp);
|
||
pp_cxx_pm_expression (pp, TREE_OPERAND (e, 1));
|
||
break;
|
||
|
||
default:
|
||
pp_cxx_pm_expression (pp, e);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* conditional-expression:
|
||
logical-or-expression
|
||
logical-or-expression ? expression : assignment-expression */
|
||
static void
|
||
pp_cxx_conditional_expression (cxx_pretty_printer *pp, tree e)
|
||
{
|
||
if (TREE_CODE (e) == COND_EXPR)
|
||
{
|
||
pp_c_logical_or_expression (pp_c_base (pp), TREE_OPERAND (e, 0));
|
||
pp_space (pp);
|
||
pp_question (pp);
|
||
pp_space (pp);
|
||
pp_cxx_expression (pp, TREE_OPERAND (e, 1));
|
||
pp_space (pp);
|
||
pp_cxx_assignment_expression (pp, TREE_OPERAND (e, 2));
|
||
}
|
||
else
|
||
pp_c_logical_or_expression (pp_c_base (pp), e);
|
||
}
|
||
|
||
static void
|
||
pp_cxx_assignment_operator (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
const char *op;
|
||
|
||
switch (TREE_CODE (t))
|
||
{
|
||
case NOP_EXPR:
|
||
op = "=";
|
||
break;
|
||
|
||
case PLUS_EXPR:
|
||
op = "+=";
|
||
break;
|
||
|
||
case MINUS_EXPR:
|
||
op = "-=";
|
||
break;
|
||
|
||
case TRUNC_DIV_EXPR:
|
||
op = "/=";
|
||
break;
|
||
|
||
case TRUNC_MOD_EXPR:
|
||
op = "%=";
|
||
break;
|
||
|
||
default:
|
||
op = tree_code_name[TREE_CODE (t)];
|
||
break;
|
||
}
|
||
|
||
pp_cxx_identifier (pp, op);
|
||
}
|
||
|
||
|
||
/* assignment-expression:
|
||
conditional-expression
|
||
logical-or-expression assignment-operator assignment-expression
|
||
throw-expression
|
||
|
||
throw-expression:
|
||
throw assignment-expression(opt)
|
||
|
||
assignment-operator: one of
|
||
= *= /= %= += -= >>= <<= &= ^= |= */
|
||
static void
|
||
pp_cxx_assignment_expression (cxx_pretty_printer *pp, tree e)
|
||
{
|
||
switch (TREE_CODE (e))
|
||
{
|
||
case MODIFY_EXPR:
|
||
case INIT_EXPR:
|
||
pp_c_logical_or_expression (pp_c_base (pp), TREE_OPERAND (e, 0));
|
||
pp_space (pp);
|
||
pp_equal (pp);
|
||
pp_space (pp);
|
||
pp_cxx_assignment_expression (pp, TREE_OPERAND (e, 1));
|
||
break;
|
||
|
||
case THROW_EXPR:
|
||
pp_cxx_identifier (pp, "throw");
|
||
if (TREE_OPERAND (e, 0))
|
||
pp_cxx_assignment_expression (pp, TREE_OPERAND (e, 0));
|
||
break;
|
||
|
||
case MODOP_EXPR:
|
||
pp_c_logical_or_expression (pp_c_base (pp), TREE_OPERAND (e, 0));
|
||
pp_cxx_assignment_operator (pp, TREE_OPERAND (e, 1));
|
||
pp_cxx_assignment_expression (pp, TREE_OPERAND (e, 2));
|
||
break;
|
||
|
||
default:
|
||
pp_cxx_conditional_expression (pp, e);
|
||
break;
|
||
}
|
||
}
|
||
|
||
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:
|
||
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:
|
||
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 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;
|
||
|
||
default:
|
||
pp_c_expression (pp_c_base (pp), t);
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
/* Declarations. */
|
||
|
||
/* function-specifier:
|
||
inline
|
||
virtual
|
||
explicit */
|
||
static void
|
||
pp_cxx_function_specifier (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
switch (TREE_CODE (t))
|
||
{
|
||
case FUNCTION_DECL:
|
||
if (DECL_VIRTUAL_P (t))
|
||
pp_cxx_identifier (pp, "virtual");
|
||
else if (DECL_CONSTRUCTOR_P (t) && DECL_NONCONVERTING_P (t))
|
||
pp_cxx_identifier (pp, "explicit");
|
||
else
|
||
pp_c_function_specifier (pp_c_base (pp), t);
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* decl-specifier-seq:
|
||
decl-specifier-seq(opt) decl-specifier
|
||
|
||
decl-specifier:
|
||
storage-class-specifier
|
||
type-specifier
|
||
function-specifier
|
||
friend
|
||
typedef */
|
||
static void
|
||
pp_cxx_decl_specifier_seq (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
switch (TREE_CODE (t))
|
||
{
|
||
case VAR_DECL:
|
||
case PARM_DECL:
|
||
case CONST_DECL:
|
||
case FIELD_DECL:
|
||
pp_cxx_storage_class_specifier (pp, t);
|
||
pp_cxx_decl_specifier_seq (pp, TREE_TYPE (t));
|
||
break;
|
||
|
||
case TYPE_DECL:
|
||
pp_cxx_identifier (pp, "typedef");
|
||
pp_cxx_decl_specifier_seq (pp, TREE_TYPE (t));
|
||
break;
|
||
|
||
case RECORD_TYPE:
|
||
if (TYPE_PTRMEMFUNC_P (t))
|
||
{
|
||
tree pfm = TYPE_PTRMEMFUNC_FN_TYPE (t);
|
||
pp_cxx_decl_specifier_seq (pp, TREE_TYPE (TREE_TYPE (pfm)));
|
||
pp_cxx_whitespace (pp);
|
||
pp_cxx_ptr_operator (pp, t);
|
||
}
|
||
break;
|
||
|
||
case FUNCTION_DECL:
|
||
/* Constructors don't have return types. And conversion functions
|
||
do not have a type-specifier in their return types. */
|
||
if (DECL_CONSTRUCTOR_P (t) || DECL_CONV_FN_P (t))
|
||
pp_cxx_function_specifier (pp, t);
|
||
else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
|
||
pp_cxx_decl_specifier_seq (pp, TREE_TYPE (TREE_TYPE (t)));
|
||
else
|
||
default:
|
||
pp_c_declaration_specifiers (pp_c_base (pp), t);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* simple-type-specifier:
|
||
::(opt) nested-name-specifier(opt) type-name
|
||
::(opt) nested-name-specifier(opt) template(opt) template-id
|
||
char
|
||
wchar_t
|
||
bool
|
||
short
|
||
int
|
||
long
|
||
signed
|
||
unsigned
|
||
float
|
||
double
|
||
void */
|
||
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_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;
|
||
}
|
||
}
|
||
|
||
/* type-specifier-seq:
|
||
type-specifier type-specifier-seq(opt)
|
||
|
||
type-specifier:
|
||
simple-type-specifier
|
||
class-specifier
|
||
enum-specifier
|
||
elaborated-type-specifier
|
||
cv-qualifier */
|
||
|
||
static void
|
||
pp_cxx_type_specifier_seq (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
switch (TREE_CODE (t))
|
||
{
|
||
case TEMPLATE_DECL:
|
||
case TEMPLATE_TYPE_PARM:
|
||
case TYPE_DECL:
|
||
case BOUND_TEMPLATE_TEMPLATE_PARM:
|
||
pp_c_type_qualifier_list (pp_c_base (pp), t);
|
||
pp_cxx_simple_type_specifier (pp, t);
|
||
break;
|
||
|
||
case METHOD_TYPE:
|
||
pp_cxx_type_specifier_seq (pp, TREE_TYPE (t));
|
||
pp_cxx_space_for_pointer_operator (pp, TREE_TYPE (t));
|
||
pp_cxx_nested_name_specifier (pp, TYPE_METHOD_BASETYPE (t));
|
||
break;
|
||
|
||
default:
|
||
if (!(TREE_CODE (t) == FUNCTION_DECL && DECL_CONSTRUCTOR_P (t)))
|
||
pp_c_specifier_qualifier_list (pp_c_base (pp), t);
|
||
}
|
||
}
|
||
|
||
/* ptr-operator:
|
||
* cv-qualifier-seq(opt)
|
||
&
|
||
::(opt) nested-name-specifier * cv-qualifier-seq(opt) */
|
||
|
||
static void
|
||
pp_cxx_ptr_operator (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
if (!TYPE_P (t) && TREE_CODE (t) != TYPE_DECL)
|
||
t = TREE_TYPE (t);
|
||
switch (TREE_CODE (t))
|
||
{
|
||
case REFERENCE_TYPE:
|
||
case POINTER_TYPE:
|
||
if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE
|
||
|| TYPE_PTR_TO_MEMBER_P (TREE_TYPE (t)))
|
||
pp_cxx_ptr_operator (pp, TREE_TYPE (t));
|
||
if (TREE_CODE (t) == POINTER_TYPE)
|
||
{
|
||
pp_star (pp);
|
||
pp_cxx_cv_qualifier_seq (pp, t);
|
||
}
|
||
else
|
||
pp_ampersand (pp);
|
||
break;
|
||
|
||
case RECORD_TYPE:
|
||
if (TYPE_PTRMEMFUNC_P (t))
|
||
{
|
||
pp_cxx_left_paren (pp);
|
||
pp_cxx_nested_name_specifier (pp, TYPE_PTRMEMFUNC_OBJECT_TYPE (t));
|
||
pp_star (pp);
|
||
break;
|
||
}
|
||
case OFFSET_TYPE:
|
||
if (TYPE_PTR_TO_MEMBER_P (t))
|
||
{
|
||
pp_cxx_nested_name_specifier (pp, TYPE_PTRMEM_CLASS_TYPE (t));
|
||
pp_star (pp);
|
||
pp_cxx_cv_qualifier_seq (pp, t);
|
||
break;
|
||
}
|
||
/* else fall through. */
|
||
|
||
default:
|
||
pp_unsupported_tree (pp, t);
|
||
break;
|
||
}
|
||
}
|
||
|
||
static inline tree
|
||
pp_cxx_implicit_parameter_type (tree mf)
|
||
{
|
||
return TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (mf))));
|
||
}
|
||
|
||
/*
|
||
parameter-declaration:
|
||
decl-specifier-seq declarator
|
||
decl-specifier-seq declarator = assignment-expression
|
||
decl-specifier-seq abstract-declarator(opt)
|
||
decl-specifier-seq abstract-declarator(opt) assignment-expression */
|
||
static inline void
|
||
pp_cxx_parameter_declaration (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
pp_cxx_decl_specifier_seq (pp, t);
|
||
if (TYPE_P (t))
|
||
pp_cxx_abstract_declarator (pp, t);
|
||
else
|
||
pp_cxx_declarator (pp, t);
|
||
}
|
||
|
||
/* parameter-declaration-clause:
|
||
parameter-declaration-list(opt) ...(opt)
|
||
parameter-declaration-list , ...
|
||
|
||
parameter-declaration-list:
|
||
parameter-declaration
|
||
parameter-declaration-list , parameter-declaration */
|
||
static void
|
||
pp_cxx_parameter_declaration_clause (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
tree args = TYPE_P (t) ? NULL : FUNCTION_FIRST_USER_PARM (t);
|
||
tree types = TYPE_P (t) ? TYPE_ARG_TYPES (t) : FUNCTION_FIRST_USER_PARMTYPE (t);
|
||
const bool abstract = args == NULL
|
||
|| pp_c_base (pp)->flags & pp_c_flag_abstract;
|
||
bool first = true;
|
||
|
||
/* Skip artificial parameter for nonstatic member functions. */
|
||
if (TREE_CODE (t) == METHOD_TYPE)
|
||
types = TREE_CHAIN (types);
|
||
|
||
pp_cxx_left_paren (pp);
|
||
for (; args; args = TREE_CHAIN (args), types = TREE_CHAIN (types))
|
||
{
|
||
if (!first)
|
||
pp_separate_with (pp, ',');
|
||
first = false;
|
||
pp_cxx_parameter_declaration (pp, abstract ? TREE_VALUE (types) : args);
|
||
if (!abstract && pp_c_base (pp)->flags & pp_cxx_flag_default_argument)
|
||
{
|
||
pp_cxx_whitespace (pp);
|
||
pp_equal (pp);
|
||
pp_cxx_whitespace (pp);
|
||
pp_cxx_assignment_expression (pp, TREE_PURPOSE (types));
|
||
}
|
||
}
|
||
pp_cxx_right_paren (pp);
|
||
}
|
||
|
||
/* exception-specification:
|
||
throw ( type-id-list(opt) )
|
||
|
||
type-id-list
|
||
type-id
|
||
type-id-list , type-id */
|
||
static void
|
||
pp_cxx_exception_specification (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
tree ex_spec = TYPE_RAISES_EXCEPTIONS (t);
|
||
|
||
if (!TYPE_NOTHROW_P (t) && ex_spec == NULL)
|
||
return;
|
||
pp_cxx_identifier (pp, "throw");
|
||
pp_cxx_left_paren (pp);
|
||
for (; ex_spec && TREE_VALUE (ex_spec); ex_spec = TREE_CHAIN (ex_spec))
|
||
{
|
||
pp_cxx_type_id (pp, TREE_VALUE (ex_spec));
|
||
if (TREE_CHAIN (ex_spec))
|
||
pp_separate_with (pp, ',');
|
||
}
|
||
pp_cxx_right_paren (pp);
|
||
}
|
||
|
||
/* direct-declarator:
|
||
declarator-id
|
||
direct-declarator ( parameter-declaration-clause ) cv-qualifier-seq(opt)
|
||
exception-specification(opt)
|
||
direct-declaration [ constant-expression(opt) ]
|
||
( declarator ) */
|
||
static void
|
||
pp_cxx_direct_declarator (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
switch (TREE_CODE (t))
|
||
{
|
||
case VAR_DECL:
|
||
case PARM_DECL:
|
||
case CONST_DECL:
|
||
case FIELD_DECL:
|
||
if (DECL_NAME (t))
|
||
{
|
||
pp_cxx_space_for_pointer_operator (pp, TREE_TYPE (t));
|
||
pp_cxx_id_expression (pp, DECL_NAME (t));
|
||
}
|
||
pp_cxx_abstract_declarator (pp, TREE_TYPE (t));
|
||
break;
|
||
|
||
case FUNCTION_DECL:
|
||
pp_cxx_space_for_pointer_operator (pp, TREE_TYPE (TREE_TYPE (t)));
|
||
pp_cxx_id_expression (pp, t);
|
||
pp_cxx_parameter_declaration_clause (pp, t);
|
||
|
||
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
|
||
{
|
||
pp_base (pp)->padding = pp_before;
|
||
pp_cxx_cv_qualifier_seq (pp, pp_cxx_implicit_parameter_type (t));
|
||
}
|
||
|
||
pp_cxx_exception_specification (pp, TREE_TYPE (t));
|
||
break;
|
||
|
||
case TYPENAME_TYPE:
|
||
case TEMPLATE_DECL:
|
||
case TEMPLATE_TYPE_PARM:
|
||
case TEMPLATE_PARM_INDEX:
|
||
break;
|
||
|
||
default:
|
||
pp_c_direct_declarator (pp_c_base (pp), t);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* declarator:
|
||
direct-declarator
|
||
ptr-operator declarator */
|
||
static void
|
||
pp_cxx_declarator (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
pp_cxx_direct_declarator (pp, t);
|
||
}
|
||
|
||
/* ctor-initializer:
|
||
: mem-initializer-list
|
||
|
||
mem-initializer-list:
|
||
mem-initializer
|
||
mem-initializer , mem-initializer-list
|
||
|
||
mem-initializer:
|
||
mem-initializer-id ( expression-list(opt) )
|
||
|
||
mem-initializer-id:
|
||
::(opt) nested-name-specifier(opt) class-name
|
||
identifier */
|
||
static void
|
||
pp_cxx_ctor_initializer (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
t = TREE_OPERAND (t, 0);
|
||
pp_cxx_whitespace (pp);
|
||
pp_colon (pp);
|
||
pp_cxx_whitespace (pp);
|
||
for (; t; t = TREE_CHAIN (t))
|
||
{
|
||
pp_cxx_primary_expression (pp, TREE_PURPOSE (t));
|
||
pp_cxx_call_argument_list (pp, TREE_VALUE (t));
|
||
if (TREE_CHAIN (t))
|
||
pp_separate_with (pp, ',');
|
||
}
|
||
}
|
||
|
||
/* function-definition:
|
||
decl-specifier-seq(opt) declarator ctor-initializer(opt) function-body
|
||
decl-specifier-seq(opt) declarator function-try-block */
|
||
|
||
void
|
||
pp_cxx_function_definition (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
tree saved_scope = pp->enclosing_scope;
|
||
pp_cxx_decl_specifier_seq (pp, t);
|
||
pp_cxx_declarator (pp, t);
|
||
pp_needs_newline (pp) = true;
|
||
pp->enclosing_scope = DECL_CONTEXT (t);
|
||
if (DECL_SAVED_TREE (t))
|
||
{
|
||
tree body = DECL_SAVED_TREE (t);
|
||
if (TREE_CODE (body) == COMPOUND_STMT
|
||
&& TREE_CODE (COMPOUND_BODY (body)) == CTOR_INITIALIZER)
|
||
{
|
||
body = COMPOUND_BODY (body);
|
||
pp_cxx_ctor_initializer (pp, body);
|
||
body = TREE_CHAIN (body);
|
||
}
|
||
pp_cxx_statement (pp, body);
|
||
}
|
||
else
|
||
{
|
||
pp_cxx_semicolon (pp);
|
||
pp_needs_newline (pp) = true;
|
||
}
|
||
pp_flush (pp);
|
||
pp->enclosing_scope = saved_scope;
|
||
}
|
||
|
||
/* abstract-declarator:
|
||
ptr-operator abstract-declarator(opt)
|
||
direct-abstract-declarator */
|
||
static void
|
||
pp_cxx_abstract_declarator (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
if (TYPE_PTRMEM_P (t) || TYPE_PTRMEMFUNC_P (t))
|
||
pp_cxx_right_paren (pp);
|
||
else if (POINTER_TYPE_P (t))
|
||
{
|
||
if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE
|
||
|| TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
|
||
pp_cxx_right_paren (pp);
|
||
t = TREE_TYPE (t);
|
||
}
|
||
pp_cxx_direct_abstract_declarator (pp, t);
|
||
}
|
||
|
||
/* direct-abstract-declarator:
|
||
direct-abstract-declarator(opt) ( parameter-declaration-clause )
|
||
cv-qualifier-seq(opt) exception-specification(opt)
|
||
direct-abstract-declarator(opt) [ constant-expression(opt) ]
|
||
( abstract-declarator ) */
|
||
static void
|
||
pp_cxx_direct_abstract_declarator (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
switch (TREE_CODE (t))
|
||
{
|
||
case REFERENCE_TYPE:
|
||
pp_cxx_abstract_declarator (pp, t);
|
||
break;
|
||
|
||
case RECORD_TYPE:
|
||
if (TYPE_PTRMEMFUNC_P (t))
|
||
pp_cxx_direct_abstract_declarator (pp, TYPE_PTRMEMFUNC_FN_TYPE (t));
|
||
break;
|
||
|
||
case METHOD_TYPE:
|
||
case FUNCTION_TYPE:
|
||
pp_cxx_parameter_declaration_clause (pp, t);
|
||
pp_cxx_direct_abstract_declarator (pp, TREE_TYPE (t));
|
||
if (TREE_CODE (t) == METHOD_TYPE)
|
||
{
|
||
pp_base (pp)->padding = pp_before;
|
||
pp_cxx_cv_qualifier_seq
|
||
(pp, TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))));
|
||
}
|
||
pp_cxx_exception_specification (pp, t);
|
||
break;
|
||
|
||
case TYPENAME_TYPE:
|
||
case TEMPLATE_TYPE_PARM:
|
||
case TEMPLATE_TEMPLATE_PARM:
|
||
case BOUND_TEMPLATE_TEMPLATE_PARM:
|
||
case UNBOUND_CLASS_TEMPLATE:
|
||
break;
|
||
|
||
default:
|
||
pp_c_direct_abstract_declarator (pp_c_base (pp), t);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* type-id:
|
||
type-specifier-seq abstract-declarator(opt) */
|
||
static void
|
||
pp_cxx_type_id (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
pp_flags saved_flags = pp_c_base (pp)->flags;
|
||
pp_c_base (pp)->flags |= pp_c_flag_abstract;
|
||
|
||
switch (TREE_CODE (t))
|
||
{
|
||
case TYPE_DECL:
|
||
case UNION_TYPE:
|
||
case RECORD_TYPE:
|
||
case ENUMERAL_TYPE:
|
||
case TYPENAME_TYPE:
|
||
case BOUND_TEMPLATE_TEMPLATE_PARM:
|
||
case UNBOUND_CLASS_TEMPLATE:
|
||
case TEMPLATE_TEMPLATE_PARM:
|
||
case TEMPLATE_TYPE_PARM:
|
||
case TEMPLATE_PARM_INDEX:
|
||
case TEMPLATE_DECL:
|
||
case TYPEOF_TYPE:
|
||
case TEMPLATE_ID_EXPR:
|
||
/* FIXME: Should be pp_cxx_type_specifier_seq. */
|
||
pp_cxx_type_specifier_seq (pp, t);
|
||
pp_cxx_declarator (pp, t);
|
||
break;
|
||
|
||
default:
|
||
pp_c_type_id (pp_c_base (pp), t);
|
||
break;
|
||
}
|
||
|
||
pp_c_base (pp)->flags = saved_flags;
|
||
}
|
||
|
||
/* template-argument-list:
|
||
template-argument
|
||
template-argument-list, template-argument
|
||
|
||
template-argument:
|
||
assignment-expression
|
||
type-id
|
||
template-name */
|
||
static void
|
||
pp_cxx_template_argument_list (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
int i;
|
||
if (t == NULL)
|
||
return;
|
||
for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
|
||
{
|
||
tree arg = TREE_VEC_ELT (t, i);
|
||
if (i != 0)
|
||
pp_separate_with (pp, ',');
|
||
if (TYPE_P (arg) || (TREE_CODE (arg) == TEMPLATE_DECL
|
||
&& TYPE_P (DECL_TEMPLATE_RESULT (arg))))
|
||
pp_cxx_type_id (pp, arg);
|
||
else
|
||
pp_cxx_expression (pp, arg);
|
||
}
|
||
}
|
||
|
||
|
||
static void
|
||
pp_cxx_exception_declaration (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
t = DECL_STMT_DECL (t);
|
||
pp_cxx_type_specifier_seq (pp, t);
|
||
if (TYPE_P (t))
|
||
pp_cxx_abstract_declarator (pp, t);
|
||
else
|
||
pp_cxx_declarator (pp, t);
|
||
}
|
||
|
||
/* Statements. */
|
||
|
||
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;
|
||
}
|
||
}
|
||
|
||
/* original-namespace-definition:
|
||
namespace identifier { namespace-body }
|
||
|
||
As an edge case, we also handle unnamed namespace definition here. */
|
||
|
||
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);
|
||
}
|
||
|
||
/* namespace-alias:
|
||
identifier
|
||
|
||
namespace-alias-definition:
|
||
namespace identifier = qualified-namespace-specifier ;
|
||
|
||
qualified-namespace-specifier:
|
||
::(opt) nested-name-specifier(opt) namespace-name */
|
||
|
||
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);
|
||
}
|
||
|
||
/* simple-declaration:
|
||
decl-specifier-seq(opt) init-declarator-list(opt) */
|
||
static void
|
||
pp_cxx_simple_declaration (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
pp_cxx_decl_specifier_seq (pp, t);
|
||
pp_cxx_init_declarator (pp, t);
|
||
pp_cxx_semicolon (pp);
|
||
pp_needs_newline (pp) = true;
|
||
}
|
||
|
||
/*
|
||
template-parameter-list:
|
||
template-parameter
|
||
template-parameter-list , template-parameter */
|
||
|
||
static inline void
|
||
pp_cxx_template_parameter_list (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
const int n = TREE_VEC_LENGTH (t);
|
||
int i;
|
||
for (i = 0; i < n; ++i)
|
||
{
|
||
if (i)
|
||
pp_separate_with (pp, ',');
|
||
pp_cxx_template_parameter (pp, TREE_VEC_ELT (t, i));
|
||
}
|
||
}
|
||
|
||
/* template-parameter:
|
||
type-parameter
|
||
parameter-declaration
|
||
|
||
type-parameter:
|
||
class identifier(opt)
|
||
class identifier(op) = type-id
|
||
typename identifier(opt)
|
||
typename identifier(opt) = type-id
|
||
template < template-parameter-list > class identifier(opt)
|
||
template < template-parameter-list > class identifier(opt) = template-name
|
||
*/
|
||
static void
|
||
pp_cxx_template_parameter (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
tree parameter = TREE_VALUE (t);
|
||
switch (TREE_CODE (parameter))
|
||
{
|
||
case TYPE_DECL:
|
||
pp_cxx_identifier (pp, "class");
|
||
if (DECL_NAME (parameter))
|
||
pp_cxx_tree_identifier (pp, DECL_NAME (parameter));
|
||
/* FIXME: Chech if we should print also default argument. */
|
||
break;
|
||
|
||
case PARM_DECL:
|
||
pp_cxx_parameter_declaration (pp, parameter);
|
||
break;
|
||
|
||
case TEMPLATE_DECL:
|
||
break;
|
||
|
||
default:
|
||
pp_unsupported_tree (pp, t);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* Pretty-print a template parameter in the canonical form
|
||
"template-parameter-<level>-<position in parameter list>". */
|
||
|
||
void
|
||
pp_cxx_canonical_template_parameter (cxx_pretty_printer *pp, tree parm)
|
||
{
|
||
const enum tree_code code = TREE_CODE (parm);
|
||
|
||
/* Brings type template parameters to the canonical forms. */
|
||
if (code == TEMPLATE_TYPE_PARM || code == TEMPLATE_TEMPLATE_PARM
|
||
|| code == BOUND_TEMPLATE_TEMPLATE_PARM)
|
||
parm = TEMPLATE_TYPE_PARM_INDEX (parm);
|
||
|
||
pp_cxx_begin_template_argument_list (pp);
|
||
pp_cxx_identifier (pp, "template-parameter-");
|
||
pp_wide_integer (pp, TEMPLATE_PARM_LEVEL (parm));
|
||
pp_minus (pp);
|
||
pp_wide_integer (pp, TEMPLATE_PARM_IDX (parm) + 1);
|
||
pp_cxx_end_template_argument_list (pp);
|
||
}
|
||
|
||
/*
|
||
template-declaration:
|
||
export(opt) template < template-parameter-list > declaration */
|
||
static void
|
||
pp_cxx_template_declaration (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
tree tmpl = most_general_template (t);
|
||
tree level;
|
||
int i = 0;
|
||
|
||
pp_maybe_newline_and_indent (pp, 0);
|
||
for (level = DECL_TEMPLATE_PARMS (tmpl); level; level = TREE_CHAIN (level))
|
||
{
|
||
pp_cxx_identifier (pp, "template");
|
||
pp_cxx_begin_template_argument_list (pp);
|
||
pp_cxx_template_parameter_list (pp, TREE_VALUE (level));
|
||
pp_cxx_end_template_argument_list (pp);
|
||
pp_newline_and_indent (pp, 3);
|
||
i += 3;
|
||
}
|
||
if (TREE_CODE (t) == FUNCTION_DECL && DECL_SAVED_TREE (t))
|
||
pp_cxx_function_definition (pp, t);
|
||
else
|
||
pp_cxx_simple_declaration (pp, t);
|
||
}
|
||
|
||
static void
|
||
pp_cxx_explicit_specialization (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
pp_unsupported_tree (pp, t);
|
||
}
|
||
|
||
static void
|
||
pp_cxx_explicit_instantiation (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
pp_unsupported_tree (pp, t);
|
||
}
|
||
|
||
/*
|
||
declaration:
|
||
block-declaration
|
||
function-definition
|
||
template-declaration
|
||
explicit-instantiation
|
||
explicit-specialization
|
||
linkage-specification
|
||
namespace-definition
|
||
|
||
block-declaration:
|
||
simple-declaration
|
||
asm-definition
|
||
namespace-alias-definition
|
||
using-declaration
|
||
using-directive */
|
||
void
|
||
pp_cxx_declaration (cxx_pretty_printer *pp, tree t)
|
||
{
|
||
if (!DECL_LANG_SPECIFIC (t))
|
||
pp_cxx_simple_declaration (pp, t);
|
||
else if (DECL_USE_TEMPLATE (t))
|
||
switch (DECL_USE_TEMPLATE (t))
|
||
{
|
||
case 1:
|
||
pp_cxx_template_declaration (pp, t);
|
||
break;
|
||
|
||
case 2:
|
||
pp_cxx_explicit_specialization (pp, t);
|
||
break;
|
||
|
||
case 3:
|
||
pp_cxx_explicit_instantiation (pp, t);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
else switch (TREE_CODE (t))
|
||
{
|
||
case VAR_DECL:
|
||
case TYPE_DECL:
|
||
pp_cxx_simple_declaration (pp, t);
|
||
break;
|
||
|
||
case FUNCTION_DECL:
|
||
if (DECL_SAVED_TREE (t))
|
||
pp_cxx_function_definition (pp, t);
|
||
else
|
||
pp_cxx_simple_declaration (pp, t);
|
||
break;
|
||
|
||
case NAMESPACE_DECL:
|
||
if (DECL_NAMESPACE_ALIAS (t))
|
||
pp_cxx_namespace_alias_definition (pp, t);
|
||
else
|
||
pp_cxx_original_namespace_definition (pp, t);
|
||
break;
|
||
|
||
default:
|
||
pp_unsupported_tree (pp, t);
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
typedef c_pretty_print_fn pp_fun;
|
||
|
||
void
|
||
pp_cxx_pretty_printer_init (cxx_pretty_printer *pp)
|
||
{
|
||
pp_c_pretty_printer_init (pp_c_base (pp));
|
||
pp_set_line_maximum_length (pp, 0);
|
||
|
||
pp->c_base.declaration = (pp_fun) pp_cxx_declaration;
|
||
pp->c_base.declaration_specifiers = (pp_fun) pp_cxx_decl_specifier_seq;
|
||
pp->c_base.function_specifier = (pp_fun) pp_cxx_function_specifier;
|
||
pp->c_base.type_specifier_seq = (pp_fun) pp_cxx_type_specifier_seq;
|
||
pp->c_base.declarator = (pp_fun) pp_cxx_declarator;
|
||
pp->c_base.direct_declarator = (pp_fun) pp_cxx_direct_declarator;
|
||
pp->c_base.parameter_list = (pp_fun) pp_cxx_parameter_declaration_clause;
|
||
pp->c_base.type_id = (pp_fun) pp_cxx_type_id;
|
||
pp->c_base.abstract_declarator = (pp_fun) pp_cxx_abstract_declarator;
|
||
pp->c_base.direct_abstract_declarator =
|
||
(pp_fun) pp_cxx_direct_abstract_declarator;
|
||
pp->c_base.simple_type_specifier = (pp_fun)pp_cxx_simple_type_specifier;
|
||
|
||
/* pp->c_base.statement = (pp_fun) pp_cxx_statement; */
|
||
|
||
pp->c_base.id_expression = (pp_fun) pp_cxx_id_expression;
|
||
pp->c_base.primary_expression = (pp_fun) pp_cxx_primary_expression;
|
||
pp->c_base.postfix_expression = (pp_fun) pp_cxx_postfix_expression;
|
||
pp->c_base.unary_expression = (pp_fun) pp_cxx_unary_expression;
|
||
pp->c_base.multiplicative_expression = (pp_fun) pp_cxx_multiplicative_expression;
|
||
pp->c_base.conditional_expression = (pp_fun) pp_cxx_conditional_expression;
|
||
pp->c_base.assignment_expression = (pp_fun) pp_cxx_assignment_expression;
|
||
pp->c_base.expression = (pp_fun) pp_cxx_expression;
|
||
pp->enclosing_scope = global_namespace;
|
||
}
|