/* Implementation of subroutines for the GNU C++ pretty-printer.
- Copyright (C) 2003-2014 Free Software Foundation, Inc.
+ Copyright (C) 2003-2020 Free Software Foundation, Inc.
Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-#include "intl.h"
#include "cp-tree.h"
#include "cxx-pretty-print.h"
#include "tree-pretty-print.h"
static void pp_cxx_template_parameter (cxx_pretty_printer *, tree);
static void pp_cxx_cast_expression (cxx_pretty_printer *, tree);
static void pp_cxx_typeid_expression (cxx_pretty_printer *, tree);
+static void pp_cxx_unary_left_fold_expression (cxx_pretty_printer *, tree);
+static void pp_cxx_unary_right_fold_expression (cxx_pretty_printer *, tree);
+static void pp_cxx_binary_fold_expression (cxx_pretty_printer *, tree);
+static void pp_cxx_concept_definition (cxx_pretty_printer *, tree);
\f
static inline void
/* 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
break;
case OVERLOAD:
- t = OVL_CURRENT (t);
+ t = OVL_FIRST (t);
+ /* FALLTHRU */
case VAR_DECL:
case PARM_DECL:
case CONST_DECL:
case USING_DECL:
case TEMPLATE_DECL:
t = DECL_NAME (t);
+ /* FALLTHRU */
case IDENTIFIER_NODE:
if (t == NULL)
pp->translate_string ("<unnamed>");
- else if (IDENTIFIER_TYPENAME_P (t))
+ else if (IDENTIFIER_CONV_OP_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);
- }
+ pp_cxx_tree_identifier (pp, t);
break;
case TEMPLATE_ID_EXPR:
case TYPENAME_TYPE:
case UNBOUND_CLASS_TEMPLATE:
pp_cxx_unqualified_id (pp, TYPE_NAME (t));
- if (CLASS_TYPE_P (t) && CLASSTYPE_USE_TEMPLATE (t))
- {
- pp_cxx_begin_template_argument_list (pp);
- pp_cxx_template_argument_list (pp, INNERMOST_TEMPLATE_ARGS
- (CLASSTYPE_TI_ARGS (t)));
- pp_cxx_end_template_argument_list (pp);
- }
+ if (tree ti = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (t))
+ if (PRIMARY_TEMPLATE_P (TI_TEMPLATE (ti)))
+ {
+ pp_cxx_begin_template_argument_list (pp);
+ tree args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (ti));
+ pp_cxx_template_argument_list (pp, args);
+ pp_cxx_end_template_argument_list (pp);
+ }
break;
case BIT_NOT_EXPR:
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
- if (TYPE_IDENTIFIER (t))
+ if (template_placeholder_p (t))
+ {
+ t = TREE_TYPE (CLASS_PLACEHOLDER_TEMPLATE (t));
+ pp_cxx_unqualified_id (pp, TYPE_IDENTIFIER (t));
+ pp_string (pp, "<...auto...>");
+ }
+ else if (TYPE_IDENTIFIER (t))
pp_cxx_unqualified_id (pp, TYPE_IDENTIFIER (t));
else
pp_cxx_canonical_template_parameter (pp, t);
static void
pp_cxx_nested_name_specifier (cxx_pretty_printer *pp, tree t)
{
- if (!SCOPE_FILE_SCOPE_P (t) && t != pp->enclosing_scope)
+ /* FIXME: When diagnosing references to concepts (especially as types?)
+ we end up adding too many '::' to the name. This is partially due
+ to the fact that pp->enclosing_namespace is null. */
+ if (t == global_namespace)
+ {
+ pp_cxx_colon_colon (pp);
+ }
+ else if (!SCOPE_FILE_SCOPE_P (t) && t != pp->enclosing_scope)
{
tree scope = get_containing_scope (t);
pp_cxx_nested_name_specifier (pp, scope);
FIXME: This is probably the wrong pretty-printing for conversion
functions and some function templates. */
case OVERLOAD:
- t = OVL_CURRENT (t);
+ t = OVL_FIRST (t);
+ /* FALLTHRU */
case FUNCTION_DECL:
if (DECL_FUNCTION_MEMBER_P (t))
pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
}
}
+/* Given a value e of ENUMERAL_TYPE:
+ Print out the first ENUMERATOR id with value e, if one is found,
+ (including nested names but excluding the enum name if unscoped)
+ else print out the value as a C-style cast (type-id)value. */
+
+static void
+pp_cxx_enumeration_constant (cxx_pretty_printer *pp, tree e)
+{
+ tree type = TREE_TYPE (e);
+ tree value = NULL_TREE;
+
+ /* Find the name of this constant. */
+ if ((pp->flags & pp_c_flag_gnu_v3) == 0)
+ for (value = TYPE_VALUES (type); value != NULL_TREE;
+ value = TREE_CHAIN (value))
+ if (tree_int_cst_equal (DECL_INITIAL (TREE_VALUE (value)), e))
+ break;
+
+ if (value != NULL_TREE)
+ {
+ if (!ENUM_IS_SCOPED (type))
+ type = get_containing_scope (type);
+ pp_cxx_nested_name_specifier (pp, type);
+ pp->id_expression (TREE_PURPOSE (value));
+ }
+ else
+ {
+ /* Value must have been cast. */
+ pp_c_type_cast (pp, type);
+ pp_c_integer_constant (pp, e);
+ }
+}
+
void
cxx_pretty_printer::constant (tree t)
pp_string (this, "nullptr");
break;
}
- /* else fall through. */
+ else if (TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
+ {
+ pp_cxx_enumeration_constant (this, t);
+ break;
+ }
+ /* fall through. */
default:
c_pretty_printer::constant (t);
cxx_pretty_printer::id_expression (tree t)
{
if (TREE_CODE (t) == OVERLOAD)
- t = OVL_CURRENT (t);
+ t = OVL_FIRST (t);
if (DECL_P (t) && DECL_CONTEXT (t))
pp_cxx_qualified_id (this, t);
else
GNU Extensions:
__builtin_va_arg ( assignment-expression , type-id )
__builtin_offsetof ( type-id, offsetof-expression )
+ __builtin_addressof ( expression )
__has_nothrow_assign ( type-id )
__has_nothrow_constructor ( type-id )
__has_trivial_assign ( type-id )
__has_trivial_constructor ( type-id )
__has_trivial_copy ( type-id )
+ __has_unique_object_representations ( type-id )
__has_trivial_destructor ( type-id )
__has_virtual_destructor ( type-id )
__is_abstract ( type-id )
case BASELINK:
t = BASELINK_FUNCTIONS (t);
+ /* FALLTHRU */
case VAR_DECL:
case PARM_DECL:
case FIELD_DECL:
pp_cxx_offsetof_expression (this, t);
break;
+ case ADDRESSOF_EXPR:
+ pp_cxx_addressof_expression (this, t);
+ break;
+
+ case REQUIRES_EXPR:
+ pp_cxx_requires_expr (this, t);
+ break;
+
default:
c_pretty_printer::primary_expression (t);
break;
case AGGR_INIT_EXPR:
case CALL_EXPR:
{
- tree fun = (code == AGGR_INIT_EXPR ? AGGR_INIT_EXPR_FN (t)
- : CALL_EXPR_FN (t));
+ tree fun = cp_get_callee (t);
tree saved_scope = enclosing_scope;
bool skipfirst = false;
tree arg;
pp_cxx_qualified_id (pp, t);
break;
}
- /* Else fall through. */
+ /* Fall through. */
case MEMBER_REF:
case DOTSTAR_EXPR:
pp_cxx_pm_expression (pp, TREE_OPERAND (t, 0));
case MULT_EXPR:
case TRUNC_DIV_EXPR:
case TRUNC_MOD_EXPR:
+ case EXACT_DIV_EXPR:
+ case RDIV_EXPR:
multiplicative_expression (TREE_OPERAND (e, 0));
pp_space (this);
if (code == MULT_EXPR)
pp_star (this);
- else if (code == TRUNC_DIV_EXPR)
+ else if (code != TRUNC_MOD_EXPR)
pp_slash (this);
else
pp_modulo (this);
break;
case OVERLOAD:
- t = OVL_CURRENT (t);
+ t = OVL_FIRST (t);
+ /* FALLTHRU */
case VAR_DECL:
case PARM_DECL:
case FIELD_DECL:
case TEMPLATE_PARM_INDEX:
case TEMPLATE_TEMPLATE_PARM:
case STMT_EXPR:
+ case REQUIRES_EXPR:
primary_expression (t);
break;
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
case NOEXCEPT_EXPR:
+ case UNARY_PLUS_EXPR:
unary_expression (t);
break;
case MULT_EXPR:
case TRUNC_DIV_EXPR:
case TRUNC_MOD_EXPR:
+ case EXACT_DIV_EXPR:
+ case RDIV_EXPR:
multiplicative_expression (t);
break;
pp_cxx_ws_string (this, "...");
break;
+ case UNARY_LEFT_FOLD_EXPR:
+ pp_cxx_unary_left_fold_expression (this, t);
+ break;
+
+ case UNARY_RIGHT_FOLD_EXPR:
+ pp_cxx_unary_right_fold_expression (this, t);
+ break;
+
+ case BINARY_LEFT_FOLD_EXPR:
+ case BINARY_RIGHT_FOLD_EXPR:
+ pp_cxx_binary_fold_expression (this, t);
+ break;
+
case TEMPLATE_ID_EXPR:
pp_cxx_template_id (this, t);
break;
{
tree args = ARGUMENT_PACK_ARGS (t);
int i, len = TREE_VEC_LENGTH (args);
+ pp_cxx_left_brace (this);
for (i = 0; i < len; ++i)
{
if (i > 0)
pp_cxx_separate_with (this, ',');
expression (TREE_VEC_ELT (args, i));
}
+ pp_cxx_right_brace (this);
}
break;
-
+
case LAMBDA_EXPR:
pp_cxx_ws_string (this, "<lambda>");
break;
+ case TRAIT_EXPR:
+ pp_cxx_trait_expression (this, t);
+ break;
+
+ case ATOMIC_CONSTR:
+ case CHECK_CONSTR:
+ case CONJ_CONSTR:
+ case DISJ_CONSTR:
+ pp_cxx_constraint (this, t);
+ break;
+
case PAREN_EXPR:
pp_cxx_left_paren (this);
expression (TREE_OPERAND (t, 0));
else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
declaration_specifiers (TREE_TYPE (TREE_TYPE (t)));
else
- default:
+ c_pretty_printer::declaration_specifiers (t);
+ break;
+ default:
c_pretty_printer::declaration_specifiers (t);
break;
}
/* simple-type-specifier:
::(opt) nested-name-specifier(opt) type-name
::(opt) nested-name-specifier(opt) template(opt) template-id
+ decltype-specifier
char
wchar_t
bool
case TEMPLATE_PARM_INDEX:
case BOUND_TEMPLATE_TEMPLATE_PARM:
pp_cxx_unqualified_id (this, t);
+ if (tree c = PLACEHOLDER_TYPE_CONSTRAINTS (t))
+ pp_cxx_constrained_type_spec (this, c);
break;
case TYPENAME_TYPE:
pp_cxx_ws_string (this, "typename");
pp_cxx_nested_name_specifier (this, TYPE_CONTEXT (t));
- pp_cxx_unqualified_id (this, TYPE_NAME (t));
+ pp_cxx_unqualified_id (this, TYPENAME_TYPE_FULLNAME (t));
+ break;
+
+ case DECLTYPE_TYPE:
+ pp_cxx_ws_string (this, "decltype");
+ pp_cxx_left_paren (this);
+ this->expression (DECLTYPE_TYPE_EXPR (t));
+ pp_cxx_right_paren (this);
break;
default:
case TEMPLATE_TEMPLATE_PARM:
case TYPE_DECL:
case BOUND_TEMPLATE_TEMPLATE_PARM:
+ case DECLTYPE_TYPE:
pp_cxx_cv_qualifier_seq (pp, t);
pp->simple_type_specifier (t);
break;
pp_cxx_nested_name_specifier (pp, TYPE_METHOD_BASETYPE (t));
break;
- case DECLTYPE_TYPE:
- pp_cxx_ws_string (pp, "decltype");
- pp_cxx_left_paren (pp);
- pp->expression (DECLTYPE_TYPE_EXPR (t));
- pp_cxx_right_paren (pp);
- break;
-
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
{
pp_cxx_ptr_operator (pp, t);
break;
}
- /* else fall through */
+ /* fall through */
+
+ case OFFSET_TYPE:
+ if (TYPE_PTRDATAMEM_P (t))
+ {
+ pp_cxx_type_specifier_seq (pp, TREE_TYPE (t));
+ pp_cxx_whitespace (pp);
+ pp_cxx_ptr_operator (pp, t);
+ break;
+ }
+ /* fall through */
default:
if (!(TREE_CODE (t) == FUNCTION_DECL && DECL_CONSTRUCTOR_P (t)))
pp_star (pp);
break;
}
+ /* FALLTHRU */
case OFFSET_TYPE:
if (TYPE_PTRMEM_P (t))
{
pp_cxx_cv_qualifier_seq (pp, t);
break;
}
- /* else fall through. */
+ /* fall through. */
default:
pp_unsupported_tree (pp, t);
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->flags & pp_c_flag_abstract;
+ tree args;
+ tree types;
+ bool abstract;
+
+ // For a requires clause or the explicit printing of a parameter list
+ // we expect T to be a chain of PARM_DECLs. Otherwise, the list of
+ // args and types are taken from the function decl T.
+ if (TREE_CODE (t) == PARM_DECL)
+ {
+ args = t;
+ types = t;
+ abstract = false;
+ }
+ else
+ {
+ bool type_p = TYPE_P (t);
+ args = type_p ? NULL : FUNCTION_FIRST_USER_PARM (t);
+ types = type_p ? TYPE_ARG_TYPES (t) : FUNCTION_FIRST_USER_PARMTYPE (t);
+ abstract = args == NULL || pp->flags & pp_c_flag_abstract;
+ }
bool first = true;
- /* Skip artificial parameter for nonstatic member functions. */
+ /* Skip artificial parameter for non-static member functions. */
if (TREE_CODE (t) == METHOD_TYPE)
types = TREE_CHAIN (types);
cxx_pretty_printer::declarator (tree t)
{
direct_declarator (t);
+
+ // Print a requires clause.
+ if (flag_concepts)
+ if (tree ci = get_constraints (t))
+ if (tree reqs = CI_DECLARATOR_REQS (ci))
+ pp_cxx_requires_clause (this, reqs);
}
/* ctor-initializer:
void
cxx_pretty_printer::abstract_declarator (tree t)
{
- if (TYPE_PTRMEM_P (t))
+ /* pp_cxx_ptr_operator prints '(' for a pointer-to-member function,
+ or a pointer-to-data-member of array type:
+
+ void (X::*)()
+ int (X::*)[5]
+
+ but not for a pointer-to-data-member of non-array type:
+
+ int X::*
+
+ so be mindful of that. */
+ if (TYPE_PTRMEMFUNC_P (t)
+ || (TYPE_PTRDATAMEM_P (t)
+ && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE))
pp_cxx_right_paren (this);
- else if (POINTER_TYPE_P (t))
+ else if (INDIRECT_TYPE_P (t))
{
if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
direct_abstract_declarator (TYPE_PTRMEMFUNC_FN_TYPE (t));
break;
+ case OFFSET_TYPE:
+ if (TYPE_PTRDATAMEM_P (t))
+ direct_abstract_declarator (TREE_TYPE (t));
+ break;
+
case METHOD_TYPE:
case FUNCTION_TYPE:
pp_cxx_parameter_declaration_clause (this, t);
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
case UNBOUND_CLASS_TEMPLATE:
+ case DECLTYPE_TYPE:
break;
default:
case UNDERLYING_TYPE:
case DECLTYPE_TYPE:
case TEMPLATE_ID_EXPR:
+ case OFFSET_TYPE:
pp_cxx_type_specifier_seq (this, t);
+ if (TYPE_PTRMEM_P (t))
+ abstract_declarator (t);
break;
case TYPE_PACK_EXPANSION:
pp_cxx_ws_string (this, "...");
break;
+ case TYPE_ARGUMENT_PACK:
+ {
+ tree args = ARGUMENT_PACK_ARGS (t);
+ int len = TREE_VEC_LENGTH (args);
+ pp_cxx_left_brace (this);
+ for (int i = 0; i < len; ++i)
+ {
+ if (i > 0)
+ pp_cxx_separate_with (this, ',');
+ type_id (TREE_VEC_ELT (args, i));
+ }
+ pp_cxx_right_brace (this);
+ }
+ break;
+
default:
c_pretty_printer::type_id (t);
break;
{
if (argpack)
arg = TREE_VEC_ELT (argpack, idx);
-
+
if (need_comma)
pp_cxx_separate_with (pp, ',');
else
if (TYPE_P (arg) || (TREE_CODE (arg) == TEMPLATE_DECL
&& TYPE_P (DECL_TEMPLATE_RESULT (arg))))
pp->type_id (arg);
+ else if (template_parm_object_p (arg))
+ pp->expression (DECL_INITIAL (arg));
else
pp->expression (arg);
}
}
break;
- case SWITCH_STMT:
- pp_cxx_ws_string (this, "switch");
- pp_space (this);
- pp_cxx_left_paren (this);
- expression (SWITCH_STMT_COND (t));
- pp_cxx_right_paren (this);
- pp_indentation (this) += 3;
- pp_needs_newline (this) = true;
- statement (SWITCH_STMT_BODY (t));
- pp_newline_and_indent (this, -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_ws_string (this, "while");
- pp_space (this);
- pp_cxx_left_paren (this);
- expression (WHILE_COND (t));
- pp_cxx_right_paren (this);
- pp_newline_and_indent (this, 3);
- statement (WHILE_BODY (t));
- pp_indentation (this) -= 3;
- pp_needs_newline (this) = true;
- break;
-
- case DO_STMT:
- pp_cxx_ws_string (this, "do");
- pp_newline_and_indent (this, 3);
- statement (DO_BODY (t));
- pp_newline_and_indent (this, -3);
- pp_cxx_ws_string (this, "while");
- pp_space (this);
- pp_cxx_left_paren (this);
- expression (DO_COND (t));
- pp_cxx_right_paren (this);
- pp_cxx_semicolon (this);
- pp_needs_newline (this) = true;
- break;
-
- case FOR_STMT:
- pp_cxx_ws_string (this, "for");
- pp_space (this);
- pp_cxx_left_paren (this);
- if (FOR_INIT_STMT (t))
- statement (FOR_INIT_STMT (t));
- else
- pp_cxx_semicolon (this);
- pp_needs_newline (this) = false;
- pp_cxx_whitespace (this);
- if (FOR_COND (t))
- expression (FOR_COND (t));
- pp_cxx_semicolon (this);
- pp_needs_newline (this) = false;
- pp_cxx_whitespace (this);
- if (FOR_EXPR (t))
- expression (FOR_EXPR (t));
- pp_cxx_right_paren (this);
- pp_newline_and_indent (this, 3);
- statement (FOR_BODY (t));
- pp_indentation (this) -= 3;
- pp_needs_newline (this) = true;
- break;
-
case RANGE_FOR_STMT:
pp_cxx_ws_string (this, "for");
pp_space (this);
pp_cxx_left_paren (this);
+ if (RANGE_FOR_INIT_STMT (t))
+ {
+ statement (RANGE_FOR_INIT_STMT (t));
+ pp_needs_newline (this) = false;
+ pp_cxx_whitespace (this);
+ }
statement (RANGE_FOR_DECL (t));
pp_space (this);
pp_needs_newline (this) = false;
pp_needs_newline (this) = true;
break;
- /* jump-statement:
- goto identifier;
- continue ;
- return expression(opt) ; */
- case BREAK_STMT:
- case CONTINUE_STMT:
- pp_string (this, TREE_CODE (t) == BREAK_STMT ? "break" : "continue");
- pp_cxx_semicolon (this);
- pp_needs_newline (this) = true;
- break;
-
/* expression-statement:
expression(opt) ; */
case EXPR_STMT:
declaration (t);
break;
+ case OMP_DEPOBJ:
+ pp_cxx_ws_string (this, "#pragma omp depobj");
+ pp_space (this);
+ pp_cxx_left_paren (this);
+ expression (OMP_DEPOBJ_DEPOBJ (t));
+ pp_cxx_right_paren (this);
+ if (OMP_DEPOBJ_CLAUSES (t) && OMP_DEPOBJ_CLAUSES (t) != error_mark_node)
+ {
+ if (TREE_CODE (OMP_DEPOBJ_CLAUSES (t)) == OMP_CLAUSE)
+ dump_omp_clauses (this, OMP_DEPOBJ_CLAUSES (t),
+ pp_indentation (this), TDF_NONE);
+ else
+ switch (tree_to_uhwi (OMP_DEPOBJ_CLAUSES (t)))
+ {
+ case OMP_CLAUSE_DEPEND_IN:
+ pp_cxx_ws_string (this, " update(in)");
+ break;
+ case OMP_CLAUSE_DEPEND_INOUT:
+ pp_cxx_ws_string (this, " update(inout)");
+ break;
+ case OMP_CLAUSE_DEPEND_OUT:
+ pp_cxx_ws_string (this, " update(out)");
+ break;
+ case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
+ pp_cxx_ws_string (this, " update(mutexinoutset)");
+ break;
+ case OMP_CLAUSE_DEPEND_LAST:
+ pp_cxx_ws_string (this, " destroy");
+ break;
+ default:
+ break;
+ }
+ }
+ pp_needs_newline (this) = true;
+ break;
+
default:
c_pretty_printer::statement (t);
break;
pp_cxx_end_template_argument_list (pp);
}
+/* Print a constrained-type-specifier. */
+
+void
+pp_cxx_constrained_type_spec (cxx_pretty_printer *pp, tree c)
+{
+ pp_cxx_whitespace (pp);
+ pp_cxx_left_bracket (pp);
+ pp->translate_string ("requires");
+ pp_cxx_whitespace (pp);
+ if (c == error_mark_node)
+ {
+ pp_cxx_ws_string(pp, "<unsatisfied-type-constraint>");
+ return;
+ }
+ tree t, a;
+ placeholder_extract_concept_and_args (c, t, a);
+ pp->id_expression (t);
+ pp_cxx_begin_template_argument_list (pp);
+ pp_cxx_ws_string (pp, "<placeholder>");
+ pp_cxx_separate_with (pp, ',');
+ tree args = make_tree_vec (TREE_VEC_LENGTH (a) - 1);
+ for (int i = 0; i < TREE_VEC_LENGTH (a) - 1; ++i)
+ TREE_VEC_ELT (args, i) = TREE_VEC_ELT (a, i + 1);
+ pp_cxx_template_argument_list (pp, args);
+ ggc_free (args);
+ pp_cxx_end_template_argument_list (pp);
+ pp_cxx_right_bracket (pp);
+}
+
/*
template-declaration:
- export(opt) template < template-parameter-list > declaration */
+ export(opt) template < template-parameter-list > declaration
+
+ Concept extensions:
+
+ template-declaration:
+ export(opt) template < template-parameter-list >
+ requires-clause(opt) declaration */
static void
pp_cxx_template_declaration (cxx_pretty_printer *pp, tree t)
pp_cxx_end_template_argument_list (pp);
pp_newline_and_indent (pp, 3);
}
+
+ if (flag_concepts)
+ if (tree ci = get_constraints (t))
+ if (tree reqs = CI_TEMPLATE_REQS (ci))
+ {
+ pp_cxx_requires_clause (pp, reqs);
+ pp_newline_and_indent (pp, 6);
+ }
+
if (TREE_CODE (t) == FUNCTION_DECL && DECL_SAVED_TREE (t))
pp_cxx_function_definition (pp, t);
+ else if (TREE_CODE (t) == CONCEPT_DECL)
+ pp_cxx_concept_definition (pp, t);
else
pp_cxx_simple_declaration (pp, t);
}
pp_unsupported_tree (pp, t);
}
+static void
+pp_cxx_concept_definition (cxx_pretty_printer *pp, tree t)
+{
+ pp_cxx_unqualified_id (pp, DECL_NAME (t));
+ pp_cxx_whitespace (pp);
+ pp_cxx_ws_string (pp, "=");
+ pp_cxx_whitespace (pp);
+ pp->expression (DECL_INITIAL (t));
+ pp_cxx_semicolon (pp);
+}
+
/*
declaration:
block-declaration
{
case ARROW_EXPR:
if (TREE_CODE (TREE_OPERAND (t, 0)) == STATIC_CAST_EXPR
- && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0))))
+ && INDIRECT_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0))))
{
pp->type_id (TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0))));
pp_cxx_separate_with (pp, ',');
pp_cxx_right_paren (pp);
}
+void
+pp_cxx_addressof_expression (cxx_pretty_printer *pp, tree t)
+{
+ pp_cxx_ws_string (pp, "__builtin_addressof");
+ pp_cxx_left_paren (pp);
+ pp->expression (TREE_OPERAND (t, 0));
+ pp_cxx_right_paren (pp);
+}
+
+static char const*
+get_fold_operator (tree t)
+{
+ int op = int_cst_value (FOLD_EXPR_OP (t));
+ ovl_op_info_t *info = OVL_OP_INFO (FOLD_EXPR_MODIFY_P (t), op);
+ return info->name;
+}
+
+void
+pp_cxx_unary_left_fold_expression (cxx_pretty_printer *pp, tree t)
+{
+ char const* op = get_fold_operator (t);
+ tree expr = PACK_EXPANSION_PATTERN (FOLD_EXPR_PACK (t));
+ pp_cxx_left_paren (pp);
+ pp_cxx_ws_string (pp, "...");
+ pp_cxx_ws_string (pp, op);
+ pp->expression (expr);
+ pp_cxx_right_paren (pp);
+}
+
+void
+pp_cxx_unary_right_fold_expression (cxx_pretty_printer *pp, tree t)
+{
+ char const* op = get_fold_operator (t);
+ tree expr = PACK_EXPANSION_PATTERN (FOLD_EXPR_PACK (t));
+ pp_cxx_left_paren (pp);
+ pp->expression (expr);
+ pp_space (pp);
+ pp_cxx_ws_string (pp, op);
+ pp_cxx_ws_string (pp, "...");
+ pp_cxx_right_paren (pp);
+}
+
+void
+pp_cxx_binary_fold_expression (cxx_pretty_printer *pp, tree t)
+{
+ char const* op = get_fold_operator (t);
+ tree t1 = TREE_OPERAND (t, 1);
+ tree t2 = TREE_OPERAND (t, 2);
+ if (t1 == FOLD_EXPR_PACK (t))
+ t1 = PACK_EXPANSION_PATTERN (t1);
+ else
+ t2 = PACK_EXPANSION_PATTERN (t2);
+ pp_cxx_left_paren (pp);
+ pp->expression (t1);
+ pp_cxx_ws_string (pp, op);
+ pp_cxx_ws_string (pp, "...");
+ pp_cxx_ws_string (pp, op);
+ pp->expression (t2);
+ pp_cxx_right_paren (pp);
+}
+
void
pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t)
{
case CPTK_HAS_TRIVIAL_DESTRUCTOR:
pp_cxx_ws_string (pp, "__has_trivial_destructor");
break;
+ case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
+ pp_cxx_ws_string (pp, "__has_unique_object_representations");
+ break;
case CPTK_HAS_VIRTUAL_DESTRUCTOR:
pp_cxx_ws_string (pp, "__has_virtual_destructor");
break;
case CPTK_IS_ABSTRACT:
pp_cxx_ws_string (pp, "__is_abstract");
break;
+ case CPTK_IS_AGGREGATE:
+ pp_cxx_ws_string (pp, "__is_aggregate");
+ break;
case CPTK_IS_BASE_OF:
pp_cxx_ws_string (pp, "__is_base_of");
break;
case CPTK_IS_POLYMORPHIC:
pp_cxx_ws_string (pp, "__is_polymorphic");
break;
+ case CPTK_IS_SAME_AS:
+ pp_cxx_ws_string (pp, "__is_same");
+ break;
case CPTK_IS_STD_LAYOUT:
pp_cxx_ws_string (pp, "__is_std_layout");
break;
case CPTK_IS_LITERAL_TYPE:
pp_cxx_ws_string (pp, "__is_literal_type");
break;
+ case CPTK_IS_ASSIGNABLE:
+ pp_cxx_ws_string (pp, "__is_assignable");
+ break;
+ case CPTK_IS_CONSTRUCTIBLE:
+ pp_cxx_ws_string (pp, "__is_constructible");
+ break;
default:
gcc_unreachable ();
pp_cxx_left_paren (pp);
pp->type_id (TRAIT_EXPR_TYPE1 (t));
- if (kind == CPTK_IS_BASE_OF)
+ if (kind == CPTK_IS_BASE_OF || kind == CPTK_IS_SAME_AS)
{
pp_cxx_separate_with (pp, ',');
pp->type_id (TRAIT_EXPR_TYPE2 (t));
pp_cxx_right_paren (pp);
}
+
+// requires-clause:
+// 'requires' logical-or-expression
+void
+pp_cxx_requires_clause (cxx_pretty_printer *pp, tree t)
+{
+ if (!t)
+ return;
+ pp->padding = pp_before;
+ pp_cxx_ws_string (pp, "requires");
+ pp_space (pp);
+ pp->expression (t);
+}
+
+/* requirement:
+ simple-requirement
+ compound-requirement
+ type-requirement
+ nested-requirement */
+static void
+pp_cxx_requirement (cxx_pretty_printer *pp, tree t)
+{
+ switch (TREE_CODE (t))
+ {
+ case SIMPLE_REQ:
+ pp_cxx_simple_requirement (pp, t);
+ break;
+
+ case TYPE_REQ:
+ pp_cxx_type_requirement (pp, t);
+ break;
+
+ case COMPOUND_REQ:
+ pp_cxx_compound_requirement (pp, t);
+ break;
+
+ case NESTED_REQ:
+ pp_cxx_nested_requirement (pp, t);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+// requirement-list:
+// requirement
+// requirement-list ';' requirement[opt]
+//
+static void
+pp_cxx_requirement_list (cxx_pretty_printer *pp, tree t)
+{
+ for (; t; t = TREE_CHAIN (t))
+ pp_cxx_requirement (pp, TREE_VALUE (t));
+}
+
+// requirement-body:
+// '{' requirement-list '}'
+static void
+pp_cxx_requirement_body (cxx_pretty_printer *pp, tree t)
+{
+ pp_cxx_left_brace (pp);
+ pp_cxx_requirement_list (pp, t);
+ pp_cxx_right_brace (pp);
+}
+
+// requires-expression:
+// 'requires' requirement-parameter-list requirement-body
+void
+pp_cxx_requires_expr (cxx_pretty_printer *pp, tree t)
+{
+ pp_string (pp, "requires");
+ if (tree parms = TREE_OPERAND (t, 0))
+ {
+ pp_cxx_parameter_declaration_clause (pp, parms);
+ pp_cxx_whitespace (pp);
+ }
+ pp_cxx_requirement_body (pp, TREE_OPERAND (t, 1));
+}
+
+/* simple-requirement:
+ expression ';' */
+void
+pp_cxx_simple_requirement (cxx_pretty_printer *pp, tree t)
+{
+ pp->expression (TREE_OPERAND (t, 0));
+ pp_cxx_semicolon (pp);
+}
+
+/* type-requirement:
+ typename type-name ';' */
+void
+pp_cxx_type_requirement (cxx_pretty_printer *pp, tree t)
+{
+ pp->type_id (TREE_OPERAND (t, 0));
+ pp_cxx_semicolon (pp);
+}
+
+/* compound-requirement:
+ '{' expression '}' 'noexcept' [opt] trailing-return-type [opt] */
+void
+pp_cxx_compound_requirement (cxx_pretty_printer *pp, tree t)
+{
+ pp_cxx_left_brace (pp);
+ pp->expression (TREE_OPERAND (t, 0));
+ pp_cxx_right_brace (pp);
+
+ if (COMPOUND_REQ_NOEXCEPT_P (t))
+ pp_cxx_ws_string (pp, "noexcept");
+
+ if (tree type = TREE_OPERAND (t, 1))
+ {
+ pp_cxx_whitespace (pp);
+ pp_cxx_ws_string (pp, "->");
+ pp->type_id (type);
+ }
+ pp_cxx_semicolon (pp);
+}
+
+/* nested requirement:
+ 'requires' constraint-expression */
+void
+pp_cxx_nested_requirement (cxx_pretty_printer *pp, tree t)
+{
+ pp_cxx_ws_string (pp, "requires");
+ pp->expression (TREE_OPERAND (t, 0));
+ pp_cxx_semicolon (pp);
+}
+
+void
+pp_cxx_check_constraint (cxx_pretty_printer *pp, tree t)
+{
+ tree decl = CHECK_CONSTR_CONCEPT (t);
+ tree tmpl = DECL_TI_TEMPLATE (decl);
+ tree args = CHECK_CONSTR_ARGS (t);
+ tree id = build_nt (TEMPLATE_ID_EXPR, tmpl, args);
+
+ if (TREE_CODE (decl) == CONCEPT_DECL)
+ pp->expression (id);
+ else if (VAR_P (decl))
+ pp->expression (id);
+ else if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ tree call = build_vl_exp (CALL_EXPR, 2);
+ TREE_OPERAND (call, 0) = integer_two_node;
+ TREE_OPERAND (call, 1) = id;
+ pp->expression (call);
+ }
+ else
+ gcc_unreachable ();
+}
+
+/* Output the "[with ...]" clause for a parameter mapping of an atomic
+ constraint. */
+
+void
+pp_cxx_parameter_mapping (cxx_pretty_printer *pp, tree map)
+{
+ pp_cxx_whitespace (pp);
+ pp_cxx_left_bracket (pp);
+ pp->translate_string ("with");
+ pp_cxx_whitespace (pp);
+
+ for (tree p = map; p; p = TREE_CHAIN (p))
+ {
+ tree parm = TREE_VALUE (p);
+ tree arg = TREE_PURPOSE (p);
+
+ if (TYPE_P (parm))
+ pp->type_id (parm);
+ else
+ pp_cxx_tree_identifier (pp, DECL_NAME (TEMPLATE_PARM_DECL (parm)));
+
+ pp_cxx_whitespace (pp);
+ pp_equal (pp);
+ pp_cxx_whitespace (pp);
+
+ if (TYPE_P (arg) || DECL_TEMPLATE_TEMPLATE_PARM_P (arg))
+ pp->type_id (arg);
+ else
+ pp->expression (arg);
+
+ if (TREE_CHAIN (p) != NULL_TREE)
+ pp_cxx_separate_with (pp, ';');
+ }
+
+ pp_cxx_right_bracket (pp);
+}
+
+void
+pp_cxx_atomic_constraint (cxx_pretty_printer *pp, tree t)
+{
+ /* Emit the expression. */
+ pp->expression (ATOMIC_CONSTR_EXPR (t));
+
+ /* Emit the parameter mapping. */
+ tree map = ATOMIC_CONSTR_MAP (t);
+ if (map && map != error_mark_node)
+ pp_cxx_parameter_mapping (pp, map);
+}
+
+void
+pp_cxx_conjunction (cxx_pretty_printer *pp, tree t)
+{
+ pp_cxx_constraint (pp, TREE_OPERAND (t, 0));
+ pp_string (pp, " /\\ ");
+ pp_cxx_constraint (pp, TREE_OPERAND (t, 1));
+}
+
+void
+pp_cxx_disjunction (cxx_pretty_printer *pp, tree t)
+{
+ pp_cxx_constraint (pp, TREE_OPERAND (t, 0));
+ pp_string (pp, " \\/ ");
+ pp_cxx_constraint (pp, TREE_OPERAND (t, 1));
+}
+
+void
+pp_cxx_constraint (cxx_pretty_printer *pp, tree t)
+{
+ if (t == error_mark_node)
+ return pp->expression (t);
+
+ switch (TREE_CODE (t))
+ {
+ case ATOMIC_CONSTR:
+ pp_cxx_atomic_constraint (pp, t);
+ break;
+
+ case CHECK_CONSTR:
+ pp_cxx_check_constraint (pp, t);
+ break;
+
+ case CONJ_CONSTR:
+ pp_cxx_conjunction (pp, t);
+ break;
+
+ case DISJ_CONSTR:
+ pp_cxx_disjunction (pp, t);
+ break;
+
+ case EXPR_PACK_EXPANSION:
+ pp->expression (TREE_OPERAND (t, 0));
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
\f
typedef c_pretty_print_fn pp_fun;
type_specifier_seq = (pp_fun) pp_cxx_type_specifier_seq;
parameter_list = (pp_fun) pp_cxx_parameter_declaration_clause;
}
+
+/* cxx_pretty_printer's implementation of pretty_printer::clone vfunc. */
+
+pretty_printer *
+cxx_pretty_printer::clone () const
+{
+ return new cxx_pretty_printer (*this);
+}