summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2017-09-28 19:39:38 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2017-09-28 19:39:38 +0000
commit6f20c78581397079216efbe5edfd1800b2fd5988 (patch)
treeb86cb1ba622a88cf4a14e1fd0e4b03bc38df3be7
parent153f22fa0edd3ff66c8a52be3870396db9262a31 (diff)
downloadgcc-6f20c78581397079216efbe5edfd1800b2fd5988.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@253265 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog16
-rw-r--r--gcc/cp/cp-tree.h10
-rw-r--r--gcc/cp/lambda.c36
-rw-r--r--gcc/cp/name-lookup.c2
-rw-r--r--gcc/cp/parser.c2
-rw-r--r--gcc/cp/pt.c13
-rw-r--r--gcc/cp/semantics.c23
7 files changed, 76 insertions, 26 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index eeea726afdb..2936f22a47e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,21 @@
2017-09-28 Jason Merrill <jason@redhat.com>
+ 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.
+
* call.c (build_special_member_call): Use the return value of
mark_lvalue_use.
* decl.c (compute_array_index_type): Likewise.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7c1c54c78b5..a6349019543 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2471,10 +2471,12 @@ struct GTY(()) lang_decl_min {
union lang_decl_u2 {
/* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is
THUNK_VIRTUAL_OFFSET.
+ In a VAR_DECL for which DECL_HAS_VALUE_EXPR_P holds,
+ this is DECL_CAPTURED_VARIABLE.
Otherwise this is DECL_ACCESS. */
tree GTY ((tag ("0"))) access;
- /* For VAR_DECL in function, this is DECL_DISCRIMINATOR. */
+ /* For TREE_STATIC VAR_DECL in function, this is DECL_DISCRIMINATOR. */
int GTY ((tag ("1"))) discriminator;
} GTY ((desc ("%0.u.base.u2sel"))) u2;
};
@@ -3240,6 +3242,10 @@ extern void decl_shadowed_for_var_insert (tree, tree);
(DECL_LANG_SPECIFIC (VAR_TEMPL_TYPE_FIELD_OR_FUNCTION_DECL_CHECK (NODE)) \
->u.min.template_info)
+/* For a lambda capture proxy, its captured variable. */
+#define DECL_CAPTURED_VARIABLE(NODE) \
+ (LANG_DECL_U2_CHECK (NODE, 0)->access)
+
/* For a VAR_DECL, indicates that the variable is actually a
non-static data member of anonymous union that has been promoted to
variable status. */
@@ -6793,7 +6799,7 @@ extern tree lambda_function (tree);
extern void apply_deduced_return_type (tree, tree);
extern tree add_capture (tree, tree, tree, bool, bool);
extern tree add_default_capture (tree, tree, tree);
-extern tree build_capture_proxy (tree);
+extern tree build_capture_proxy (tree, tree);
extern void insert_capture_proxy (tree);
extern void insert_pending_capture_proxies (void);
extern bool is_capture_proxy (tree);
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 695666abbe3..66d510e6818 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;
}
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index a3a124b9ce2..6763a5b9c68 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -5296,7 +5296,7 @@ qualify_lookup (tree val, int flags)
if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
return false;
/* Look through lambda things that we shouldn't be able to see. */
- if (is_lambda_ignored_entity (val))
+ if (!(flags & LOOKUP_HIDDEN) && is_lambda_ignored_entity (val))
return false;
return true;
}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index bb2a8774aa0..f22c2c091dc 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -10560,6 +10560,8 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
+ function_definition_after_declarator
+ ctor_initializer_opt_and_function_body */
{
+ local_specialization_stack s (lss_copy);
+
tree fco = lambda_function (lambda_expr);
tree body = start_lambda_function (fco, lambda_expr);
bool done = false;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f12ab2605d8..2bdac6de6c4 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15986,7 +15986,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
{
/* We're in tsubst_lambda_expr, we've already inserted a new
capture proxy, so look it up and register it. */
- tree inst = lookup_name (DECL_NAME (decl));
+ tree inst = lookup_name_real (DECL_NAME (decl), 0, 0,
+ /*block_p=*/true, 0, LOOKUP_HIDDEN);
gcc_assert (inst != decl && is_capture_proxy (inst));
register_local_specialization (inst, decl);
break;
@@ -16906,10 +16907,10 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (nested)
push_function_context ();
- tree body = start_lambda_function (fn, r);
-
local_specialization_stack s (lss_copy);
+ tree body = start_lambda_function (fn, r);
+
register_parameter_specializations (oldfn, fn);
tsubst_expr (DECL_SAVED_TREE (oldfn), args, complain, r,
@@ -18136,11 +18137,7 @@ tsubst_copy_and_build (tree t,
r = build_cxx_call (wrap, 0, NULL, tf_warning_or_error);
}
else if (outer_automatic_var_p (r))
- {
- r = process_outer_var_ref (r, complain);
- if (is_capture_proxy (r) && !DECL_PACK_P (t))
- register_local_specialization (r, t);
- }
+ r = process_outer_var_ref (r, complain);
if (TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE)
/* If the original type was a reference, we'll be wrapped in
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 3a3ae55aa44..4e87e47d9b3 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3303,16 +3303,19 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain)
if (parsing_nsdmi ())
containing_function = NULL_TREE;
- if (containing_function && DECL_TEMPLATE_INFO (context)
- && LAMBDA_FUNCTION_P (containing_function))
- {
- /* Check whether we've already built a proxy;
- insert_pending_capture_proxies doesn't update
- local_specializations. */
- tree d = lookup_name (DECL_NAME (decl));
- if (d && is_capture_proxy (d)
- && DECL_CONTEXT (d) == containing_function)
- return d;
+ if (containing_function && LAMBDA_FUNCTION_P (containing_function))
+ {
+ /* Check whether we've already built a proxy. */
+ tree d = retrieve_local_specialization (decl);
+ if (d && is_capture_proxy (d))
+ {
+ if (DECL_CONTEXT (d) == containing_function)
+ /* We already have an inner proxy. */
+ return d;
+ else
+ /* We need to capture an outer proxy. */
+ return process_outer_var_ref (d, complain);
+ }
}
/* If we are in a lambda function, we can move out until we hit