Commit 2993d08a by Jason Merrill Committed by Jason Merrill

Core DR 904 PR c++/41933

	Core DR 904
	PR c++/41933
	* parser.c (cp_parser_lambda_introducer): Handle variadic capture.
	* lambda.c (add_capture): Handle variadic capture.
	(add_default_capture, lambda_capture_field_type): Likewise.
	(build_capture_proxy, register_capture_members): Likewise.
	* pt.c (register_specialization): Allow FIELD_DECL.
	(retrieve_specialization): Likewise.
	(find_parameter_packs_r): Handle FIELD_DECL and VAR_DECL.
	(tsubst_pack_expansion): Handle FIELD_DECL packs.
	(gen_elem_of_pack_expansion_instantiation): Likewise.
	(instantiate_class_template_1): Likewise.
	(tsubst_decl, tsubst_copy): Likewise.
	(tsubst_expr) [DECL_EXPR]: Handle capture proxy packs.
	(tsubst_copy_and_build) [VAR_DECL]: Likewise.
	* semantics.c (finish_non_static_data_member): Don't try to represent
	the type of a COMPOUND_REF of a FIELD_DECL pack.

From-SVN: r202605
parent 73f4e2d2
2013-09-15 Jason Merrill <jason@redhat.com> 2013-09-15 Jason Merrill <jason@redhat.com>
Core DR 904
PR c++/41933
* parser.c (cp_parser_lambda_introducer): Handle variadic capture.
* lambda.c (add_capture): Handle variadic capture.
(add_default_capture, lambda_capture_field_type): Likewise.
(build_capture_proxy, register_capture_members): Likewise.
* pt.c (register_specialization): Allow FIELD_DECL.
(retrieve_specialization): Likewise.
(find_parameter_packs_r): Handle FIELD_DECL and VAR_DECL.
(tsubst_pack_expansion): Handle FIELD_DECL packs.
(gen_elem_of_pack_expansion_instantiation): Likewise.
(instantiate_class_template_1): Likewise.
(tsubst_decl, tsubst_copy): Likewise.
(tsubst_expr) [DECL_EXPR]: Handle capture proxy packs.
(tsubst_copy_and_build) [VAR_DECL]: Likewise.
* semantics.c (finish_non_static_data_member): Don't try to represent
the type of a COMPOUND_REF of a FIELD_DECL pack.
PR c++/41933 PR c++/41933
* cp-tree.h (DECL_PACK_P): Replace FUNCTION_PARAMETER_PACK_P. * cp-tree.h (DECL_PACK_P): Replace FUNCTION_PARAMETER_PACK_P.
* cxx-pretty-print.c (direct_declarator): Adjust. * cxx-pretty-print.c (direct_declarator): Adjust.
......
...@@ -215,7 +215,8 @@ lambda_capture_field_type (tree expr, bool explicit_init_p) ...@@ -215,7 +215,8 @@ lambda_capture_field_type (tree expr, bool explicit_init_p)
} }
else else
type = non_reference (unlowered_expr_type (expr)); type = non_reference (unlowered_expr_type (expr));
if (!type || WILDCARD_TYPE_P (type) || type_uses_auto (type)) if (!type || WILDCARD_TYPE_P (type) || type_uses_auto (type)
|| DECL_PACK_P (expr))
{ {
type = cxx_make_type (DECLTYPE_TYPE); type = cxx_make_type (DECLTYPE_TYPE);
DECLTYPE_TYPE_EXPR (type) = expr; DECLTYPE_TYPE_EXPR (type) = expr;
...@@ -320,15 +321,21 @@ tree ...@@ -320,15 +321,21 @@ tree
lambda_proxy_type (tree ref) lambda_proxy_type (tree ref)
{ {
tree type; tree type;
if (ref == error_mark_node)
return error_mark_node;
if (REFERENCE_REF_P (ref)) if (REFERENCE_REF_P (ref))
ref = TREE_OPERAND (ref, 0); ref = TREE_OPERAND (ref, 0);
gcc_assert (TREE_CODE (ref) == COMPONENT_REF);
type = TREE_TYPE (ref); type = TREE_TYPE (ref);
if (type && !WILDCARD_TYPE_P (non_reference (type))) if (!type || WILDCARD_TYPE_P (non_reference (type)))
return type; {
type = cxx_make_type (DECLTYPE_TYPE); type = cxx_make_type (DECLTYPE_TYPE);
DECLTYPE_TYPE_EXPR (type) = ref; DECLTYPE_TYPE_EXPR (type) = ref;
DECLTYPE_FOR_LAMBDA_PROXY (type) = true; DECLTYPE_FOR_LAMBDA_PROXY (type) = true;
SET_TYPE_STRUCTURAL_EQUALITY (type); SET_TYPE_STRUCTURAL_EQUALITY (type);
}
if (DECL_PACK_P (TREE_OPERAND (ref, 1)))
type = make_pack_expansion (type);
return type; return type;
} }
...@@ -341,6 +348,9 @@ build_capture_proxy (tree member) ...@@ -341,6 +348,9 @@ build_capture_proxy (tree member)
{ {
tree var, object, fn, closure, name, lam, type; tree var, object, fn, closure, name, lam, type;
if (PACK_EXPANSION_P (member))
member = PACK_EXPANSION_PATTERN (member);
closure = DECL_CONTEXT (member); closure = DECL_CONTEXT (member);
fn = lambda_function (closure); fn = lambda_function (closure);
lam = CLASSTYPE_LAMBDA_EXPR (closure); lam = CLASSTYPE_LAMBDA_EXPR (closure);
...@@ -422,12 +432,20 @@ vla_capture_type (tree array_type) ...@@ -422,12 +432,20 @@ vla_capture_type (tree array_type)
and return it. */ and return it. */
tree tree
add_capture (tree lambda, tree id, tree initializer, bool by_reference_p, add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
bool explicit_init_p) bool explicit_init_p)
{ {
char *buf; char *buf;
tree type, member, name; tree type, member, name;
bool vla = false; bool vla = false;
bool variadic = false;
tree initializer = orig_init;
if (PACK_EXPANSION_P (initializer))
{
initializer = PACK_EXPANSION_PATTERN (initializer);
variadic = true;
}
if (TREE_CODE (initializer) == TREE_LIST) if (TREE_CODE (initializer) == TREE_LIST)
initializer = build_x_compound_expr_from_list (initializer, ELK_INIT, initializer = build_x_compound_expr_from_list (initializer, ELK_INIT,
...@@ -498,6 +516,9 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p, ...@@ -498,6 +516,9 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
IDENTIFIER_MARKED (name) = true; IDENTIFIER_MARKED (name) = true;
} }
if (variadic)
type = make_pack_expansion (type);
/* Make member variable. */ /* Make member variable. */
member = build_decl (input_location, FIELD_DECL, name, type); member = build_decl (input_location, FIELD_DECL, name, type);
DECL_VLA_CAPTURE_P (member) = vla; DECL_VLA_CAPTURE_P (member) = vla;
...@@ -518,8 +539,14 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p, ...@@ -518,8 +539,14 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
&& current_class_type == LAMBDA_EXPR_CLOSURE (lambda)) && current_class_type == LAMBDA_EXPR_CLOSURE (lambda))
finish_member_declaration (member); finish_member_declaration (member);
tree listmem = member;
if (variadic)
{
listmem = make_pack_expansion (member);
initializer = orig_init;
}
LAMBDA_EXPR_CAPTURE_LIST (lambda) LAMBDA_EXPR_CAPTURE_LIST (lambda)
= tree_cons (member, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda)); = tree_cons (listmem, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda));
if (LAMBDA_EXPR_CLOSURE (lambda)) if (LAMBDA_EXPR_CLOSURE (lambda))
return build_capture_proxy (member); return build_capture_proxy (member);
...@@ -538,9 +565,14 @@ register_capture_members (tree captures) ...@@ -538,9 +565,14 @@ register_capture_members (tree captures)
return; return;
register_capture_members (TREE_CHAIN (captures)); register_capture_members (TREE_CHAIN (captures));
tree field = TREE_PURPOSE (captures);
if (PACK_EXPANSION_P (field))
field = PACK_EXPANSION_PATTERN (field);
/* We set this in add_capture to avoid duplicates. */ /* We set this in add_capture to avoid duplicates. */
IDENTIFIER_MARKED (DECL_NAME (TREE_PURPOSE (captures))) = false; IDENTIFIER_MARKED (DECL_NAME (field)) = false;
finish_member_declaration (TREE_PURPOSE (captures)); finish_member_declaration (field);
} }
/* Similar to add_capture, except this works on a stack of nested lambdas. /* Similar to add_capture, except this works on a stack of nested lambdas.
...@@ -565,6 +597,8 @@ add_default_capture (tree lambda_stack, tree id, tree initializer) ...@@ -565,6 +597,8 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
tree lambda = TREE_VALUE (node); tree lambda = TREE_VALUE (node);
current_class_type = LAMBDA_EXPR_CLOSURE (lambda); current_class_type = LAMBDA_EXPR_CLOSURE (lambda);
if (DECL_PACK_P (initializer))
initializer = make_pack_expansion (initializer);
var = add_capture (lambda, var = add_capture (lambda,
id, id,
initializer, initializer,
......
...@@ -8753,6 +8753,14 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) ...@@ -8753,6 +8753,14 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
/*template_arg_p=*/false, /*template_arg_p=*/false,
&error_msg, &error_msg,
capture_token->location); capture_token->location);
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
{
cp_lexer_consume_token (parser->lexer);
capture_init_expr = make_pack_expansion (capture_init_expr);
}
else
check_for_bare_parameter_packs (capture_init_expr);
} }
if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE
......
...@@ -1004,7 +1004,10 @@ optimize_specialization_lookup_p (tree tmpl) ...@@ -1004,7 +1004,10 @@ optimize_specialization_lookup_p (tree tmpl)
If TMPL is a type template and CLASS_SPECIALIZATIONS_P is true, If TMPL is a type template and CLASS_SPECIALIZATIONS_P is true,
then we search for a partial specialization matching ARGS. This then we search for a partial specialization matching ARGS. This
parameter is ignored if TMPL is not a class template. */ parameter is ignored if TMPL is not a class template.
We can also look up a FIELD_DECL, if it is a lambda capture pack; the
result is a NONTYPE_ARGUMENT_PACK. */
static tree static tree
retrieve_specialization (tree tmpl, tree args, hashval_t hash) retrieve_specialization (tree tmpl, tree args, hashval_t hash)
...@@ -1015,12 +1018,15 @@ retrieve_specialization (tree tmpl, tree args, hashval_t hash) ...@@ -1015,12 +1018,15 @@ retrieve_specialization (tree tmpl, tree args, hashval_t hash)
if (args == error_mark_node) if (args == error_mark_node)
return NULL_TREE; return NULL_TREE;
gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL); gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL
|| TREE_CODE (tmpl) == FIELD_DECL);
/* There should be as many levels of arguments as there are /* There should be as many levels of arguments as there are
levels of parameters. */ levels of parameters. */
gcc_assert (TMPL_ARGS_DEPTH (args) gcc_assert (TMPL_ARGS_DEPTH (args)
== TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))); == (TREE_CODE (tmpl) == TEMPLATE_DECL
? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))
: template_class_depth (DECL_CONTEXT (tmpl))));
if (optimize_specialization_lookup_p (tmpl)) if (optimize_specialization_lookup_p (tmpl))
{ {
...@@ -1311,7 +1317,10 @@ is_specialization_of_friend (tree decl, tree friend_decl) ...@@ -1311,7 +1317,10 @@ is_specialization_of_friend (tree decl, tree friend_decl)
/* Register the specialization SPEC as a specialization of TMPL with /* Register the specialization SPEC as a specialization of TMPL with
the indicated ARGS. IS_FRIEND indicates whether the specialization the indicated ARGS. IS_FRIEND indicates whether the specialization
is actually just a friend declaration. Returns SPEC, or an is actually just a friend declaration. Returns SPEC, or an
equivalent prior declaration, if available. */ equivalent prior declaration, if available.
We also store instantiations of field packs in the hash table, even
though they are not themselves templates, to make lookup easier. */
static tree static tree
register_specialization (tree spec, tree tmpl, tree args, bool is_friend, register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
...@@ -1321,7 +1330,9 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend, ...@@ -1321,7 +1330,9 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
void **slot = NULL; void **slot = NULL;
spec_entry elt; spec_entry elt;
gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL && DECL_P (spec)); gcc_assert ((TREE_CODE (tmpl) == TEMPLATE_DECL && DECL_P (spec))
|| (TREE_CODE (tmpl) == FIELD_DECL
&& TREE_CODE (spec) == NONTYPE_ARGUMENT_PACK));
if (TREE_CODE (spec) == FUNCTION_DECL if (TREE_CODE (spec) == FUNCTION_DECL
&& uses_template_parms (DECL_TI_ARGS (spec))) && uses_template_parms (DECL_TI_ARGS (spec)))
...@@ -1443,7 +1454,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend, ...@@ -1443,7 +1454,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
/* A specialization must be declared in the same namespace as the /* A specialization must be declared in the same namespace as the
template it is specializing. */ template it is specializing. */
if (DECL_TEMPLATE_SPECIALIZATION (spec) if (DECL_P (spec) && DECL_TEMPLATE_SPECIALIZATION (spec)
&& !check_specialization_namespace (tmpl)) && !check_specialization_namespace (tmpl))
DECL_CONTEXT (spec) = DECL_CONTEXT (tmpl); DECL_CONTEXT (spec) = DECL_CONTEXT (tmpl);
...@@ -3084,6 +3095,7 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data) ...@@ -3084,6 +3095,7 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
parameter_pack_p = true; parameter_pack_p = true;
break; break;
case FIELD_DECL:
case PARM_DECL: case PARM_DECL:
if (DECL_PACK_P (t)) if (DECL_PACK_P (t))
{ {
...@@ -3094,6 +3106,18 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data) ...@@ -3094,6 +3106,18 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
} }
break; break;
/* Look through a lambda capture proxy to the field pack. */
case VAR_DECL:
if (DECL_HAS_VALUE_EXPR_P (t))
{
tree v = DECL_VALUE_EXPR (t);
cp_walk_tree (&v,
&find_parameter_packs_r,
ppd, ppd->visited);
*walk_subtrees = 0;
}
break;
case BASES: case BASES:
parameter_pack_p = true; parameter_pack_p = true;
break; break;
...@@ -8913,6 +8937,8 @@ instantiate_class_template_1 (tree type) ...@@ -8913,6 +8937,8 @@ instantiate_class_template_1 (tree type)
else if (TREE_CODE (t) != CONST_DECL) else if (TREE_CODE (t) != CONST_DECL)
{ {
tree r; tree r;
tree vec = NULL_TREE;
int len = 1;
/* The file and line for this declaration, to /* The file and line for this declaration, to
assist in error message reporting. Since we assist in error message reporting. Since we
...@@ -8925,55 +8951,68 @@ instantiate_class_template_1 (tree type) ...@@ -8925,55 +8951,68 @@ instantiate_class_template_1 (tree type)
r = tsubst (t, args, tf_warning_or_error, NULL_TREE); r = tsubst (t, args, tf_warning_or_error, NULL_TREE);
if (TREE_CODE (t) == TEMPLATE_DECL) if (TREE_CODE (t) == TEMPLATE_DECL)
--processing_template_decl; --processing_template_decl;
if (VAR_P (r))
if (TREE_CODE (r) == TREE_VEC)
{ {
/* In [temp.inst]: /* A capture pack became multiple fields. */
vec = r;
[t]he initialization (and any associated len = TREE_VEC_LENGTH (vec);
side-effects) of a static data member does
not occur unless the static data member is
itself used in a way that requires the
definition of the static data member to
exist.
Therefore, we do not substitute into the
initialized for the static data member here. */
finish_static_data_member_decl
(r,
/*init=*/NULL_TREE,
/*init_const_expr_p=*/false,
/*asmspec_tree=*/NULL_TREE,
/*flags=*/0);
/* Instantiate members marked with attribute used. */
if (r != error_mark_node && DECL_PRESERVE_P (r))
mark_used (r);
} }
else if (TREE_CODE (r) == FIELD_DECL)
for (int i = 0; i < len; ++i)
{ {
/* Determine whether R has a valid type and can be if (vec)
completed later. If R is invalid, then its type is r = TREE_VEC_ELT (vec, i);
replaced by error_mark_node. */ if (VAR_P (r))
tree rtype = TREE_TYPE (r);
if (can_complete_type_without_circularity (rtype))
complete_type (rtype);
if (!COMPLETE_TYPE_P (rtype))
{ {
cxx_incomplete_type_error (r, rtype); /* In [temp.inst]:
TREE_TYPE (r) = error_mark_node;
[t]he initialization (and any associated
side-effects) of a static data member does
not occur unless the static data member is
itself used in a way that requires the
definition of the static data member to
exist.
Therefore, we do not substitute into the
initialized for the static data member here. */
finish_static_data_member_decl
(r,
/*init=*/NULL_TREE,
/*init_const_expr_p=*/false,
/*asmspec_tree=*/NULL_TREE,
/*flags=*/0);
/* Instantiate members marked with attribute used. */
if (r != error_mark_node && DECL_PRESERVE_P (r))
mark_used (r);
}
else if (TREE_CODE (r) == FIELD_DECL)
{
/* Determine whether R has a valid type and can be
completed later. If R is invalid, then its type
is replaced by error_mark_node. */
tree rtype = TREE_TYPE (r);
if (can_complete_type_without_circularity (rtype))
complete_type (rtype);
if (!COMPLETE_TYPE_P (rtype))
{
cxx_incomplete_type_error (r, rtype);
TREE_TYPE (r) = error_mark_node;
}
} }
}
/* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE, /* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
such a thing will already have been added to the field such a thing will already have been added to the field
list by tsubst_enum in finish_member_declaration in the list by tsubst_enum in finish_member_declaration in the
CLASSTYPE_NESTED_UTDS case above. */ CLASSTYPE_NESTED_UTDS case above. */
if (!(TREE_CODE (r) == TYPE_DECL if (!(TREE_CODE (r) == TYPE_DECL
&& TREE_CODE (TREE_TYPE (r)) == ENUMERAL_TYPE && TREE_CODE (TREE_TYPE (r)) == ENUMERAL_TYPE
&& DECL_ARTIFICIAL (r))) && DECL_ARTIFICIAL (r)))
{ {
set_current_access_from_decl (r); set_current_access_from_decl (r);
finish_member_declaration (r); finish_member_declaration (r);
}
} }
} }
} }
...@@ -9367,7 +9406,8 @@ gen_elem_of_pack_expansion_instantiation (tree pattern, ...@@ -9367,7 +9406,8 @@ gen_elem_of_pack_expansion_instantiation (tree pattern,
argument_pack_element_is_expansion_p (arg_pack, index); argument_pack_element_is_expansion_p (arg_pack, index);
/* Select the Ith argument from the pack. */ /* Select the Ith argument from the pack. */
if (TREE_CODE (parm) == PARM_DECL) if (TREE_CODE (parm) == PARM_DECL
|| TREE_CODE (parm) == FIELD_DECL)
{ {
if (index == 0) if (index == 0)
{ {
...@@ -9481,6 +9521,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, ...@@ -9481,6 +9521,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
need_local_specializations = true; need_local_specializations = true;
} }
} }
else if (TREE_CODE (parm_pack) == FIELD_DECL)
arg_pack = tsubst_copy (parm_pack, args, complain, in_decl);
else else
{ {
int idx; int idx;
...@@ -9605,7 +9647,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, ...@@ -9605,7 +9647,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
{ {
tree parm = TREE_PURPOSE (pack); tree parm = TREE_PURPOSE (pack);
if (TREE_CODE (parm) == PARM_DECL) if (TREE_CODE (parm) == PARM_DECL
|| TREE_CODE (parm) == FIELD_DECL)
register_local_specialization (TREE_TYPE (pack), parm); register_local_specialization (TREE_TYPE (pack), parm);
else else
{ {
...@@ -10572,39 +10615,88 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -10572,39 +10615,88 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
case FIELD_DECL: case FIELD_DECL:
{ {
tree type; tree type = NULL_TREE;
tree vec = NULL_TREE;
tree expanded_types = NULL_TREE;
int len = 1;
r = copy_decl (t); if (PACK_EXPANSION_P (TREE_TYPE (t)))
type = tsubst (TREE_TYPE (t), args, complain, in_decl); {
if (type == error_mark_node) /* This field is a lambda capture pack. Return a TREE_VEC of
RETURN (error_mark_node); the expanded fields to instantiate_class_template_1 and
TREE_TYPE (r) = type; store them in the specializations hash table as a
cp_apply_type_quals_to_decl (cp_type_quals (type), r); NONTYPE_ARGUMENT_PACK so that tsubst_copy can find them. */
expanded_types = tsubst_pack_expansion (TREE_TYPE (t), args,
complain, in_decl);
if (TREE_CODE (expanded_types) == TREE_VEC)
{
len = TREE_VEC_LENGTH (expanded_types);
vec = make_tree_vec (len);
}
else
{
/* All we did was update the type. Make a note of that. */
type = expanded_types;
expanded_types = NULL_TREE;
}
}
if (DECL_C_BIT_FIELD (r)) for (int i = 0; i < len; ++i)
/* For bit-fields, DECL_INITIAL gives the number of bits. For
non-bit-fields DECL_INITIAL is a non-static data member
initializer, which gets deferred instantiation. */
DECL_INITIAL (r)
= tsubst_expr (DECL_INITIAL (t), args,
complain, in_decl,
/*integral_constant_expression_p=*/true);
else if (DECL_INITIAL (t))
{ {
/* Set up DECL_TEMPLATE_INFO so that we can get at the r = copy_decl (t);
NSDMI in perform_member_init. Still set DECL_INITIAL if (expanded_types)
so that we know there is one. */ {
DECL_INITIAL (r) = void_zero_node; type = TREE_VEC_ELT (expanded_types, i);
gcc_assert (DECL_LANG_SPECIFIC (r) == NULL); DECL_NAME (r)
retrofit_lang_decl (r); = make_ith_pack_parameter_name (DECL_NAME (r), i);
DECL_TEMPLATE_INFO (r) = build_template_info (t, args); }
else if (!type)
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node)
RETURN (error_mark_node);
TREE_TYPE (r) = type;
cp_apply_type_quals_to_decl (cp_type_quals (type), r);
if (DECL_C_BIT_FIELD (r))
/* For bit-fields, DECL_INITIAL gives the number of bits. For
non-bit-fields DECL_INITIAL is a non-static data member
initializer, which gets deferred instantiation. */
DECL_INITIAL (r)
= tsubst_expr (DECL_INITIAL (t), args,
complain, in_decl,
/*integral_constant_expression_p=*/true);
else if (DECL_INITIAL (t))
{
/* Set up DECL_TEMPLATE_INFO so that we can get at the
NSDMI in perform_member_init. Still set DECL_INITIAL
so that we know there is one. */
DECL_INITIAL (r) = void_zero_node;
gcc_assert (DECL_LANG_SPECIFIC (r) == NULL);
retrofit_lang_decl (r);
DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
}
/* We don't have to set DECL_CONTEXT here; it is set by
finish_member_declaration. */
DECL_CHAIN (r) = NULL_TREE;
apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
args, complain, in_decl);
if (vec)
TREE_VEC_ELT (vec, i) = r;
} }
/* We don't have to set DECL_CONTEXT here; it is set by
finish_member_declaration. */
DECL_CHAIN (r) = NULL_TREE;
apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0, if (vec)
args, complain, in_decl); {
r = vec;
tree pack = make_node (NONTYPE_ARGUMENT_PACK);
tree tpack = cxx_make_type (TYPE_ARGUMENT_PACK);
SET_ARGUMENT_PACK_ARGS (pack, vec);
SET_ARGUMENT_PACK_ARGS (tpack, expanded_types);
TREE_TYPE (pack) = tpack;
register_specialization (pack, t, args, false, 0);
}
} }
break; break;
...@@ -10753,14 +10845,14 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -10753,14 +10845,14 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
{ {
/* It may seem that this case cannot occur, since: /* It may seem that this case cannot occur, since:
typedef void f(); typedef void f();
void g() { f x; } void g() { f x; }
declares a function, not a variable. However: declares a function, not a variable. However:
typedef void f(); typedef void f();
template <typename T> void g() { T t; } template <typename T> void g() { T t; }
template void g<f>(); template void g<f>();
is an attempt to declare a variable with function is an attempt to declare a variable with function
type. */ type. */
...@@ -12261,6 +12353,23 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -12261,6 +12353,23 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return t; return t;
case FIELD_DECL: case FIELD_DECL:
if (PACK_EXPANSION_P (TREE_TYPE (t)))
{
/* Check for a local specialization set up by
tsubst_pack_expansion. */
tree r = retrieve_local_specialization (t);
if (r)
{
if (TREE_CODE (r) == ARGUMENT_PACK_SELECT)
r = ARGUMENT_PACK_SELECT_ARG (r);
return r;
}
/* Otherwise return the full NONTYPE_ARGUMENT_PACK that
tsubst_decl put in the hash table. */
return retrieve_specialization (t, args, 0);
}
if (DECL_CONTEXT (t)) if (DECL_CONTEXT (t))
{ {
tree ctx; tree ctx;
...@@ -13020,6 +13129,12 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, ...@@ -13020,6 +13129,12 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
else else
do_local_using_decl (decl, scope, name); do_local_using_decl (decl, scope, name);
} }
else if (DECL_PACK_P (decl))
{
/* Don't build up decls for a variadic capture proxy, we'll
instantiate the elements directly as needed. */
break;
}
else else
{ {
init = DECL_INITIAL (decl); init = DECL_INITIAL (decl);
...@@ -14585,6 +14700,14 @@ tsubst_copy_and_build (tree t, ...@@ -14585,6 +14700,14 @@ tsubst_copy_and_build (tree t,
case VAR_DECL: case VAR_DECL:
if (!args) if (!args)
RETURN (t); RETURN (t);
else if (DECL_PACK_P (t))
{
/* We don't build decls for an instantiation of a
variadic capture proxy, we instantiate the elements
when needed. */
gcc_assert (DECL_HAS_VALUE_EXPR_P (t));
return RECUR (DECL_VALUE_EXPR (t));
}
/* Fall through */ /* Fall through */
case PARM_DECL: case PARM_DECL:
......
...@@ -1604,6 +1604,9 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) ...@@ -1604,6 +1604,9 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
if (TREE_CODE (type) == REFERENCE_TYPE) if (TREE_CODE (type) == REFERENCE_TYPE)
/* Quals on the object don't matter. */; /* Quals on the object don't matter. */;
else if (PACK_EXPANSION_P (type))
/* Don't bother trying to represent this. */
type = NULL_TREE;
else else
{ {
/* Set the cv qualifiers. */ /* Set the cv qualifiers. */
......
// { dg-do run { target c++11 } }
int g() { return 0; }
template <class T, class... U>
int g(T t, U... u)
{
return t + g(u...);
}
template <class... T>
int f1(T... t)
{
return [t...] {
return g(t...);
}();
}
template <class... T>
int f2(T... t)
{
return [&t...] {
return g(t...);
}();
}
template <class... T>
int f3(T... t)
{
return [=] {
return g(t...);
}();
}
template <class... T>
int f4(T... t)
{
return [&] {
return g(t...);
}();
}
#define assert(E) do { if (!(E)) __builtin_abort(); } while(0)
int main()
{
assert (f1() == 0);
assert (f2() == 0);
assert (f3() == 0);
assert (f4() == 0);
assert (f1(42) == 42);
assert (f2(42) == 42);
assert (f3(42) == 42);
assert (f4(42) == 42);
assert (f1(1,2,3) == 6);
assert (f2(1,2,3) == 6);
assert (f3(1,2,3) == 6);
assert (f4(1,2,3) == 6);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment