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>
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
* cp-tree.h (DECL_PACK_P): Replace FUNCTION_PARAMETER_PACK_P.
* cxx-pretty-print.c (direct_declarator): Adjust.
......
......@@ -215,7 +215,8 @@ lambda_capture_field_type (tree expr, bool explicit_init_p)
}
else
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);
DECLTYPE_TYPE_EXPR (type) = expr;
......@@ -320,15 +321,21 @@ tree
lambda_proxy_type (tree ref)
{
tree type;
if (ref == error_mark_node)
return error_mark_node;
if (REFERENCE_REF_P (ref))
ref = TREE_OPERAND (ref, 0);
gcc_assert (TREE_CODE (ref) == COMPONENT_REF);
type = TREE_TYPE (ref);
if (type && !WILDCARD_TYPE_P (non_reference (type)))
return type;
type = cxx_make_type (DECLTYPE_TYPE);
DECLTYPE_TYPE_EXPR (type) = ref;
DECLTYPE_FOR_LAMBDA_PROXY (type) = true;
SET_TYPE_STRUCTURAL_EQUALITY (type);
if (!type || WILDCARD_TYPE_P (non_reference (type)))
{
type = cxx_make_type (DECLTYPE_TYPE);
DECLTYPE_TYPE_EXPR (type) = ref;
DECLTYPE_FOR_LAMBDA_PROXY (type) = true;
SET_TYPE_STRUCTURAL_EQUALITY (type);
}
if (DECL_PACK_P (TREE_OPERAND (ref, 1)))
type = make_pack_expansion (type);
return type;
}
......@@ -341,6 +348,9 @@ build_capture_proxy (tree member)
{
tree var, object, fn, closure, name, lam, type;
if (PACK_EXPANSION_P (member))
member = PACK_EXPANSION_PATTERN (member);
closure = DECL_CONTEXT (member);
fn = lambda_function (closure);
lam = CLASSTYPE_LAMBDA_EXPR (closure);
......@@ -422,12 +432,20 @@ vla_capture_type (tree array_type)
and return it. */
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)
{
char *buf;
tree type, member, name;
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)
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,
IDENTIFIER_MARKED (name) = true;
}
if (variadic)
type = make_pack_expansion (type);
/* Make member variable. */
member = build_decl (input_location, FIELD_DECL, name, type);
DECL_VLA_CAPTURE_P (member) = vla;
......@@ -518,8 +539,14 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
&& current_class_type == LAMBDA_EXPR_CLOSURE (lambda))
finish_member_declaration (member);
tree listmem = member;
if (variadic)
{
listmem = make_pack_expansion (member);
initializer = orig_init;
}
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))
return build_capture_proxy (member);
......@@ -538,9 +565,14 @@ register_capture_members (tree captures)
return;
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. */
IDENTIFIER_MARKED (DECL_NAME (TREE_PURPOSE (captures))) = false;
finish_member_declaration (TREE_PURPOSE (captures));
IDENTIFIER_MARKED (DECL_NAME (field)) = false;
finish_member_declaration (field);
}
/* 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)
tree lambda = TREE_VALUE (node);
current_class_type = LAMBDA_EXPR_CLOSURE (lambda);
if (DECL_PACK_P (initializer))
initializer = make_pack_expansion (initializer);
var = add_capture (lambda,
id,
initializer,
......
......@@ -8753,6 +8753,14 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
/*template_arg_p=*/false,
&error_msg,
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
......
......@@ -1604,6 +1604,9 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
if (TREE_CODE (type) == REFERENCE_TYPE)
/* Quals on the object don't matter. */;
else if (PACK_EXPANSION_P (type))
/* Don't bother trying to represent this. */
type = NULL_TREE;
else
{
/* 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