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