re PR c++/20599 (variadic template support)
2007-03-09 Douglas Gregor <doug.gregor@gmail.com> PR c++/20599 * typeck.c (check_return_expr): Check for bare parameter packs. (comptypes): Compare template parameter packs and type pack expansions. * decl.c (grokdeclarator): Deal with the declaration of function parameter packs. (grokparms): Verify that the (optional) function parameter pack is at the end of the parameter list. (xref_basetypes): Handle pack expansions in the base class. (cp_tree_node_structure): Handle ARGUMENT_PACK_SELECT. * cp-tree.def (TYPE_ARGUMENT_PACK): New. (NONTYPE_ARGUMENT_PACK): New. (TYPE_PACK_EXPANSION): New. (EXPR_PACK_EXPANSION): New. (ARGUMENT_PACK_SELECT): New. * cp-objcp-common.c (cp_tree_size): Compute size of (NON)TYPE_ARGUMENT_PACK, (TYPE|EXPR)_PACK_EXPANSION, and ARGUMENT_PACK_SELECT. * error.c (dump_template_argument): Print template argument packs. (dump_template_argument_list): Ditto. (dump_template_parameter): Dump `...' for template type parameter packs. (dump_type): Dump TYPE_PACK_EXPANSION nodes. (dump_parameters): Print function parameter packs. (dump_template_parms): Print template argument packs. (dump_expr): Dump EXPR_PACK_EXPANSION nodes. (maybe_warn_variadic_templates): New. * operators.def: Add ellipsis operator for EXPR_PACK_EXPANSION. * tree.c (cp_walk_subtrees): Walk BASELINK, TYPE_ARGUMENT_PACK, NONTYPE_ARGUMENT_PACK, TYPE_PACK_EXPANSION, EXPR_PACK_EXPANSION, CAST_EXPR. * mangle.c (write_type): Mangle TYPE_PACK_EXPANSION. (write_template_arg): Write argument packs as separate arguments. * cp-tree.h (struct template_parm_index_s): Add flag that indicates that the template parameter is actually a parameter pack. (struct tree_argument_pack_select): New. (enum cp_tree_node_structure_enum): Add TS_CP_ARGUMENT_PACK_SELECT. (union lang_tree_node): Add argument_pack_select. (FUNCTION_PARAMETER_PACK_P): New. (PACK_EXPANSION_P): New. (PACK_EXPANSION_PATTERN): New. (SET_PACK_EXPANSION_PATTERN): New. (PACK_EXPANSION_PARAMETER_PACKS): New. (ARGUMENT_PACK_P): New. (ARGUMENT_PACK_ARGS): New. (SET_ARGUMENT_PACK_ARGS): New. (ARGUMENT_PACK_INCOMPLETE_P): New. (ARGUMENT_PACK_EXPLICIT_ARGS): New. (TEMPLATE_PARM_PARAMETER_PACK): New. (TEMPLATE_TYPE_PARAMETER_PACK): New. (ARGUMENT_PACK_SELECT_FROM_PACK): New. (ARGUMENT_PACK_SELECT_INDEX): New. (ARGUMENT_PACK_SELECT_ARG): New. (struct cp_declarator): Add parameter_pack_p flag. (maybe_warn_variadic_templates): Declare. (process_template_parm): Add bool parameter IS_PARAMETER_PACK, to indicate a template parameter pack. (uses_parameter_packs): Declare. (template_parameter_pack_p): Declare. (template_parms_variadic_p): Declare. (make_pack_expansion): Declare. (check_for_bare_parameter_packs): Declare. * cxx-pretty-print.c (pp_cxx_unary_expression): Print sizeof... expressions. (pp_cxx_expression): Print pack expansions and non-type argument packs. (pp_cxx_exception_specification): Print pack expansions. (pp_cxx_direct_declarator): Print ellipsis for parameter packs. (pp_cxx_ctor_initializer): Print pack expansions. (pp_cxx_type_id): Print pack expansions. (pp_cxx_template_argument_list): Print argument packs. (pp_cxx_template_parameter): Print ellipsis for template parameter packs. * pt.c (comp_template_parms): Compare template parameter packs. (template_parameter_pack_p): New. (template_parms_variadic_p): New. (template_args_variadic_p): New. (make_ith_pack_parameter_name): New. (struct find_parameter_pack_data): New. (find_parameter_packs_r): New. (uses_parameter_packs): New. (make_pack_expansion): New. (check_for_bare_parameter_packs): New. (expand_template_argument_pack): New. (reduce_template_parm_level): Propagate parameter pack flag. (process_template_parm): Add is_parameter_pack parameter to state when the parameter is actually a parameter pack. Create template parameter packs when is_parameter_pack is true. (current_template_args): The argument for a template parameter pack is an argument pack containing a single pack expansion. (process_partial_specialization): When checking that non-type argument expressions do not involve template parameters, loop over the arguments in argument packs separately. (push_template_decl_real): Check that the type of the declaration does not have any bare parameter packs. Check that primary templates have no more than one parameter pack, and that it comes at the end of the template parameter list. (convert_template_argument): Handle coercions for pack expansion expressions by coercing the pattern then rebuilding the expansion. (coerce_template_parms): When coercing the arguments for a variadic template, pack "extra" arguments into an argument pack. (coerce_template_template_parms): Cannot coerce between parameter packs and non-pack parameters. (template_args_equal): Compare PACK_EXPANSION_P expressions. (comp_template_args): Expand all template arguments packs before comparing template argument lists. (mangle_class_name_for_template): Make argument packs as separate template arguments. (for_each_template_parm_r): No need to handle BASELINK. (instantiate_class_template): Handle pack expansions in the base class list. (tsubst_pack_expansion): New. (tsubst_template_args): Handle substitutions of argument packs and pack expansion into template argument lists. (tsubst_decl): Expand function parameter packs into separate function parameters. (tsubst_arg_types): Expand a type pack expansion into separate argument types. (tsubst_exception_specification): Handle pack expansions in exception specifiers. (tsubst): See through ARGUMENT_PACK_SELECT arguments when replacing a template parameter with its argument. If we encounter a substitution for an argument pack, just return the parameter itself. (tsubst_copy): sizeof(X...) returns the number of elements in parameter pack X. See through ARGUMENT_PACK_SELECT when the PARM_DECL is a parameter pack. (tsubst_expr): Expression pack expansions and argument packs cannot show up here; they will all be handled through function calls, sizeof, and template argument lists. (tsubst_copy_and_build): sizeof(X...) returns the number of elements in parameter pack X. Handle pack expansions in TREE_LIST and CONSTRUCTOR nodes. (fn_type_unification): Handle "incomplete" explicit template argument lists that specify some of the arguments for a template parameter pack. (type_unification_real): Unify arguments against pack expansions. (template_parm_level_and_index): New, helper function. (unify_pack_expansion): New. (unify): Unify argument packs on an argument-by-argument basis, handling variadic argument packs as well. (more_specialized_fn): Handle unification of function parameter packs. All things being equal, prefer non-variadic function templates to variadic function templates. (more_specialized_class): Prefer the variadic class template partial specialization that binds fewer arguments to a parameter pack. (regenerate_decl_from_template): Expand function parameter packs into separate parameters. (instantiate_decl): Ditto. (tsubst_initializer_list): Handle pack expansions for base-class initializers. (dependent_type_p_r): Determine dependent types in argument packs and pack expansions. (value_dependent_expression_p): Determine value-dependence of non-type argument packs. (dependent_template_arg_p): Handle argument packs. * semantics.c (finish_cond): Check for bare parameter packs. (finish_expr_stmt): Ditto. (finish_for_expr): Ditto. (finish_switch_cond): Ditto. (finish_mem_initializers): Ditto. * name-lookup.c (arg_assoc_type): Handle pack expansions and argument packs. * decl2.c (cp_build_parm_decl): Mark function parameter packs. * parser.c (make_declarator): Declarator is not an expansion. (make_pointer_declarator): Transfer parameter pack flag to outer declarator. (make_reference_declarator): Ditto. (make_ptrmem_declarator): Ditto. (make_call_declarator): Ditto. (make_array_declarator): Ditto. (cp_parser_postfix_expression): Allow pack expansion expressions in the argument list for a call expression. (cp_parser_parenthesized_expression_list): Add new parameter ALLOW_EXPANSION_P. When true, parse the ellipsis to mean "expand into separate arguments." (cp_parser_new_placement): Allow pack expansion expressions. (cp_parser_new_initializer): Ditto. (cp_parser_mem_initializer_list): Allow ellipsis to create a base-class initializer expansion. (cp_parser_mem_initializer): Ditto. (cp_parser_template_parameter_list): Keep track of whether the template parameter is a template parameter pack. (cp_parser_template_parameter): Parse the ellipsis to indicate a template parameter pack. (cp_parser_type_parameter): Ditto. (cp_parser_template_argument_list): Parse the ellipsis to indicate a pack expansion. (cp_parser_direct_declarator): Parse the ellipsis to indicate that this declarator is a parameter pack. (cp_parser_parameter_declaration): The ellipsis does not end the parameter declaration, because it might be a parameter pack. Parse the ellipsis to indicate a parameter pack. (cp_parser_initializer): Allow pack expansions. (cp_parser_initializer_list): Allow ellipsis to create an initializer expansion. (cp_parser_base_clause): Allow ellipsis to create a base specifier expansion. (cp_parser_type_id_list): Allow ellipsis to create an exception specifier expansion. (cp_parser_attribute_list): Don't allow pack expansions. (cp_parser_functional_cast): Allow pack expansions. (cp_parser_sizeof_operand): Allow ellipsis following "sizeof" to compute the length of a parameter pack. (cp_parser_next_token_ends_template_argument_p): An ellipsis can end a template argument. * tree.c (cp_walk_subtrees): Walk BASELINK, TYPE_ARGUMENT_PACK, NONTYPE_ARGUMENT_PACK, TYPE_PACK_EXPANSION, EXPR_PACK_EXPANSION, CAST_EXPR. From-SVN: r122788
This commit is contained in:
parent
706ca88ebb
commit
5d80a30674
214
gcc/cp/ChangeLog
214
gcc/cp/ChangeLog
@ -1,3 +1,217 @@
|
||||
2007-03-09 Douglas Gregor <doug.gregor@gmail.com>
|
||||
|
||||
PR c++/20599
|
||||
* typeck.c (check_return_expr): Check for bare parameter packs.
|
||||
(comptypes): Compare template parameter packs and
|
||||
type pack expansions.
|
||||
* decl.c (grokdeclarator): Deal with the declaration of function
|
||||
parameter packs.
|
||||
(grokparms): Verify that the (optional) function parameter pack is
|
||||
at the end of the parameter list.
|
||||
(xref_basetypes): Handle pack expansions in the base class.
|
||||
(cp_tree_node_structure): Handle ARGUMENT_PACK_SELECT.
|
||||
* cp-tree.def (TYPE_ARGUMENT_PACK): New.
|
||||
(NONTYPE_ARGUMENT_PACK): New.
|
||||
(TYPE_PACK_EXPANSION): New.
|
||||
(EXPR_PACK_EXPANSION): New.
|
||||
(ARGUMENT_PACK_SELECT): New.
|
||||
* cp-objcp-common.c (cp_tree_size): Compute size of
|
||||
(NON)TYPE_ARGUMENT_PACK, (TYPE|EXPR)_PACK_EXPANSION, and
|
||||
ARGUMENT_PACK_SELECT.
|
||||
* error.c (dump_template_argument): Print template argument packs.
|
||||
(dump_template_argument_list): Ditto.
|
||||
(dump_template_parameter): Dump `...' for template type parameter
|
||||
packs.
|
||||
(dump_type): Dump TYPE_PACK_EXPANSION nodes.
|
||||
(dump_parameters): Print function parameter packs.
|
||||
(dump_template_parms): Print template argument packs.
|
||||
(dump_expr): Dump EXPR_PACK_EXPANSION nodes.
|
||||
(maybe_warn_variadic_templates): New.
|
||||
* operators.def: Add ellipsis operator for EXPR_PACK_EXPANSION.
|
||||
* tree.c (cp_walk_subtrees): Walk BASELINK, TYPE_ARGUMENT_PACK,
|
||||
NONTYPE_ARGUMENT_PACK, TYPE_PACK_EXPANSION, EXPR_PACK_EXPANSION,
|
||||
CAST_EXPR.
|
||||
* mangle.c (write_type): Mangle TYPE_PACK_EXPANSION.
|
||||
(write_template_arg): Write argument packs as separate arguments.
|
||||
* cp-tree.h (struct template_parm_index_s): Add flag that
|
||||
indicates that the template parameter is actually a parameter
|
||||
pack.
|
||||
(struct tree_argument_pack_select): New.
|
||||
(enum cp_tree_node_structure_enum): Add TS_CP_ARGUMENT_PACK_SELECT.
|
||||
(union lang_tree_node): Add argument_pack_select.
|
||||
(FUNCTION_PARAMETER_PACK_P): New.
|
||||
(PACK_EXPANSION_P): New.
|
||||
(PACK_EXPANSION_PATTERN): New.
|
||||
(SET_PACK_EXPANSION_PATTERN): New.
|
||||
(PACK_EXPANSION_PARAMETER_PACKS): New.
|
||||
(ARGUMENT_PACK_P): New.
|
||||
(ARGUMENT_PACK_ARGS): New.
|
||||
(SET_ARGUMENT_PACK_ARGS): New.
|
||||
(ARGUMENT_PACK_INCOMPLETE_P): New.
|
||||
(ARGUMENT_PACK_EXPLICIT_ARGS): New.
|
||||
(TEMPLATE_PARM_PARAMETER_PACK): New.
|
||||
(TEMPLATE_TYPE_PARAMETER_PACK): New.
|
||||
(ARGUMENT_PACK_SELECT_FROM_PACK): New.
|
||||
(ARGUMENT_PACK_SELECT_INDEX): New.
|
||||
(ARGUMENT_PACK_SELECT_ARG): New.
|
||||
(struct cp_declarator): Add parameter_pack_p flag.
|
||||
(maybe_warn_variadic_templates): Declare.
|
||||
(process_template_parm): Add bool parameter IS_PARAMETER_PACK, to
|
||||
indicate a template parameter pack.
|
||||
(uses_parameter_packs): Declare.
|
||||
(template_parameter_pack_p): Declare.
|
||||
(template_parms_variadic_p): Declare.
|
||||
(make_pack_expansion): Declare.
|
||||
(check_for_bare_parameter_packs): Declare.
|
||||
* cxx-pretty-print.c (pp_cxx_unary_expression): Print
|
||||
sizeof... expressions.
|
||||
(pp_cxx_expression): Print pack expansions and non-type argument
|
||||
packs.
|
||||
(pp_cxx_exception_specification): Print pack expansions.
|
||||
(pp_cxx_direct_declarator): Print ellipsis for parameter packs.
|
||||
(pp_cxx_ctor_initializer): Print pack expansions.
|
||||
(pp_cxx_type_id): Print pack expansions.
|
||||
(pp_cxx_template_argument_list): Print argument packs.
|
||||
(pp_cxx_template_parameter): Print ellipsis for template parameter
|
||||
packs.
|
||||
* pt.c (comp_template_parms): Compare template parameter packs.
|
||||
(template_parameter_pack_p): New.
|
||||
(template_parms_variadic_p): New.
|
||||
(template_args_variadic_p): New.
|
||||
(make_ith_pack_parameter_name): New.
|
||||
(struct find_parameter_pack_data): New.
|
||||
(find_parameter_packs_r): New.
|
||||
(uses_parameter_packs): New.
|
||||
(make_pack_expansion): New.
|
||||
(check_for_bare_parameter_packs): New.
|
||||
(expand_template_argument_pack): New.
|
||||
(reduce_template_parm_level): Propagate parameter pack flag.
|
||||
(process_template_parm): Add is_parameter_pack parameter to state
|
||||
when the parameter is actually a parameter pack. Create template
|
||||
parameter packs when is_parameter_pack is true.
|
||||
(current_template_args): The argument for a template parameter
|
||||
pack is an argument pack containing a single pack expansion.
|
||||
(process_partial_specialization): When checking that non-type
|
||||
argument expressions do not involve template parameters, loop over
|
||||
the arguments in argument packs separately.
|
||||
(push_template_decl_real): Check that the type of the declaration
|
||||
does not have any bare parameter packs. Check that primary
|
||||
templates have no more than one parameter pack, and that it comes
|
||||
at the end of the template parameter list.
|
||||
(convert_template_argument): Handle coercions for pack expansion
|
||||
expressions by coercing the pattern then rebuilding the expansion.
|
||||
(coerce_template_parms): When coercing the arguments for a
|
||||
variadic template, pack "extra" arguments into an argument pack.
|
||||
(coerce_template_template_parms): Cannot coerce between parameter
|
||||
packs and non-pack parameters.
|
||||
(template_args_equal): Compare PACK_EXPANSION_P expressions.
|
||||
(comp_template_args): Expand all template arguments packs before
|
||||
comparing template argument lists.
|
||||
(mangle_class_name_for_template): Make argument packs as separate
|
||||
template arguments.
|
||||
(for_each_template_parm_r): No need to handle BASELINK.
|
||||
(instantiate_class_template): Handle pack expansions in the base
|
||||
class list.
|
||||
(tsubst_pack_expansion): New.
|
||||
(tsubst_template_args): Handle substitutions of argument packs and
|
||||
pack expansion into template argument lists.
|
||||
(tsubst_decl): Expand function parameter packs into separate
|
||||
function parameters.
|
||||
(tsubst_arg_types): Expand a type pack expansion into separate
|
||||
argument types.
|
||||
(tsubst_exception_specification): Handle pack expansions in
|
||||
exception specifiers.
|
||||
(tsubst): See through ARGUMENT_PACK_SELECT arguments when
|
||||
replacing a template parameter with its argument. If we encounter
|
||||
a substitution for an argument pack, just return the parameter
|
||||
itself.
|
||||
(tsubst_copy): sizeof(X...) returns the number of elements in
|
||||
parameter pack X. See through ARGUMENT_PACK_SELECT when the
|
||||
PARM_DECL is a parameter pack.
|
||||
(tsubst_expr): Expression pack expansions and argument packs
|
||||
cannot show up here; they will all be handled through function
|
||||
calls, sizeof, and template argument lists.
|
||||
(tsubst_copy_and_build): sizeof(X...) returns the number of
|
||||
elements in parameter pack X. Handle pack expansions in TREE_LIST
|
||||
and CONSTRUCTOR nodes.
|
||||
(fn_type_unification): Handle "incomplete" explicit template
|
||||
argument lists that specify some of the arguments for a template
|
||||
parameter pack.
|
||||
(type_unification_real): Unify arguments against pack expansions.
|
||||
(template_parm_level_and_index): New, helper function.
|
||||
(unify_pack_expansion): New.
|
||||
(unify): Unify argument packs on an argument-by-argument basis,
|
||||
handling variadic argument packs as well.
|
||||
(more_specialized_fn): Handle unification of function parameter
|
||||
packs. All things being equal, prefer non-variadic function
|
||||
templates to variadic function templates.
|
||||
(more_specialized_class): Prefer the variadic class template
|
||||
partial specialization that binds fewer arguments to a parameter
|
||||
pack.
|
||||
(regenerate_decl_from_template): Expand function parameter packs
|
||||
into separate parameters.
|
||||
(instantiate_decl): Ditto.
|
||||
(tsubst_initializer_list): Handle pack expansions for base-class
|
||||
initializers.
|
||||
(dependent_type_p_r): Determine dependent types in argument packs
|
||||
and pack expansions.
|
||||
(value_dependent_expression_p): Determine value-dependence of
|
||||
non-type argument packs.
|
||||
(dependent_template_arg_p): Handle argument packs.
|
||||
* semantics.c (finish_cond): Check for bare parameter packs.
|
||||
(finish_expr_stmt): Ditto.
|
||||
(finish_for_expr): Ditto.
|
||||
(finish_switch_cond): Ditto.
|
||||
(finish_mem_initializers): Ditto.
|
||||
* name-lookup.c (arg_assoc_type): Handle pack expansions and
|
||||
argument packs.
|
||||
* decl2.c (cp_build_parm_decl): Mark function parameter packs.
|
||||
* parser.c (make_declarator): Declarator is not an expansion.
|
||||
(make_pointer_declarator): Transfer parameter pack flag to outer
|
||||
declarator.
|
||||
(make_reference_declarator): Ditto.
|
||||
(make_ptrmem_declarator): Ditto.
|
||||
(make_call_declarator): Ditto.
|
||||
(make_array_declarator): Ditto.
|
||||
(cp_parser_postfix_expression): Allow pack expansion expressions
|
||||
in the argument list for a call expression.
|
||||
(cp_parser_parenthesized_expression_list): Add new parameter
|
||||
ALLOW_EXPANSION_P. When true, parse the ellipsis to mean "expand
|
||||
into separate arguments."
|
||||
(cp_parser_new_placement): Allow pack expansion expressions.
|
||||
(cp_parser_new_initializer): Ditto.
|
||||
(cp_parser_mem_initializer_list): Allow ellipsis to create a
|
||||
base-class initializer expansion.
|
||||
(cp_parser_mem_initializer): Ditto.
|
||||
(cp_parser_template_parameter_list): Keep track of whether the
|
||||
template parameter is a template parameter pack.
|
||||
(cp_parser_template_parameter): Parse the ellipsis to indicate a
|
||||
template parameter pack.
|
||||
(cp_parser_type_parameter): Ditto.
|
||||
(cp_parser_template_argument_list): Parse the ellipsis to indicate
|
||||
a pack expansion.
|
||||
(cp_parser_direct_declarator): Parse the ellipsis to indicate that
|
||||
this declarator is a parameter pack.
|
||||
(cp_parser_parameter_declaration): The ellipsis does not end the
|
||||
parameter declaration, because it might be a parameter pack. Parse
|
||||
the ellipsis to indicate a parameter pack.
|
||||
(cp_parser_initializer): Allow pack expansions.
|
||||
(cp_parser_initializer_list): Allow ellipsis to create an
|
||||
initializer expansion.
|
||||
(cp_parser_base_clause): Allow ellipsis to create a base specifier
|
||||
expansion.
|
||||
(cp_parser_type_id_list): Allow ellipsis to create an exception
|
||||
specifier expansion.
|
||||
(cp_parser_attribute_list): Don't allow pack expansions.
|
||||
(cp_parser_functional_cast): Allow pack expansions.
|
||||
(cp_parser_sizeof_operand): Allow ellipsis following "sizeof" to
|
||||
compute the length of a parameter pack.
|
||||
(cp_parser_next_token_ends_template_argument_p): An ellipsis can
|
||||
end a template argument.
|
||||
* tree.c (cp_walk_subtrees): Walk BASELINK, TYPE_ARGUMENT_PACK,
|
||||
NONTYPE_ARGUMENT_PACK, TYPE_PACK_EXPANSION, EXPR_PACK_EXPANSION,
|
||||
CAST_EXPR.
|
||||
|
||||
2007-03-09 Dirk Mueller <dmueller@suse.de>
|
||||
|
||||
* cp/call.c (build_new_op): Call warn_logical_operator.
|
||||
|
@ -124,6 +124,17 @@ cp_tree_size (enum tree_code code)
|
||||
case DEFAULT_ARG: return sizeof (struct tree_default_arg);
|
||||
case OVERLOAD: return sizeof (struct tree_overload);
|
||||
case STATIC_ASSERT: return sizeof (struct tree_static_assert);
|
||||
case TYPE_ARGUMENT_PACK:
|
||||
case TYPE_PACK_EXPANSION:
|
||||
return sizeof (struct tree_common);
|
||||
|
||||
case NONTYPE_ARGUMENT_PACK:
|
||||
case EXPR_PACK_EXPANSION:
|
||||
return sizeof (struct tree_exp);
|
||||
|
||||
case ARGUMENT_PACK_SELECT:
|
||||
return sizeof (struct tree_argument_pack_select);
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
@ -352,6 +352,76 @@ DEFTREECODE (UNARY_PLUS_EXPR, "unary_plus_expr", tcc_unary, 1)
|
||||
literal) to be displayed if the condition fails to hold. */
|
||||
DEFTREECODE (STATIC_ASSERT, "static_assert", tcc_exceptional, 0)
|
||||
|
||||
/* Represents an argument pack of types (or templates). An argument
|
||||
pack stores zero or more arguments that will be used to instantiate
|
||||
a parameter pack.
|
||||
|
||||
ARGUMENT_PACK_ARGS retrieves the arguments stored in the argument
|
||||
pack.
|
||||
|
||||
Example:
|
||||
template<typename... Values>
|
||||
class tuple { ... };
|
||||
|
||||
tuple<int, float, double> t;
|
||||
|
||||
Values is a (template) parameter pack. When tuple<int, float,
|
||||
double> is instantiated, the Values parameter pack is instantiated
|
||||
with the argment pack <int, float, double>. ARGUMENT_PACK_ARGS will
|
||||
be a TREE_VEC containing int, float, and double. */
|
||||
DEFTREECODE (TYPE_ARGUMENT_PACK, "type_argument_pack", tcc_type, 0)
|
||||
|
||||
/* Represents an argument pack of values, which can be used either for
|
||||
non-type template arguments or function call arguments.
|
||||
|
||||
NONTYPE_ARGUMENT_PACK plays precisely the same role as
|
||||
TYPE_ARGUMENT_PACK, but will be used for packing non-type template
|
||||
arguments (e.g., "int... Dimensions") or function arguments ("const
|
||||
Args&... args"). */
|
||||
DEFTREECODE (NONTYPE_ARGUMENT_PACK, "nontype_argument_pack", tcc_expression, 1)
|
||||
|
||||
/* Represents a type expression that will be expanded into a list of
|
||||
types when instantiated with one or more argument packs.
|
||||
|
||||
PACK_EXPANSION_PATTERN retrieves the expansion pattern. This is
|
||||
the type or expression that we will substitute into with each
|
||||
argument in an argument pack.
|
||||
|
||||
SET_PACK_EXPANSION_PATTERN sets the expansion pattern.
|
||||
|
||||
PACK_EXPANSION_PARAMETER_PACKS contains a TREE_LIST of the parameter
|
||||
packs that are used in this pack expansion.
|
||||
|
||||
Example:
|
||||
template<typename... Values>
|
||||
struct tied : tuple<Values&...> {
|
||||
// ...
|
||||
};
|
||||
|
||||
The derivation from tuple contains a TYPE_PACK_EXPANSION for the
|
||||
template arguments. Its EXPR_PACK_EXPANSION is "Values&" and its
|
||||
PACK_EXPANSION_PARAMETER_PACKS will contain "Values". */
|
||||
DEFTREECODE (TYPE_PACK_EXPANSION, "type_pack_expansion", tcc_type, 0)
|
||||
|
||||
/* Represents an expression that will be expanded into a list of
|
||||
expressions when instantiated with one or more argument packs.
|
||||
|
||||
EXPR_PACK_EXPANSION plays precisely the same role as TYPE_PACK_EXPANSION,
|
||||
but will be used for expressions. */
|
||||
DEFTREECODE (EXPR_PACK_EXPANSION, "expr_pack_expansion", tcc_expression, 1)
|
||||
|
||||
/* Selects the Ith parameter out of an argument pack. This node will
|
||||
be used when instantiating pack expansions; see
|
||||
tsubst_pack_expansion.
|
||||
|
||||
ARGUMENT_PACK_SELECT_FROM_PACK contains the *_ARGUMENT_PACK node
|
||||
from which the argument will be selected.
|
||||
|
||||
ARGUMENT_PACK_SELECT_INDEX contains the index into the argument
|
||||
pack that will be returned by this ARGUMENT_PACK_SELECT node. The
|
||||
index is a machine integer. */
|
||||
DEFTREECODE (ARGUMENT_PACK_SELECT, "argument_pack_select", tcc_exceptional, 0)
|
||||
|
||||
/*
|
||||
Local variables:
|
||||
mode:c
|
||||
|
109
gcc/cp/cp-tree.h
109
gcc/cp/cp-tree.h
@ -103,6 +103,7 @@ struct diagnostic_context;
|
||||
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
|
||||
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
|
||||
DECL_MEMBER_TEMPLATE_P (in TEMPLATE_DECL)
|
||||
FUNCTION_PARAMETER_PACK_P (in PARM_DECL)
|
||||
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
|
||||
DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
|
||||
3: DECL_IN_AGGR_P.
|
||||
@ -222,6 +223,10 @@ struct template_parm_index_s GTY(())
|
||||
HOST_WIDE_INT level;
|
||||
HOST_WIDE_INT orig_level;
|
||||
tree decl;
|
||||
|
||||
/* When true, indicates that this parameter is actually a parameter
|
||||
pack, for variadic templates. */
|
||||
BOOL_BITFIELD parameter_pack;
|
||||
};
|
||||
typedef struct template_parm_index_s template_parm_index;
|
||||
|
||||
@ -469,6 +474,13 @@ struct tree_static_assert GTY (())
|
||||
location_t location;
|
||||
};
|
||||
|
||||
struct tree_argument_pack_select GTY (())
|
||||
{
|
||||
struct tree_common common;
|
||||
tree argument_pack;
|
||||
int index;
|
||||
};
|
||||
|
||||
enum cp_tree_node_structure_enum {
|
||||
TS_CP_GENERIC,
|
||||
TS_CP_IDENTIFIER,
|
||||
@ -481,6 +493,7 @@ enum cp_tree_node_structure_enum {
|
||||
TS_CP_WRAPPER,
|
||||
TS_CP_DEFAULT_ARG,
|
||||
TS_CP_STATIC_ASSERT,
|
||||
TS_CP_ARGUMENT_PACK_SELECT,
|
||||
LAST_TS_CP_ENUM
|
||||
};
|
||||
|
||||
@ -499,6 +512,8 @@ union lang_tree_node GTY((desc ("cp_tree_node_structure (&%h)"),
|
||||
struct lang_identifier GTY ((tag ("TS_CP_IDENTIFIER"))) identifier;
|
||||
struct tree_static_assert GTY ((tag ("TS_CP_STATIC_ASSERT")))
|
||||
static_assertion;
|
||||
struct tree_argument_pack_select GTY ((tag ("TS_CP_ARGUMENT_PACK_SELECT")))
|
||||
argument_pack_select;
|
||||
};
|
||||
|
||||
|
||||
@ -2188,7 +2203,7 @@ extern void decl_shadowed_for_var_insert (tree, tree);
|
||||
/* Nonzero if the template arguments is actually a vector of vectors,
|
||||
rather than just a vector. */
|
||||
#define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \
|
||||
(NODE && TREE_VEC_ELT (NODE, 0) \
|
||||
(NODE && TREE_VEC_ELT (NODE, 0) \
|
||||
&& TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC)
|
||||
|
||||
/* The depth of a template argument vector. When called directly by
|
||||
@ -2295,6 +2310,84 @@ extern void decl_shadowed_for_var_insert (tree, tree);
|
||||
the class definition is complete. */
|
||||
#define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE)
|
||||
|
||||
/* Determine if a parameter (i.e., a PARM_DECL) is a function
|
||||
parameter pack. */
|
||||
#define FUNCTION_PARAMETER_PACK_P(NODE) \
|
||||
(DECL_LANG_FLAG_1 (PARM_DECL_CHECK (NODE)))
|
||||
|
||||
/* Determines if NODE is an expansion of one or more parameter packs,
|
||||
e.g., a TYPE_PACK_EXPANSION or EXPR_PACK_EXPANSION. */
|
||||
#define PACK_EXPANSION_P(NODE) \
|
||||
(TREE_CODE (NODE) == TYPE_PACK_EXPANSION \
|
||||
|| TREE_CODE (NODE) == EXPR_PACK_EXPANSION)
|
||||
|
||||
/* Extracts the type or expression pattern from a TYPE_PACK_EXPANSION or
|
||||
EXPR_PACK_EXPANSION. */
|
||||
#define PACK_EXPANSION_PATTERN(NODE) \
|
||||
(TREE_CODE (NODE) == TYPE_PACK_EXPANSION? TREE_TYPE (NODE) \
|
||||
: TREE_OPERAND (NODE, 0))
|
||||
|
||||
/* Sets the type or expression pattern for a TYPE_PACK_EXPANSION or
|
||||
EXPR_PACK_EXPANSION. */
|
||||
#define SET_PACK_EXPANSION_PATTERN(NODE,VALUE) \
|
||||
if (TREE_CODE (NODE) == TYPE_PACK_EXPANSION) \
|
||||
TREE_TYPE (NODE) = VALUE; \
|
||||
else \
|
||||
TREE_OPERAND (NODE, 0) = VALUE
|
||||
|
||||
/* The list of parameter packs used in the PACK_EXPANSION_* node. The
|
||||
TREE_VALUE of each TREE_LIST contains the parameter packs. */
|
||||
#define PACK_EXPANSION_PARAMETER_PACKS(NODE) TREE_CHAIN (NODE)
|
||||
|
||||
/* Determine if this is an argument pack. */
|
||||
#define ARGUMENT_PACK_P(NODE) \
|
||||
(TREE_CODE (NODE) == TYPE_ARGUMENT_PACK \
|
||||
|| TREE_CODE (NODE) == NONTYPE_ARGUMENT_PACK)
|
||||
|
||||
/* The arguments stored in an argument pack. Arguments are stored in a
|
||||
TREE_VEC, which may have length zero. */
|
||||
#define ARGUMENT_PACK_ARGS(NODE) \
|
||||
(TREE_CODE (NODE) == TYPE_ARGUMENT_PACK? TREE_TYPE (NODE) \
|
||||
: TREE_OPERAND (NODE, 0))
|
||||
|
||||
/* Set the arguments stored in an argument pack. VALUE must be a
|
||||
TREE_VEC. */
|
||||
#define SET_ARGUMENT_PACK_ARGS(NODE,VALUE) \
|
||||
if (TREE_CODE (NODE) == TYPE_ARGUMENT_PACK) \
|
||||
TREE_TYPE (NODE) = VALUE; \
|
||||
else \
|
||||
TREE_OPERAND (NODE, 0) = VALUE
|
||||
|
||||
/* Whether the argument pack is "incomplete", meaning that more
|
||||
arguments can still be deduced. Incomplete argument packs are only
|
||||
used when the user has provided an explicit template argument list
|
||||
for a variadic function template. Some of the explicit template
|
||||
arguments will be placed into the beginning of the argument pack,
|
||||
but additional arguments might still be deduced. */
|
||||
#define ARGUMENT_PACK_INCOMPLETE_P(NODE) \
|
||||
TREE_LANG_FLAG_0 (ARGUMENT_PACK_ARGS (NODE))
|
||||
|
||||
/* When ARGUMENT_PACK_INCOMPLETE_P, stores the explicit template
|
||||
arguments used to fill this pack. */
|
||||
#define ARGUMENT_PACK_EXPLICIT_ARGS(NODE) \
|
||||
TREE_TYPE (ARGUMENT_PACK_ARGS (NODE))
|
||||
|
||||
/* In an ARGUMENT_PACK_SELECT, the argument pack from which an
|
||||
argument will be selected. */
|
||||
#define ARGUMENT_PACK_SELECT_FROM_PACK(NODE) \
|
||||
(((struct tree_argument_pack_select *)ARGUMENT_PACK_SELECT_CHECK (NODE))->argument_pack)
|
||||
|
||||
/* In an ARGUMENT_PACK_SELECT, the index of the argument we want to
|
||||
select. */
|
||||
#define ARGUMENT_PACK_SELECT_INDEX(NODE) \
|
||||
(((struct tree_argument_pack_select *)ARGUMENT_PACK_SELECT_CHECK (NODE))->index)
|
||||
|
||||
/* In an ARGUMENT_PACK_SELECT, the actual underlying argument that the
|
||||
ARGUMENT_PACK_SELECT represents. */
|
||||
#define ARGUMENT_PACK_SELECT_ARG(NODE) \
|
||||
TREE_VEC_ELT (ARGUMENT_PACK_ARGS (ARGUMENT_PACK_SELECT_FROM_PACK (NODE)), \
|
||||
ARGUMENT_PACK_SELECT_INDEX (NODE));
|
||||
|
||||
/* In a FUNCTION_DECL, the saved language-specific per-function data. */
|
||||
#define DECL_SAVED_FUNCTION_DATA(NODE) \
|
||||
(DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE)) \
|
||||
@ -3612,6 +3705,7 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
|
||||
#define TEMPLATE_PARM_DESCENDANTS(NODE) (TREE_CHAIN (NODE))
|
||||
#define TEMPLATE_PARM_ORIG_LEVEL(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->orig_level)
|
||||
#define TEMPLATE_PARM_DECL(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->decl)
|
||||
#define TEMPLATE_PARM_PARAMETER_PACK(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->parameter_pack)
|
||||
|
||||
/* These macros are for accessing the fields of TEMPLATE_TYPE_PARM,
|
||||
TEMPLATE_TEMPLATE_PARM and BOUND_TEMPLATE_TEMPLATE_PARM nodes. */
|
||||
@ -3626,6 +3720,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
|
||||
(TEMPLATE_PARM_ORIG_LEVEL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
|
||||
#define TEMPLATE_TYPE_DECL(NODE) \
|
||||
(TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
|
||||
#define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
|
||||
(TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
|
||||
|
||||
/* These constants can used as bit flags in the process of tree formatting.
|
||||
|
||||
@ -3812,6 +3908,9 @@ struct cp_declarator {
|
||||
cdk_id and cdk_error, guaranteed to be NULL. */
|
||||
cp_declarator *declarator;
|
||||
location_t id_loc; /* Currently only set for cdk_id. */
|
||||
/* Whether we parsed an ellipsis (`...') just before the declarator,
|
||||
to indicate this is a parameter pack. */
|
||||
bool parameter_pack_p;
|
||||
union {
|
||||
/* For identifiers. */
|
||||
struct {
|
||||
@ -4104,6 +4203,7 @@ extern const char *lang_decl_name (tree, int);
|
||||
extern const char *language_to_string (enum languages);
|
||||
extern const char *class_key_or_enum_as_string (tree);
|
||||
extern void print_instantiation_context (void);
|
||||
extern void maybe_warn_variadic_templates (void);
|
||||
|
||||
/* in except.c */
|
||||
extern void init_exception_processing (void);
|
||||
@ -4194,7 +4294,7 @@ extern void end_specialization (void);
|
||||
extern void begin_explicit_instantiation (void);
|
||||
extern void end_explicit_instantiation (void);
|
||||
extern tree check_explicit_specialization (tree, tree, int, int);
|
||||
extern tree process_template_parm (tree, tree, bool);
|
||||
extern tree process_template_parm (tree, tree, bool, bool);
|
||||
extern tree end_template_parm_list (tree);
|
||||
extern void end_template_decl (void);
|
||||
extern tree push_template_decl (tree);
|
||||
@ -4215,6 +4315,11 @@ extern void do_decl_instantiation (tree, tree);
|
||||
extern void do_type_instantiation (tree, tree, tsubst_flags_t);
|
||||
extern tree instantiate_decl (tree, int, bool);
|
||||
extern int comp_template_parms (tree, tree);
|
||||
extern bool uses_parameter_packs (tree);
|
||||
extern bool template_parameter_pack_p (tree);
|
||||
extern bool template_parms_variadic_p (tree);
|
||||
extern tree make_pack_expansion (tree);
|
||||
extern void check_for_bare_parameter_packs (tree);
|
||||
extern int template_class_depth (tree);
|
||||
extern int is_specialization_of (tree, tree);
|
||||
extern bool is_specialization_of_friend (tree, tree);
|
||||
|
@ -659,6 +659,7 @@ pp_cxx_delete_expression (cxx_pretty_printer *pp, tree t)
|
||||
unary-operator cast-expression
|
||||
sizeof unary-expression
|
||||
sizeof ( type-id )
|
||||
sizeof ... ( identifier )
|
||||
new-expression
|
||||
delete-expression
|
||||
|
||||
@ -686,6 +687,21 @@ pp_cxx_unary_expression (cxx_pretty_printer *pp, tree t)
|
||||
break;
|
||||
|
||||
case SIZEOF_EXPR:
|
||||
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
|
||||
{
|
||||
pp_cxx_identifier (pp, "sizeof");
|
||||
pp_cxx_identifier (pp, "...");
|
||||
pp_cxx_whitespace (pp);
|
||||
pp_cxx_left_paren (pp);
|
||||
if (TYPE_P (TREE_OPERAND (t, 0)))
|
||||
pp_cxx_type_id (pp, TREE_OPERAND (t, 0));
|
||||
else
|
||||
pp_unary_expression (pp, TREE_OPERAND (t, 0));
|
||||
pp_cxx_right_paren (pp);
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
|
||||
case ALIGNOF_EXPR:
|
||||
pp_cxx_identifier (pp, code == SIZEOF_EXPR ? "sizeof" : "__alignof__");
|
||||
pp_cxx_whitespace (pp);
|
||||
@ -1000,6 +1016,24 @@ pp_cxx_expression (cxx_pretty_printer *pp, tree t)
|
||||
pp_cxx_expression (pp, t);
|
||||
break;
|
||||
|
||||
case EXPR_PACK_EXPANSION:
|
||||
pp_cxx_expression (pp, PACK_EXPANSION_PATTERN (t));
|
||||
pp_cxx_identifier (pp, "...");
|
||||
break;
|
||||
|
||||
case NONTYPE_ARGUMENT_PACK:
|
||||
{
|
||||
tree args = ARGUMENT_PACK_ARGS (t);
|
||||
int i, len = TREE_VEC_LENGTH (args);
|
||||
for (i = 0; i < len; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
pp_cxx_separate_with (pp, ',');
|
||||
pp_cxx_expression (pp, TREE_VEC_ELT (args, i));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
pp_c_expression (pp_c_base (pp), t);
|
||||
break;
|
||||
@ -1290,6 +1324,7 @@ static void
|
||||
pp_cxx_exception_specification (cxx_pretty_printer *pp, tree t)
|
||||
{
|
||||
tree ex_spec = TYPE_RAISES_EXCEPTIONS (t);
|
||||
bool need_comma = false;
|
||||
|
||||
if (!TYPE_NOTHROW_P (t) && ex_spec == NULL)
|
||||
return;
|
||||
@ -1297,9 +1332,28 @@ pp_cxx_exception_specification (cxx_pretty_printer *pp, tree t)
|
||||
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_cxx_separate_with (pp, ',');
|
||||
tree type = TREE_VALUE (ex_spec);
|
||||
tree argpack = NULL_TREE;
|
||||
int i, len = 1;
|
||||
|
||||
if (ARGUMENT_PACK_P (type))
|
||||
{
|
||||
argpack = ARGUMENT_PACK_ARGS (type);
|
||||
len = TREE_VEC_LENGTH (argpack);
|
||||
}
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
{
|
||||
if (argpack)
|
||||
type = TREE_VEC_ELT (argpack, i);
|
||||
|
||||
if (need_comma)
|
||||
pp_cxx_separate_with (pp, ',');
|
||||
else
|
||||
need_comma = true;
|
||||
|
||||
pp_cxx_type_id (pp, type);
|
||||
}
|
||||
}
|
||||
pp_cxx_right_paren (pp);
|
||||
}
|
||||
@ -1323,6 +1377,13 @@ pp_cxx_direct_declarator (cxx_pretty_printer *pp, tree t)
|
||||
if (DECL_NAME (t))
|
||||
{
|
||||
pp_cxx_space_for_pointer_operator (pp, TREE_TYPE (t));
|
||||
|
||||
if ((TREE_CODE (t) == PARM_DECL && FUNCTION_PARAMETER_PACK_P (t))
|
||||
|| template_parameter_pack_p (t))
|
||||
/* A function parameter pack or non-type template
|
||||
parameter pack. */
|
||||
pp_cxx_identifier (pp, "...");
|
||||
|
||||
pp_cxx_id_expression (pp, DECL_NAME (t));
|
||||
}
|
||||
pp_cxx_abstract_declarator (pp, TREE_TYPE (t));
|
||||
@ -1388,8 +1449,16 @@ pp_cxx_ctor_initializer (cxx_pretty_printer *pp, tree t)
|
||||
pp_cxx_whitespace (pp);
|
||||
for (; t; t = TREE_CHAIN (t))
|
||||
{
|
||||
pp_cxx_primary_expression (pp, TREE_PURPOSE (t));
|
||||
tree purpose = TREE_PURPOSE (t);
|
||||
bool is_pack = PACK_EXPANSION_P (purpose);
|
||||
|
||||
if (is_pack)
|
||||
pp_cxx_primary_expression (pp, PACK_EXPANSION_PATTERN (purpose));
|
||||
else
|
||||
pp_cxx_primary_expression (pp, purpose);
|
||||
pp_cxx_call_argument_list (pp, TREE_VALUE (t));
|
||||
if (is_pack)
|
||||
pp_cxx_identifier (pp, "...");
|
||||
if (TREE_CHAIN (t))
|
||||
pp_cxx_separate_with (pp, ',');
|
||||
}
|
||||
@ -1510,6 +1579,11 @@ pp_cxx_type_id (cxx_pretty_printer *pp, tree t)
|
||||
pp_cxx_type_specifier_seq (pp, t);
|
||||
break;
|
||||
|
||||
case TYPE_PACK_EXPANSION:
|
||||
pp_cxx_type_id (pp, PACK_EXPANSION_PATTERN (t));
|
||||
pp_cxx_identifier (pp, "...");
|
||||
break;
|
||||
|
||||
default:
|
||||
pp_c_type_id (pp_c_base (pp), t);
|
||||
break;
|
||||
@ -1519,30 +1593,50 @@ pp_cxx_type_id (cxx_pretty_printer *pp, tree t)
|
||||
}
|
||||
|
||||
/* template-argument-list:
|
||||
template-argument
|
||||
template-argument-list, template-argument
|
||||
template-argument ...(opt)
|
||||
template-argument-list, template-argument ...(opt)
|
||||
|
||||
template-argument:
|
||||
assignment-expression
|
||||
type-id
|
||||
template-name */
|
||||
template-name */
|
||||
|
||||
static void
|
||||
pp_cxx_template_argument_list (cxx_pretty_printer *pp, tree t)
|
||||
{
|
||||
int i;
|
||||
bool need_comma = false;
|
||||
|
||||
if (t == NULL)
|
||||
return;
|
||||
for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
|
||||
{
|
||||
tree arg = TREE_VEC_ELT (t, i);
|
||||
if (i != 0)
|
||||
pp_cxx_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);
|
||||
tree argpack = NULL_TREE;
|
||||
int idx, len = 1;
|
||||
|
||||
if (ARGUMENT_PACK_P (arg))
|
||||
{
|
||||
argpack = ARGUMENT_PACK_ARGS (arg);
|
||||
len = TREE_VEC_LENGTH (argpack);
|
||||
}
|
||||
|
||||
for (idx = 0; idx < len; idx++)
|
||||
{
|
||||
if (argpack)
|
||||
arg = TREE_VEC_ELT (argpack, idx);
|
||||
|
||||
if (need_comma)
|
||||
pp_cxx_separate_with (pp, ',');
|
||||
else
|
||||
need_comma = true;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1837,11 +1931,11 @@ pp_cxx_template_parameter_list (cxx_pretty_printer *pp, tree t)
|
||||
parameter-declaration
|
||||
|
||||
type-parameter:
|
||||
class identifier(opt)
|
||||
class identifier(op) = type-id
|
||||
class ...(opt) identifier(opt)
|
||||
class identifier(opt) = type-id
|
||||
typename identifier(opt)
|
||||
typename identifier(opt) = type-id
|
||||
template < template-parameter-list > class identifier(opt)
|
||||
typename ...(opt) identifier(opt) = type-id
|
||||
template < template-parameter-list > class ...(opt) identifier(opt)
|
||||
template < template-parameter-list > class identifier(opt) = template-name */
|
||||
|
||||
static void
|
||||
@ -1852,6 +1946,8 @@ pp_cxx_template_parameter (cxx_pretty_printer *pp, tree t)
|
||||
{
|
||||
case TYPE_DECL:
|
||||
pp_cxx_identifier (pp, "class");
|
||||
if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (t)))
|
||||
pp_cxx_identifier (pp, "...");
|
||||
if (DECL_NAME (parameter))
|
||||
pp_cxx_tree_identifier (pp, DECL_NAME (parameter));
|
||||
/* FIXME: Chech if we should print also default argument. */
|
||||
|
@ -6967,6 +6967,7 @@ grokdeclarator (const cp_declarator *declarator,
|
||||
cp_storage_class storage_class;
|
||||
bool unsigned_p, signed_p, short_p, long_p, thread_p;
|
||||
bool type_was_error_mark_node = false;
|
||||
bool parameter_pack_p = declarator? declarator->parameter_pack_p : false;
|
||||
bool set_no_warning = false;
|
||||
|
||||
signed_p = declspecs->specs[(int)ds_signed];
|
||||
@ -7938,6 +7939,16 @@ grokdeclarator (const cp_declarator *declarator,
|
||||
attrlist = &returned_attrs;
|
||||
}
|
||||
|
||||
/* Handle parameter packs. */
|
||||
if (parameter_pack_p)
|
||||
{
|
||||
if (decl_context == PARM)
|
||||
/* Turn the type into a pack expansion.*/
|
||||
type = make_pack_expansion (type);
|
||||
else
|
||||
error ("non-parameter %qs cannot be a parameter pack", name);
|
||||
}
|
||||
|
||||
/* Did array size calculations overflow? */
|
||||
|
||||
if (TREE_CODE (type) == ARRAY_TYPE
|
||||
@ -8940,6 +8951,11 @@ grokparms (cp_parameter_declarator *first_parm, tree *parms)
|
||||
init = check_default_argument (decl, init);
|
||||
}
|
||||
|
||||
if (TREE_CODE (decl) == PARM_DECL
|
||||
&& FUNCTION_PARAMETER_PACK_P (decl)
|
||||
&& parm->next)
|
||||
error ("parameter packs must be at the end of the parameter list");
|
||||
|
||||
TREE_CHAIN (decl) = decls;
|
||||
decls = decl;
|
||||
result = tree_cons (init, type, result);
|
||||
@ -9941,6 +9957,8 @@ xref_basetypes (tree ref, tree base_list)
|
||||
if (access == access_default_node)
|
||||
access = default_access;
|
||||
|
||||
if (PACK_EXPANSION_P (basetype))
|
||||
basetype = PACK_EXPANSION_PATTERN (basetype);
|
||||
if (TREE_CODE (basetype) == TYPE_DECL)
|
||||
basetype = TREE_TYPE (basetype);
|
||||
if (TREE_CODE (basetype) != RECORD_TYPE
|
||||
@ -9986,6 +10004,11 @@ xref_basetypes (tree ref, tree base_list)
|
||||
error ("duplicate base type %qT invalid", basetype);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (PACK_EXPANSION_P (TREE_VALUE (base_list)))
|
||||
/* Regenerate the pack expansion for the bases. */
|
||||
basetype = make_pack_expansion (basetype);
|
||||
|
||||
TYPE_MARKED_P (basetype) = 1;
|
||||
|
||||
base_binfo = copy_binfo (base_binfo, basetype, ref,
|
||||
@ -11695,6 +11718,7 @@ cp_tree_node_structure (union lang_tree_node * t)
|
||||
case PTRMEM_CST: return TS_CP_PTRMEM;
|
||||
case BASELINK: return TS_CP_BASELINK;
|
||||
case STATIC_ASSERT: return TS_CP_STATIC_ASSERT;
|
||||
case ARGUMENT_PACK_SELECT: return TS_CP_ARGUMENT_PACK_SELECT;
|
||||
default: return TS_CP_GENERIC;
|
||||
}
|
||||
}
|
||||
|
@ -136,6 +136,12 @@ cp_build_parm_decl (tree name, tree type)
|
||||
sees templates. */
|
||||
if (!processing_template_decl)
|
||||
DECL_ARG_TYPE (parm) = type_passed_as (type);
|
||||
|
||||
/* If the type is a pack expansion, then we have a function
|
||||
parameter pack. */
|
||||
if (type && TREE_CODE (type) == TYPE_PACK_EXPANSION)
|
||||
FUNCTION_PARAMETER_PACK_P (parm) = 1;
|
||||
|
||||
return parm;
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,9 @@ dump_scope (tree scope, int flags)
|
||||
static void
|
||||
dump_template_argument (tree arg, int flags)
|
||||
{
|
||||
if (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL)
|
||||
if (ARGUMENT_PACK_P (arg))
|
||||
dump_template_argument_list (ARGUMENT_PACK_ARGS (arg), flags);
|
||||
else if (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL)
|
||||
dump_type (arg, flags & ~TFF_CLASS_KEY_OR_ENUM);
|
||||
else
|
||||
dump_expr (arg, (flags | TFF_EXPR_IN_PARENS) & ~TFF_CLASS_KEY_OR_ENUM);
|
||||
@ -156,9 +158,17 @@ dump_template_argument_list (tree args, int flags)
|
||||
|
||||
for (i = 0; i< n; ++i)
|
||||
{
|
||||
if (need_comma)
|
||||
tree arg = TREE_VEC_ELT (args, i);
|
||||
|
||||
/* Only print a comma if we know there is an argument coming. In
|
||||
the case of an empty template argument pack, no actual
|
||||
argument will be printed. */
|
||||
if (need_comma
|
||||
&& (!ARGUMENT_PACK_P (arg)
|
||||
|| TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg)) > 0))
|
||||
pp_separate_with_comma (cxx_pp);
|
||||
dump_template_argument (TREE_VEC_ELT (args, i), flags);
|
||||
|
||||
dump_template_argument (arg, flags);
|
||||
need_comma = 1;
|
||||
}
|
||||
}
|
||||
@ -182,6 +192,8 @@ dump_template_parameter (tree parm, int flags)
|
||||
if (flags & TFF_DECL_SPECIFIERS)
|
||||
{
|
||||
pp_cxx_identifier (cxx_pp, "class");
|
||||
if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (p)))
|
||||
pp_cxx_identifier (cxx_pp, "...");
|
||||
if (DECL_NAME (p))
|
||||
pp_cxx_tree_identifier (cxx_pp, DECL_NAME (p));
|
||||
}
|
||||
@ -378,6 +390,11 @@ dump_type (tree t, int flags)
|
||||
pp_cxx_right_paren (cxx_pp);
|
||||
break;
|
||||
|
||||
case TYPE_PACK_EXPANSION:
|
||||
dump_type (PACK_EXPANSION_PATTERN (t), flags);
|
||||
pp_cxx_identifier (cxx_pp, "...");
|
||||
break;
|
||||
|
||||
default:
|
||||
pp_unsupported_tree (cxx_pp, t);
|
||||
/* Fall through to error. */
|
||||
@ -1102,8 +1119,7 @@ dump_function_decl (tree t, int flags)
|
||||
static void
|
||||
dump_parameters (tree parmtypes, int flags)
|
||||
{
|
||||
int first;
|
||||
|
||||
int first = 1;
|
||||
pp_cxx_left_paren (cxx_pp);
|
||||
|
||||
for (first = 1; parmtypes != void_list_node;
|
||||
@ -1117,7 +1133,22 @@ dump_parameters (tree parmtypes, int flags)
|
||||
pp_cxx_identifier (cxx_pp, "...");
|
||||
break;
|
||||
}
|
||||
dump_type (TREE_VALUE (parmtypes), flags);
|
||||
if (ARGUMENT_PACK_P (TREE_VALUE (parmtypes)))
|
||||
{
|
||||
tree types = ARGUMENT_PACK_ARGS (TREE_VALUE (parmtypes));
|
||||
int i, len = TREE_VEC_LENGTH (types);
|
||||
first = 1;
|
||||
for (i = 0; i < len; ++i)
|
||||
{
|
||||
if (!first)
|
||||
pp_separate_with_comma (cxx_pp);
|
||||
first = 0;
|
||||
|
||||
dump_type (TREE_VEC_ELT (types, i), flags);
|
||||
}
|
||||
}
|
||||
else
|
||||
dump_type (TREE_VALUE (parmtypes), flags);
|
||||
|
||||
if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && TREE_PURPOSE (parmtypes))
|
||||
{
|
||||
@ -1240,14 +1271,19 @@ dump_template_parms (tree info, int primary, int flags)
|
||||
{
|
||||
tree arg = TREE_VEC_ELT (args, ix);
|
||||
|
||||
if (ix)
|
||||
pp_separate_with_comma (cxx_pp);
|
||||
|
||||
if (!arg)
|
||||
pp_identifier (cxx_pp, "<template parameter error>");
|
||||
else
|
||||
dump_template_argument (arg, flags);
|
||||
}
|
||||
/* Only print a comma if we know there is an argument coming. In
|
||||
the case of an empty template argument pack, no actual
|
||||
argument will be printed. */
|
||||
if (ix
|
||||
&& (!ARGUMENT_PACK_P (arg)
|
||||
|| TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg)) > 0))
|
||||
pp_separate_with_comma (cxx_pp);
|
||||
|
||||
if (!arg)
|
||||
pp_identifier (cxx_pp, "<template parameter error>");
|
||||
else
|
||||
dump_template_argument (arg, flags);
|
||||
}
|
||||
}
|
||||
else if (primary)
|
||||
{
|
||||
@ -1946,6 +1982,11 @@ dump_expr (tree t, int flags)
|
||||
dump_expr (TREE_OPERAND (t, 0), flags);
|
||||
break;
|
||||
|
||||
case EXPR_PACK_EXPANSION:
|
||||
dump_expr (PACK_EXPANSION_PATTERN (t), flags);
|
||||
pp_cxx_identifier (cxx_pp, "...");
|
||||
break;
|
||||
|
||||
/* This list is incomplete, but should suffice for now.
|
||||
It is very important that `sorry' does not call
|
||||
`report_error_function'. That could cause an infinite loop. */
|
||||
@ -2464,3 +2505,14 @@ cp_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level,
|
||||
input_location, dlevel);
|
||||
report_diagnostic (&diagnostic);
|
||||
}
|
||||
|
||||
/* Warn about the use of variadic templates when appropriate. */
|
||||
void
|
||||
maybe_warn_variadic_templates (void)
|
||||
{
|
||||
if ((!flag_cpp0x || flag_iso) && !in_system_header)
|
||||
/* We really want to surpress this warning in system headers,
|
||||
because libstdc++ uses variadic templates even when we aren't
|
||||
in C++0x mode. */
|
||||
pedwarn ("ISO C++ does not include variadic templates");
|
||||
}
|
||||
|
@ -1645,6 +1645,11 @@ write_type (tree type)
|
||||
write_type (TREE_TYPE (type));
|
||||
break;
|
||||
|
||||
case TYPE_PACK_EXPANSION:
|
||||
write_string ("U10__variadic");
|
||||
write_type (PACK_EXPANSION_PATTERN (type));
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
@ -2302,7 +2307,15 @@ write_template_arg (tree node)
|
||||
G.need_abi_warning = 1;
|
||||
}
|
||||
|
||||
if (TYPE_P (node))
|
||||
if (ARGUMENT_PACK_P (node))
|
||||
{
|
||||
/* Expand the template argument pack. */
|
||||
tree args = ARGUMENT_PACK_ARGS (node);
|
||||
int i, length = TREE_VEC_LENGTH (args);
|
||||
for (i = 0; i < length; ++i)
|
||||
write_template_arg (TREE_VEC_ELT (args, i));
|
||||
}
|
||||
else if (TYPE_P (node))
|
||||
write_type (node);
|
||||
else if (code == TEMPLATE_DECL)
|
||||
/* A template appearing as a template arg is a template template arg. */
|
||||
|
@ -4563,6 +4563,18 @@ arg_assoc_type (struct arg_lookup *k, tree type)
|
||||
case LANG_TYPE:
|
||||
gcc_assert (type == unknown_type_node);
|
||||
return false;
|
||||
case TYPE_PACK_EXPANSION:
|
||||
return arg_assoc_type (k, PACK_EXPANSION_PATTERN (type));
|
||||
case TYPE_ARGUMENT_PACK:
|
||||
{
|
||||
tree args = ARGUMENT_PACK_ARGS (type);
|
||||
int i, len = TREE_VEC_LENGTH (args);
|
||||
for (i = 0; i < len; i++)
|
||||
if (arg_assoc_type (k, TREE_VEC_ELT (args, i)))
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
@ -150,3 +150,6 @@ DEF_SIMPLE_OPERATOR ("?:", COND_EXPR, "qu", 3)
|
||||
|
||||
/* Miscellaneous. */
|
||||
DEF_SIMPLE_OPERATOR ("()", CALL_EXPR, "cl", -1)
|
||||
|
||||
/* Variadic templates extension. */
|
||||
DEF_SIMPLE_OPERATOR ("...", EXPR_PACK_EXPANSION, "pu", 1)
|
||||
|
370
gcc/cp/parser.c
370
gcc/cp/parser.c
@ -891,6 +891,7 @@ make_declarator (cp_declarator_kind kind)
|
||||
declarator->kind = kind;
|
||||
declarator->attributes = NULL_TREE;
|
||||
declarator->declarator = NULL;
|
||||
declarator->parameter_pack_p = false;
|
||||
|
||||
return declarator;
|
||||
}
|
||||
@ -928,7 +929,7 @@ make_id_declarator (tree qualifying_scope, tree unqualified_name,
|
||||
declarator->u.id.qualifying_scope = qualifying_scope;
|
||||
declarator->u.id.unqualified_name = unqualified_name;
|
||||
declarator->u.id.sfk = sfk;
|
||||
|
||||
|
||||
return declarator;
|
||||
}
|
||||
|
||||
@ -945,6 +946,13 @@ make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
|
||||
declarator->declarator = target;
|
||||
declarator->u.pointer.qualifiers = cv_qualifiers;
|
||||
declarator->u.pointer.class_type = NULL_TREE;
|
||||
if (target)
|
||||
{
|
||||
declarator->parameter_pack_p = target->parameter_pack_p;
|
||||
target->parameter_pack_p = false;
|
||||
}
|
||||
else
|
||||
declarator->parameter_pack_p = false;
|
||||
|
||||
return declarator;
|
||||
}
|
||||
@ -960,6 +968,13 @@ make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
|
||||
declarator->declarator = target;
|
||||
declarator->u.pointer.qualifiers = cv_qualifiers;
|
||||
declarator->u.pointer.class_type = NULL_TREE;
|
||||
if (target)
|
||||
{
|
||||
declarator->parameter_pack_p = target->parameter_pack_p;
|
||||
target->parameter_pack_p = false;
|
||||
}
|
||||
else
|
||||
declarator->parameter_pack_p = false;
|
||||
|
||||
return declarator;
|
||||
}
|
||||
@ -978,6 +993,14 @@ make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type,
|
||||
declarator->u.pointer.qualifiers = cv_qualifiers;
|
||||
declarator->u.pointer.class_type = class_type;
|
||||
|
||||
if (pointee)
|
||||
{
|
||||
declarator->parameter_pack_p = pointee->parameter_pack_p;
|
||||
pointee->parameter_pack_p = false;
|
||||
}
|
||||
else
|
||||
declarator->parameter_pack_p = false;
|
||||
|
||||
return declarator;
|
||||
}
|
||||
|
||||
@ -999,6 +1022,13 @@ make_call_declarator (cp_declarator *target,
|
||||
declarator->u.function.parameters = parms;
|
||||
declarator->u.function.qualifiers = cv_qualifiers;
|
||||
declarator->u.function.exception_specification = exception_specification;
|
||||
if (target)
|
||||
{
|
||||
declarator->parameter_pack_p = target->parameter_pack_p;
|
||||
target->parameter_pack_p = false;
|
||||
}
|
||||
else
|
||||
declarator->parameter_pack_p = false;
|
||||
|
||||
return declarator;
|
||||
}
|
||||
@ -1014,6 +1044,13 @@ make_array_declarator (cp_declarator *element, tree bounds)
|
||||
declarator = make_declarator (cdk_array);
|
||||
declarator->declarator = element;
|
||||
declarator->u.array.bounds = bounds;
|
||||
if (element)
|
||||
{
|
||||
declarator->parameter_pack_p = element->parameter_pack_p;
|
||||
element->parameter_pack_p = false;
|
||||
}
|
||||
else
|
||||
declarator->parameter_pack_p = false;
|
||||
|
||||
return declarator;
|
||||
}
|
||||
@ -1518,7 +1555,7 @@ static tree cp_parser_postfix_open_square_expression
|
||||
static tree cp_parser_postfix_dot_deref_expression
|
||||
(cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *);
|
||||
static tree cp_parser_parenthesized_expression_list
|
||||
(cp_parser *, bool, bool, bool *);
|
||||
(cp_parser *, bool, bool, bool, bool *);
|
||||
static void cp_parser_pseudo_destructor_name
|
||||
(cp_parser *, tree *, tree *);
|
||||
static tree cp_parser_unary_expression
|
||||
@ -1731,9 +1768,9 @@ static void cp_parser_template_declaration
|
||||
static tree cp_parser_template_parameter_list
|
||||
(cp_parser *);
|
||||
static tree cp_parser_template_parameter
|
||||
(cp_parser *, bool *);
|
||||
(cp_parser *, bool *, bool *);
|
||||
static tree cp_parser_type_parameter
|
||||
(cp_parser *);
|
||||
(cp_parser *, bool *);
|
||||
static tree cp_parser_template_id
|
||||
(cp_parser *, bool, bool, bool);
|
||||
static tree cp_parser_template_name
|
||||
@ -4368,7 +4405,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
|
||||
}
|
||||
args = (cp_parser_parenthesized_expression_list
|
||||
(parser, /*is_attribute_list=*/false,
|
||||
/*cast_p=*/false,
|
||||
/*cast_p=*/false, /*allow_expansion_p=*/true,
|
||||
/*non_constant_p=*/NULL));
|
||||
if (is_builtin_constant_p)
|
||||
{
|
||||
@ -4764,6 +4801,9 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
|
||||
|
||||
CAST_P is true if this expression is the target of a cast.
|
||||
|
||||
ALLOW_EXPANSION_P is true if this expression allows expansion of an
|
||||
argument pack.
|
||||
|
||||
Returns a TREE_LIST. The TREE_VALUE of each node is a
|
||||
representation of an assignment-expression. Note that a TREE_LIST
|
||||
is returned even if there is only a single expression in the list.
|
||||
@ -4778,6 +4818,7 @@ static tree
|
||||
cp_parser_parenthesized_expression_list (cp_parser* parser,
|
||||
bool is_attribute_list,
|
||||
bool cast_p,
|
||||
bool allow_expansion_p,
|
||||
bool *non_constant_p)
|
||||
{
|
||||
tree expression_list = NULL_TREE;
|
||||
@ -4827,6 +4868,18 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
|
||||
if (fold_expr_p)
|
||||
expr = fold_non_dependent_expr (expr);
|
||||
|
||||
/* If we have an ellipsis, then this is an expression
|
||||
expansion. */
|
||||
if (allow_expansion_p
|
||||
&& cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
|
||||
{
|
||||
/* Consume the `...'. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
/* Build the argument pack. */
|
||||
expr = make_pack_expansion (expr);
|
||||
}
|
||||
|
||||
/* Add it to the list. We add error_mark_node
|
||||
expressions to the list, so that we can still tell if
|
||||
the correct form for a parenthesized expression-list
|
||||
@ -5276,7 +5329,7 @@ cp_parser_new_placement (cp_parser* parser)
|
||||
|
||||
/* Parse the expression-list. */
|
||||
expression_list = (cp_parser_parenthesized_expression_list
|
||||
(parser, false, /*cast_p=*/false,
|
||||
(parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
|
||||
/*non_constant_p=*/NULL));
|
||||
|
||||
return expression_list;
|
||||
@ -5481,7 +5534,7 @@ cp_parser_new_initializer (cp_parser* parser)
|
||||
tree expression_list;
|
||||
|
||||
expression_list = (cp_parser_parenthesized_expression_list
|
||||
(parser, false, /*cast_p=*/false,
|
||||
(parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
|
||||
/*non_constant_p=*/NULL));
|
||||
if (!expression_list)
|
||||
expression_list = void_zero_node;
|
||||
@ -8189,8 +8242,8 @@ cp_parser_ctor_initializer_opt (cp_parser* parser)
|
||||
/* Parse a mem-initializer-list.
|
||||
|
||||
mem-initializer-list:
|
||||
mem-initializer
|
||||
mem-initializer , mem-initializer-list */
|
||||
mem-initializer ... [opt]
|
||||
mem-initializer ... [opt] , mem-initializer-list */
|
||||
|
||||
static void
|
||||
cp_parser_mem_initializer_list (cp_parser* parser)
|
||||
@ -8209,6 +8262,26 @@ cp_parser_mem_initializer_list (cp_parser* parser)
|
||||
|
||||
/* Parse the mem-initializer. */
|
||||
mem_initializer = cp_parser_mem_initializer (parser);
|
||||
/* If the next token is a `...', we're expanding member initializers. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
|
||||
{
|
||||
/* Consume the `...'. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
/* The TREE_PURPOSE must be a _TYPE, because base-specifiers
|
||||
can be expanded but members cannot. */
|
||||
if (mem_initializer != error_mark_node
|
||||
&& !TYPE_P (TREE_PURPOSE (mem_initializer)))
|
||||
{
|
||||
error ("cannot expand initializer for member %<%D%>",
|
||||
TREE_PURPOSE (mem_initializer));
|
||||
mem_initializer = error_mark_node;
|
||||
}
|
||||
|
||||
/* Construct the pack expansion type. */
|
||||
if (mem_initializer != error_mark_node)
|
||||
mem_initializer = make_pack_expansion (mem_initializer);
|
||||
}
|
||||
/* Add it to the list, unless it was erroneous. */
|
||||
if (mem_initializer != error_mark_node)
|
||||
{
|
||||
@ -8264,6 +8337,7 @@ cp_parser_mem_initializer (cp_parser* parser)
|
||||
expression_list
|
||||
= cp_parser_parenthesized_expression_list (parser, false,
|
||||
/*cast_p=*/false,
|
||||
/*allow_expansion_p=*/true,
|
||||
/*non_constant_p=*/NULL);
|
||||
if (expression_list == error_mark_node)
|
||||
return error_mark_node;
|
||||
@ -8667,14 +8741,18 @@ cp_parser_template_parameter_list (cp_parser* parser)
|
||||
tree parameter;
|
||||
cp_token *token;
|
||||
bool is_non_type;
|
||||
bool is_parameter_pack;
|
||||
|
||||
/* Parse the template-parameter. */
|
||||
parameter = cp_parser_template_parameter (parser, &is_non_type);
|
||||
parameter = cp_parser_template_parameter (parser,
|
||||
&is_non_type,
|
||||
&is_parameter_pack);
|
||||
/* Add it to the list. */
|
||||
if (parameter != error_mark_node)
|
||||
parameter_list = process_template_parm (parameter_list,
|
||||
parameter,
|
||||
is_non_type);
|
||||
is_non_type,
|
||||
is_parameter_pack);
|
||||
else
|
||||
{
|
||||
tree err_parm = build_tree_list (parameter, parameter);
|
||||
@ -8703,10 +8781,12 @@ cp_parser_template_parameter_list (cp_parser* parser)
|
||||
If all goes well, returns a TREE_LIST. The TREE_VALUE represents
|
||||
the parameter. The TREE_PURPOSE is the default value, if any.
|
||||
Returns ERROR_MARK_NODE on failure. *IS_NON_TYPE is set to true
|
||||
iff this parameter is a non-type parameter. */
|
||||
iff this parameter is a non-type parameter. *IS_PARAMETER_PACK is
|
||||
set to true iff this parameter is a parameter pack. */
|
||||
|
||||
static tree
|
||||
cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
|
||||
cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
|
||||
bool *is_parameter_pack)
|
||||
{
|
||||
cp_token *token;
|
||||
cp_parameter_declarator *parameter_declarator;
|
||||
@ -8714,11 +8794,13 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
|
||||
|
||||
/* Assume it is a type parameter or a template parameter. */
|
||||
*is_non_type = false;
|
||||
/* Assume it not a parameter pack. */
|
||||
*is_parameter_pack = false;
|
||||
/* Peek at the next token. */
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
/* If it is `class' or `template', we have a type-parameter. */
|
||||
if (token->keyword == RID_TEMPLATE)
|
||||
return cp_parser_type_parameter (parser);
|
||||
return cp_parser_type_parameter (parser, is_parameter_pack);
|
||||
/* If it is `class' or `typename' we do not know yet whether it is a
|
||||
type parameter or a non-type parameter. Consider:
|
||||
|
||||
@ -8736,6 +8818,10 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
|
||||
{
|
||||
/* Peek at the token after `class' or `typename'. */
|
||||
token = cp_lexer_peek_nth_token (parser->lexer, 2);
|
||||
/* If it's an ellipsis, we have a template type parameter
|
||||
pack. */
|
||||
if (token->type == CPP_ELLIPSIS)
|
||||
return cp_parser_type_parameter (parser, is_parameter_pack);
|
||||
/* If it's an identifier, skip it. */
|
||||
if (token->type == CPP_NAME)
|
||||
token = cp_lexer_peek_nth_token (parser->lexer, 3);
|
||||
@ -8744,7 +8830,7 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
|
||||
if (token->type == CPP_COMMA
|
||||
|| token->type == CPP_EQ
|
||||
|| token->type == CPP_GREATER)
|
||||
return cp_parser_type_parameter (parser);
|
||||
return cp_parser_type_parameter (parser, is_parameter_pack);
|
||||
}
|
||||
|
||||
/* Otherwise, it is a non-type parameter.
|
||||
@ -8759,12 +8845,40 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
|
||||
parameter_declarator
|
||||
= cp_parser_parameter_declaration (parser, /*template_parm_p=*/true,
|
||||
/*parenthesized_p=*/NULL);
|
||||
|
||||
/* If the parameter declaration is marked as a parameter pack, set
|
||||
*IS_PARAMETER_PACK to notify the caller. Also, unmark the
|
||||
declarator's PACK_EXPANSION_P, otherwise we'll get errors from
|
||||
grokdeclarator. */
|
||||
if (parameter_declarator
|
||||
&& parameter_declarator->declarator
|
||||
&& parameter_declarator->declarator->parameter_pack_p)
|
||||
{
|
||||
*is_parameter_pack = true;
|
||||
parameter_declarator->declarator->parameter_pack_p = false;
|
||||
}
|
||||
|
||||
/* If the next token is an ellipsis, and we don't already have it
|
||||
marked as a parameter pack, then we have a parameter pack (that
|
||||
has no declarator); */
|
||||
if (!*is_parameter_pack
|
||||
&& cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
|
||||
{
|
||||
|
||||
/* Consume the `...'. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
maybe_warn_variadic_templates ();
|
||||
|
||||
*is_parameter_pack = true;
|
||||
}
|
||||
|
||||
parm = grokdeclarator (parameter_declarator->declarator,
|
||||
¶meter_declarator->decl_specifiers,
|
||||
PARM, /*initialized=*/0,
|
||||
/*attrlist=*/NULL);
|
||||
if (parm == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
return build_tree_list (parameter_declarator->default_argument, parm);
|
||||
}
|
||||
|
||||
@ -8779,12 +8893,20 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
|
||||
template < template-parameter-list > class identifier [opt]
|
||||
= id-expression
|
||||
|
||||
GNU Extension (variadic templates):
|
||||
|
||||
type-parameter:
|
||||
class ... identifier [opt]
|
||||
typename ... identifier [opt]
|
||||
|
||||
Returns a TREE_LIST. The TREE_VALUE is itself a TREE_LIST. The
|
||||
TREE_PURPOSE is the default-argument, if any. The TREE_VALUE is
|
||||
the declaration of the parameter. */
|
||||
the declaration of the parameter.
|
||||
|
||||
Sets *IS_PARAMETER_PACK if this is a template parameter pack. */
|
||||
|
||||
static tree
|
||||
cp_parser_type_parameter (cp_parser* parser)
|
||||
cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
|
||||
{
|
||||
cp_token *token;
|
||||
tree parameter;
|
||||
@ -8803,6 +8925,17 @@ cp_parser_type_parameter (cp_parser* parser)
|
||||
tree identifier;
|
||||
tree default_argument;
|
||||
|
||||
/* If the next token is an ellipsis, we have a template
|
||||
argument pack. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
|
||||
{
|
||||
/* Consume the `...' token. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
maybe_warn_variadic_templates ();
|
||||
|
||||
*is_parameter_pack = true;
|
||||
}
|
||||
|
||||
/* If the next token is an identifier, then it names the
|
||||
parameter. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
|
||||
@ -8821,6 +8954,18 @@ cp_parser_type_parameter (cp_parser* parser)
|
||||
/* Parse the default-argument. */
|
||||
push_deferring_access_checks (dk_no_deferred);
|
||||
default_argument = cp_parser_type_id (parser);
|
||||
|
||||
/* Template parameter packs cannot have default
|
||||
arguments. */
|
||||
if (*is_parameter_pack)
|
||||
{
|
||||
if (identifier)
|
||||
error ("template parameter pack %qD cannot have a default argument",
|
||||
identifier);
|
||||
else
|
||||
error ("template parameter packs cannot have default arguments");
|
||||
default_argument = NULL_TREE;
|
||||
}
|
||||
pop_deferring_access_checks ();
|
||||
}
|
||||
else
|
||||
@ -8846,6 +8991,16 @@ cp_parser_type_parameter (cp_parser* parser)
|
||||
cp_parser_require (parser, CPP_GREATER, "`>'");
|
||||
/* Look for the `class' keyword. */
|
||||
cp_parser_require_keyword (parser, RID_CLASS, "`class'");
|
||||
/* If the next token is an ellipsis, we have a template
|
||||
argument pack. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
|
||||
{
|
||||
/* Consume the `...' token. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
maybe_warn_variadic_templates ();
|
||||
|
||||
*is_parameter_pack = true;
|
||||
}
|
||||
/* If the next token is an `=', then there is a
|
||||
default-argument. If the next token is a `>', we are at
|
||||
the end of the parameter-list. If the next token is a `,',
|
||||
@ -8900,6 +9055,18 @@ cp_parser_type_parameter (cp_parser* parser)
|
||||
/* See if the default argument is valid. */
|
||||
default_argument
|
||||
= check_template_template_default_arg (default_argument);
|
||||
|
||||
/* Template parameter packs cannot have default
|
||||
arguments. */
|
||||
if (*is_parameter_pack)
|
||||
{
|
||||
if (identifier)
|
||||
error ("template parameter pack %qD cannot have a default argument",
|
||||
identifier);
|
||||
else
|
||||
error ("template parameter packs cannot have default arguments");
|
||||
default_argument = NULL_TREE;
|
||||
}
|
||||
pop_deferring_access_checks ();
|
||||
}
|
||||
else
|
||||
@ -9316,8 +9483,8 @@ cp_parser_template_name (cp_parser* parser,
|
||||
/* Parse a template-argument-list.
|
||||
|
||||
template-argument-list:
|
||||
template-argument
|
||||
template-argument-list , template-argument
|
||||
template-argument ... [opt]
|
||||
template-argument-list , template-argument ... [opt]
|
||||
|
||||
Returns a TREE_VEC containing the arguments. */
|
||||
|
||||
@ -9353,6 +9520,19 @@ cp_parser_template_argument_list (cp_parser* parser)
|
||||
|
||||
/* Parse the template-argument. */
|
||||
argument = cp_parser_template_argument (parser);
|
||||
|
||||
/* If the next token is an ellipsis, we're expanding a template
|
||||
argument pack. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
|
||||
{
|
||||
/* Consume the `...' token. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
/* Make the argument into a TYPE_PACK_EXPANSION or
|
||||
EXPR_PACK_EXPANSION. */
|
||||
argument = make_pack_expansion (argument);
|
||||
}
|
||||
|
||||
if (n_args == alloced)
|
||||
{
|
||||
alloced *= 2;
|
||||
@ -11878,17 +12058,47 @@ cp_parser_direct_declarator (cp_parser* parser,
|
||||
tree unqualified_name;
|
||||
special_function_kind sfk;
|
||||
bool abstract_ok;
|
||||
bool pack_expansion_p = false;
|
||||
|
||||
/* Parse a declarator-id */
|
||||
abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER);
|
||||
if (abstract_ok)
|
||||
cp_parser_parse_tentatively (parser);
|
||||
{
|
||||
cp_parser_parse_tentatively (parser);
|
||||
|
||||
/* If we see an ellipsis, we should be looking at a
|
||||
parameter pack. */
|
||||
if (token->type == CPP_ELLIPSIS)
|
||||
{
|
||||
/* Consume the `...' */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
pack_expansion_p = true;
|
||||
}
|
||||
}
|
||||
|
||||
unqualified_name
|
||||
= cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok);
|
||||
qualifying_scope = parser->scope;
|
||||
if (abstract_ok)
|
||||
{
|
||||
if (!cp_parser_parse_definitely (parser))
|
||||
bool okay = false;
|
||||
|
||||
if (!unqualified_name && pack_expansion_p)
|
||||
{
|
||||
/* Check whether an error occurred. */
|
||||
okay = !cp_parser_error_occurred (parser);
|
||||
|
||||
/* We already consumed the ellipsis to mark a
|
||||
parameter pack, but we have no way to report it,
|
||||
so abort the tentative parse. We will be exiting
|
||||
immediately anyway. */
|
||||
cp_parser_abort_tentative_parse (parser);
|
||||
}
|
||||
else
|
||||
okay = cp_parser_parse_definitely (parser);
|
||||
|
||||
if (!okay)
|
||||
unqualified_name = error_mark_node;
|
||||
else if (unqualified_name
|
||||
&& (qualifying_scope
|
||||
@ -11905,6 +12115,8 @@ cp_parser_direct_declarator (cp_parser* parser,
|
||||
if (unqualified_name == error_mark_node)
|
||||
{
|
||||
declarator = cp_error_declarator;
|
||||
pack_expansion_p = false;
|
||||
declarator->parameter_pack_p = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -11941,6 +12153,7 @@ cp_parser_direct_declarator (cp_parser* parser,
|
||||
}
|
||||
|
||||
sfk = sfk_none;
|
||||
|
||||
if (unqualified_name)
|
||||
{
|
||||
tree class_type;
|
||||
@ -12008,6 +12221,10 @@ cp_parser_direct_declarator (cp_parser* parser,
|
||||
unqualified_name,
|
||||
sfk);
|
||||
declarator->id_loc = token->location;
|
||||
declarator->parameter_pack_p = pack_expansion_p;
|
||||
|
||||
if (pack_expansion_p)
|
||||
maybe_warn_variadic_templates ();
|
||||
|
||||
handle_declarator:;
|
||||
scope = get_scope_of_declarator (declarator);
|
||||
@ -12569,9 +12786,9 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
|
||||
/* Parse a parameter declaration.
|
||||
|
||||
parameter-declaration:
|
||||
decl-specifier-seq declarator
|
||||
decl-specifier-seq ... [opt] declarator
|
||||
decl-specifier-seq declarator = assignment-expression
|
||||
decl-specifier-seq abstract-declarator [opt]
|
||||
decl-specifier-seq ... [opt] abstract-declarator [opt]
|
||||
decl-specifier-seq abstract-declarator [opt] = assignment-expression
|
||||
|
||||
If TEMPLATE_PARM_P is TRUE, then this parameter-declaration
|
||||
@ -12626,12 +12843,13 @@ cp_parser_parameter_declaration (cp_parser *parser,
|
||||
|
||||
/* Peek at the next token. */
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
|
||||
/* If the next token is a `)', `,', `=', `>', or `...', then there
|
||||
is no declarator. */
|
||||
is no declarator. However, when variadic templates are enabled,
|
||||
there may be a declarator following `...'. */
|
||||
if (token->type == CPP_CLOSE_PAREN
|
||||
|| token->type == CPP_COMMA
|
||||
|| token->type == CPP_EQ
|
||||
|| token->type == CPP_ELLIPSIS
|
||||
|| token->type == CPP_GREATER)
|
||||
{
|
||||
declarator = NULL;
|
||||
@ -12673,6 +12891,34 @@ cp_parser_parameter_declaration (cp_parser *parser,
|
||||
cp_parser_attributes_opt (parser));
|
||||
}
|
||||
|
||||
/* If the next token is an ellipsis, and the type of the declarator
|
||||
contains parameter packs but it is not a TYPE_PACK_EXPANSION, then
|
||||
we actually have a parameter pack expansion expression. Otherwise,
|
||||
leave the ellipsis for a C-style variadic function. */
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
|
||||
{
|
||||
tree type = decl_specifiers.type;
|
||||
|
||||
if (DECL_P (type))
|
||||
type = TREE_TYPE (type);
|
||||
|
||||
if (TREE_CODE (type) != TYPE_PACK_EXPANSION
|
||||
&& (!declarator || !declarator->parameter_pack_p)
|
||||
&& uses_parameter_packs (type))
|
||||
{
|
||||
/* Consume the `...'. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
maybe_warn_variadic_templates ();
|
||||
|
||||
/* Build a pack expansion type */
|
||||
if (declarator)
|
||||
declarator->parameter_pack_p = true;
|
||||
else
|
||||
decl_specifiers.type = make_pack_expansion (type);
|
||||
}
|
||||
}
|
||||
|
||||
/* The restriction on defining new types applies only to the type
|
||||
of the parameter, not to the default argument. */
|
||||
parser->type_definition_forbidden_message = saved_message;
|
||||
@ -12904,6 +13150,7 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
|
||||
else if (token->type == CPP_OPEN_PAREN)
|
||||
init = cp_parser_parenthesized_expression_list (parser, false,
|
||||
/*cast_p=*/false,
|
||||
/*allow_expansion_p=*/true,
|
||||
non_constant_p);
|
||||
else
|
||||
{
|
||||
@ -12979,8 +13226,8 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
|
||||
/* Parse an initializer-list.
|
||||
|
||||
initializer-list:
|
||||
initializer-clause
|
||||
initializer-list , initializer-clause
|
||||
initializer-clause ... [opt]
|
||||
initializer-list , initializer-clause ... [opt]
|
||||
|
||||
GNU Extension:
|
||||
|
||||
@ -13034,6 +13281,17 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
|
||||
if (clause_non_constant_p)
|
||||
*non_constant_p = true;
|
||||
|
||||
/* If we have an ellipsis, this is an initializer pack
|
||||
expansion. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
|
||||
{
|
||||
/* Consume the `...'. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
/* Turn the initializer into an initializer expansion. */
|
||||
initializer = make_pack_expansion (initializer);
|
||||
}
|
||||
|
||||
/* Add it to the vector. */
|
||||
CONSTRUCTOR_APPEND_ELT(v, identifier, initializer);
|
||||
|
||||
@ -14335,8 +14593,8 @@ cp_parser_constant_initializer (cp_parser* parser)
|
||||
: base-specifier-list
|
||||
|
||||
base-specifier-list:
|
||||
base-specifier
|
||||
base-specifier-list , base-specifier
|
||||
base-specifier ... [opt]
|
||||
base-specifier-list , base-specifier ... [opt]
|
||||
|
||||
Returns a TREE_LIST representing the base-classes, in the order in
|
||||
which they were declared. The representation of each node is as
|
||||
@ -14358,12 +14616,28 @@ cp_parser_base_clause (cp_parser* parser)
|
||||
{
|
||||
cp_token *token;
|
||||
tree base;
|
||||
bool pack_expansion_p = false;
|
||||
|
||||
/* Look for the base-specifier. */
|
||||
base = cp_parser_base_specifier (parser);
|
||||
/* Look for the (optional) ellipsis. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
|
||||
{
|
||||
/* Consume the `...'. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
pack_expansion_p = true;
|
||||
}
|
||||
|
||||
/* Add BASE to the front of the list. */
|
||||
if (base != error_mark_node)
|
||||
{
|
||||
if (pack_expansion_p)
|
||||
/* Make this a pack expansion type. */
|
||||
TREE_VALUE (base) = make_pack_expansion (TREE_VALUE (base));
|
||||
else
|
||||
check_for_bare_parameter_packs (TREE_VALUE (base));
|
||||
|
||||
TREE_CHAIN (base) = bases;
|
||||
bases = base;
|
||||
}
|
||||
@ -14569,8 +14843,8 @@ cp_parser_exception_specification_opt (cp_parser* parser)
|
||||
/* Parse an (optional) type-id-list.
|
||||
|
||||
type-id-list:
|
||||
type-id
|
||||
type-id-list , type-id
|
||||
type-id ... [opt]
|
||||
type-id-list , type-id ... [opt]
|
||||
|
||||
Returns a TREE_LIST. The TREE_VALUE of each node is a TYPE,
|
||||
in the order that the types were presented. */
|
||||
@ -14587,6 +14861,15 @@ cp_parser_type_id_list (cp_parser* parser)
|
||||
|
||||
/* Get the next type-id. */
|
||||
type = cp_parser_type_id (parser);
|
||||
/* Parse the optional ellipsis. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
|
||||
{
|
||||
/* Consume the `...'. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
/* Turn the type into a pack expansion expression. */
|
||||
type = make_pack_expansion (type);
|
||||
}
|
||||
/* Add it to the list. */
|
||||
types = add_exception_specifier (types, type, /*complain=*/1);
|
||||
/* Peek at the next token. */
|
||||
@ -15020,6 +15303,7 @@ cp_parser_attribute_list (cp_parser* parser)
|
||||
{
|
||||
arguments = cp_parser_parenthesized_expression_list
|
||||
(parser, true, /*cast_p=*/false,
|
||||
/*allow_expansion_p=*/false,
|
||||
/*non_constant_p=*/NULL);
|
||||
/* Save the arguments away. */
|
||||
TREE_VALUE (attribute) = arguments;
|
||||
@ -16102,6 +16386,7 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
|
||||
expression_list
|
||||
= cp_parser_parenthesized_expression_list (parser, false,
|
||||
/*cast_p=*/true,
|
||||
/*allow_expansion_p=*/true,
|
||||
/*non_constant_p=*/NULL);
|
||||
|
||||
cast = build_functional_cast (type, expression_list);
|
||||
@ -16451,6 +16736,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
|
||||
const char *saved_message;
|
||||
bool saved_integral_constant_expression_p;
|
||||
bool saved_non_integral_constant_expression_p;
|
||||
bool pack_expansion_p = false;
|
||||
|
||||
/* Initialize FORMAT the first time we get here. */
|
||||
if (!format)
|
||||
@ -16475,6 +16761,19 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
|
||||
= parser->non_integral_constant_expression_p;
|
||||
parser->integral_constant_expression_p = false;
|
||||
|
||||
/* If it's a `...', then we are computing the length of a parameter
|
||||
pack. */
|
||||
if (keyword == RID_SIZEOF
|
||||
&& cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
|
||||
{
|
||||
/* Consume the `...'. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
maybe_warn_variadic_templates ();
|
||||
|
||||
/* Note that this is an expansion. */
|
||||
pack_expansion_p = true;
|
||||
}
|
||||
|
||||
/* Do not actually evaluate the expression. */
|
||||
++skip_evaluation;
|
||||
/* If it's a `(', then we might be looking at the type-id
|
||||
@ -16519,6 +16818,11 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
|
||||
if (!expr)
|
||||
expr = cp_parser_unary_expression (parser, /*address_p=*/false,
|
||||
/*cast_p=*/false);
|
||||
|
||||
if (pack_expansion_p)
|
||||
/* Build a pack expansion. */
|
||||
expr = make_pack_expansion (expr);
|
||||
|
||||
/* Go back to evaluating expressions. */
|
||||
--skip_evaluation;
|
||||
|
||||
@ -16811,7 +17115,9 @@ cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
|
||||
cp_token *token;
|
||||
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
return (token->type == CPP_COMMA || token->type == CPP_GREATER);
|
||||
return (token->type == CPP_COMMA
|
||||
|| token->type == CPP_GREATER
|
||||
|| token->type == CPP_ELLIPSIS);
|
||||
}
|
||||
|
||||
/* Returns TRUE iff the n-th token is a "<", or the n-th is a "[" and the
|
||||
|
2381
gcc/cp/pt.c
2381
gcc/cp/pt.c
File diff suppressed because it is too large
Load Diff
@ -509,6 +509,8 @@ finish_cond (tree *cond_p, tree expr)
|
||||
tree cond = pop_stmt_list (*cond_p);
|
||||
if (TREE_CODE (cond) == DECL_EXPR)
|
||||
expr = cond;
|
||||
|
||||
check_for_bare_parameter_packs (expr);
|
||||
}
|
||||
*cond_p = expr;
|
||||
}
|
||||
@ -618,6 +620,8 @@ finish_expr_stmt (tree expr)
|
||||
else if (!type_dependent_expression_p (expr))
|
||||
convert_to_void (build_non_dependent_expr (expr), "statement");
|
||||
|
||||
check_for_bare_parameter_packs (expr);
|
||||
|
||||
/* Simplification of inner statement expressions, compound exprs,
|
||||
etc can result in us already having an EXPR_STMT. */
|
||||
if (TREE_CODE (expr) != CLEANUP_POINT_EXPR)
|
||||
@ -866,6 +870,7 @@ finish_for_expr (tree expr, tree for_stmt)
|
||||
else if (!type_dependent_expression_p (expr))
|
||||
convert_to_void (build_non_dependent_expr (expr), "3rd expression in for");
|
||||
expr = maybe_cleanup_point_expr_void (expr);
|
||||
check_for_bare_parameter_packs (expr);
|
||||
FOR_EXPR (for_stmt) = expr;
|
||||
}
|
||||
|
||||
@ -966,6 +971,7 @@ finish_switch_cond (tree cond, tree switch_stmt)
|
||||
add_stmt (switch_stmt);
|
||||
push_switch (switch_stmt);
|
||||
SWITCH_STMT_BODY (switch_stmt) = push_stmt_list ();
|
||||
check_for_bare_parameter_packs (cond);
|
||||
}
|
||||
|
||||
/* Finish the body of a switch-statement, which may be given by
|
||||
@ -1362,7 +1368,22 @@ finish_mem_initializers (tree mem_inits)
|
||||
mem_inits = nreverse (mem_inits);
|
||||
|
||||
if (processing_template_decl)
|
||||
add_stmt (build_min_nt (CTOR_INITIALIZER, mem_inits));
|
||||
{
|
||||
tree mem;
|
||||
|
||||
for (mem = mem_inits; mem; mem = TREE_CHAIN (mem))
|
||||
{
|
||||
/* If the TREE_PURPOSE is a TYPE_PACK_EXPANSION, skip the
|
||||
check for bare parameter packs in the TREE_VALUE, because
|
||||
any parameter packs in the TREE_VALUE have already been
|
||||
bound as part of the TREE_PURPOSE. See
|
||||
make_pack_expansion for more information. */
|
||||
if (TREE_CODE (TREE_PURPOSE (mem)) != TYPE_PACK_EXPANSION)
|
||||
check_for_bare_parameter_packs (TREE_VALUE (mem));
|
||||
}
|
||||
|
||||
add_stmt (build_min_nt (CTOR_INITIALIZER, mem_inits));
|
||||
}
|
||||
else
|
||||
emit_mem_initializers (mem_inits);
|
||||
}
|
||||
|
@ -2233,12 +2233,16 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
|
||||
case TEMPLATE_TYPE_PARM:
|
||||
case TYPENAME_TYPE:
|
||||
case TYPEOF_TYPE:
|
||||
case BASELINK:
|
||||
/* None of these have subtrees other than those already walked
|
||||
above. */
|
||||
*walk_subtrees_p = 0;
|
||||
break;
|
||||
|
||||
case BASELINK:
|
||||
WALK_SUBTREE (BASELINK_FUNCTIONS (*tp));
|
||||
*walk_subtrees_p = 0;
|
||||
break;
|
||||
|
||||
case TINST_LEVEL:
|
||||
WALK_SUBTREE (TINST_DECL (*tp));
|
||||
*walk_subtrees_p = 0;
|
||||
@ -2264,6 +2268,38 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
|
||||
WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE (*tp));
|
||||
break;
|
||||
|
||||
case TYPE_ARGUMENT_PACK:
|
||||
case NONTYPE_ARGUMENT_PACK:
|
||||
{
|
||||
tree args = ARGUMENT_PACK_ARGS (*tp);
|
||||
int i, len = TREE_VEC_LENGTH (args);
|
||||
for (i = 0; i < len; i++)
|
||||
WALK_SUBTREE (TREE_VEC_ELT (args, i));
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_PACK_EXPANSION:
|
||||
WALK_SUBTREE (TREE_TYPE (*tp));
|
||||
*walk_subtrees_p = 0;
|
||||
break;
|
||||
|
||||
case EXPR_PACK_EXPANSION:
|
||||
WALK_SUBTREE (TREE_OPERAND (*tp, 0));
|
||||
*walk_subtrees_p = 0;
|
||||
break;
|
||||
|
||||
case CAST_EXPR:
|
||||
if (TREE_TYPE (*tp))
|
||||
WALK_SUBTREE (TREE_TYPE (*tp));
|
||||
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (*tp)); ++i)
|
||||
WALK_SUBTREE (TREE_OPERAND (*tp, i));
|
||||
}
|
||||
*walk_subtrees_p = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
input_location = save_locus;
|
||||
return NULL_TREE;
|
||||
|
@ -991,7 +991,9 @@ structural_comptypes (tree t1, tree t2, int strict)
|
||||
case TEMPLATE_TEMPLATE_PARM:
|
||||
case BOUND_TEMPLATE_TEMPLATE_PARM:
|
||||
if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
|
||||
|| TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2))
|
||||
|| TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
|
||||
|| (TEMPLATE_TYPE_PARAMETER_PACK (t1)
|
||||
!= TEMPLATE_TYPE_PARAMETER_PACK (t2)))
|
||||
return false;
|
||||
if (!comp_template_parms
|
||||
(DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t1)),
|
||||
@ -1050,7 +1052,9 @@ structural_comptypes (tree t1, tree t2, int strict)
|
||||
|
||||
case TEMPLATE_TYPE_PARM:
|
||||
if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
|
||||
|| TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2))
|
||||
|| TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
|
||||
|| (TEMPLATE_TYPE_PARAMETER_PACK (t1)
|
||||
!= TEMPLATE_TYPE_PARAMETER_PACK (t2)))
|
||||
return false;
|
||||
break;
|
||||
|
||||
@ -1080,6 +1084,10 @@ structural_comptypes (tree t1, tree t2, int strict)
|
||||
return false;
|
||||
break;
|
||||
|
||||
case TYPE_PACK_EXPANSION:
|
||||
return same_type_p (PACK_EXPANSION_PATTERN (t1),
|
||||
PACK_EXPANSION_PATTERN (t2));
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -6543,6 +6551,7 @@ check_return_expr (tree retval, bool *no_warning)
|
||||
if (processing_template_decl)
|
||||
{
|
||||
current_function_returns_value = 1;
|
||||
check_for_bare_parameter_packs (retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user