aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/lambda.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2013-09-15 15:34:42 -0400
committerJason Merrill <jason@gcc.gnu.org>2013-09-15 15:34:42 -0400
commit2993d08a0f9053d6b434f550c489d2cc9af81c46 (patch)
tree1ea5c1ef411fbda7152061fe7ec9543ea81fc0b7 /gcc/cp/lambda.c
parent73f4e2d261705d356b2283ae1576e495b74e7992 (diff)
downloadgcc-2993d08a0f9053d6b434f550c489d2cc9af81c46.zip
gcc-2993d08a0f9053d6b434f550c489d2cc9af81c46.tar.gz
gcc-2993d08a0f9053d6b434f550c489d2cc9af81c46.tar.bz2
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
Diffstat (limited to 'gcc/cp/lambda.c')
-rw-r--r--gcc/cp/lambda.c56
1 files changed, 45 insertions, 11 deletions
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index bf75834..1af301d 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -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,