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:
Douglas Gregor 2007-03-10 01:58:58 +00:00 committed by Doug Gregor
parent 706ca88ebb
commit 5d80a30674
16 changed files with 3220 additions and 281 deletions

View File

@ -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.

View File

@ -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 ();
}

View File

@ -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

View File

@ -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);

View File

@ -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. */

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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");
}

View File

@ -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. */

View File

@ -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 ();
}

View File

@ -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)

View File

@ -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,
&parameter_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

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}