aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/lambda.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2017-09-28 15:39:38 -0400
committerJason Merrill <jason@gcc.gnu.org>2017-09-28 15:39:38 -0400
commit5c263e84ab7e5df28a9055ae533c2d305f4b7b3d (patch)
treeb86cb1ba622a88cf4a14e1fd0e4b03bc38df3be7 /gcc/cp/lambda.c
parent697a7a575de01835b3941e6b6d25b940033301d5 (diff)
downloadgcc-5c263e84ab7e5df28a9055ae533c2d305f4b7b3d.zip
gcc-5c263e84ab7e5df28a9055ae533c2d305f4b7b3d.tar.gz
gcc-5c263e84ab7e5df28a9055ae533c2d305f4b7b3d.tar.bz2
Use local_specializations to find capture proxies.
* cp-tree.h (DECL_CAPTURED_VARIABLE): New. * lambda.c (build_capture_proxy): Set it. (add_capture): Pass initializer to build_capture_proxy. (start_lambda_function): Likewise. (insert_capture_proxy): Use register_local_specialization. (is_lambda_ignored_entity): Always ignore proxies. * name-lookup.c (qualify_lookup): Don't check is_lambda_ignored_entity if LOOKUP_HIDDEN is set. * semantics.c (process_outer_var_ref): Use retrieve_local_specialization. * parser.c (cp_parser_lambda_body): Push local_specializations. * pt.c (tsubst_expr): Pass LOOKUP_HIDDEN when looking for a proxy. (tsubst_lambda_expr): Push local_specializations sooner. (tsubst_copy_and_build): Don't register_local_specialization. From-SVN: r253265
Diffstat (limited to 'gcc/cp/lambda.c')
-rw-r--r--gcc/cp/lambda.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 695666a..66d510e 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -296,6 +296,9 @@ is_normal_capture_proxy (tree decl)
void
insert_capture_proxy (tree var)
{
+ if (is_normal_capture_proxy (var))
+ register_local_specialization (var, DECL_CAPTURED_VARIABLE (var));
+
/* Put the capture proxy in the extra body block so that it won't clash
with a later local variable. */
pushdecl_outermost_localscope (var);
@@ -364,7 +367,7 @@ lambda_proxy_type (tree ref)
debugging. */
tree
-build_capture_proxy (tree member)
+build_capture_proxy (tree member, tree init)
{
tree var, object, fn, closure, name, lam, type;
@@ -414,6 +417,29 @@ build_capture_proxy (tree member)
TREE_USED (var) = 1;
DECL_CONTEXT (var) = fn;
+ if (DECL_NORMAL_CAPTURE_P (member))
+ {
+ if (DECL_VLA_CAPTURE_P (member))
+ {
+ init = CONSTRUCTOR_ELT (init, 0)->value;
+ init = TREE_OPERAND (init, 0); // Strip ADDR_EXPR.
+ init = TREE_OPERAND (init, 0); // Strip ARRAY_REF.
+ }
+ else
+ {
+ if (PACK_EXPANSION_P (init))
+ init = PACK_EXPANSION_PATTERN (init);
+ if (TREE_CODE (init) == INDIRECT_REF)
+ init = TREE_OPERAND (init, 0);
+ STRIP_NOPS (init);
+ }
+ gcc_assert (VAR_P (init) || TREE_CODE (init) == PARM_DECL);
+ while (is_normal_capture_proxy (init))
+ init = DECL_CAPTURED_VARIABLE (init);
+ retrofit_lang_decl (var);
+ DECL_CAPTURED_VARIABLE (var) = init;
+ }
+
if (name == this_identifier)
{
gcc_assert (LAMBDA_EXPR_THIS_CAPTURE (lam) == member);
@@ -609,7 +635,7 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
= tree_cons (listmem, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda));
if (LAMBDA_EXPR_CLOSURE (lambda))
- return build_capture_proxy (member);
+ return build_capture_proxy (member, initializer);
/* For explicit captures we haven't started the function yet, so we wait
and build the proxy from cp_parser_lambda_body. */
return NULL_TREE;
@@ -1243,8 +1269,8 @@ lambda_static_thunk_p (tree fn)
bool
is_lambda_ignored_entity (tree val)
{
- /* In unevaluated context, look past normal capture proxies. */
- if (cp_unevaluated_operand && is_normal_capture_proxy (val))
+ /* Look past normal capture proxies. */
+ if (is_normal_capture_proxy (val))
return true;
/* Always ignore lambda fields, their names are only for debugging. */
@@ -1325,7 +1351,7 @@ start_lambda_function (tree fco, tree lambda_expr)
/* Push the proxies for any explicit captures. */
for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (lambda_expr); cap;
cap = TREE_CHAIN (cap))
- build_capture_proxy (TREE_PURPOSE (cap));
+ build_capture_proxy (TREE_PURPOSE (cap), TREE_VALUE (cap));
return body;
}