aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-06-17 16:08:01 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-06-17 16:08:01 -0400
commit61ca4737a85b646c6f4f28e5a49e4f89fa44106b (patch)
tree1cc558a7e679f551ed8af13589db5f793e8cd923 /gcc
parent7e7666aed8caa20d3351147e6875292ca27cf1d9 (diff)
downloadgcc-61ca4737a85b646c6f4f28e5a49e4f89fa44106b.zip
gcc-61ca4737a85b646c6f4f28e5a49e4f89fa44106b.tar.gz
gcc-61ca4737a85b646c6f4f28e5a49e4f89fa44106b.tar.bz2
re PR c++/43912 ([C++0x] lambda debug info does not describe captured variables)
PR c++/43912 Generate proxy VAR_DECLs for better lambda debug info. * cp-tree.h (FUNCTION_NEEDS_BODY_BLOCK): Add lambda operator(). (LAMBDA_EXPR_PENDING_PROXIES): New. (struct tree_lambda_expr): Add pending_proxies. * name-lookup.c (pushdecl_maybe_friend_1): Handle capture shadowing. (qualify_lookup): Use is_lambda_ignored_entity. * parser.c (cp_parser_lambda_expression): Don't adjust field names. Call insert_pending_capture_proxies. (cp_parser_lambda_introducer): Use this_identifier. (cp_parser_lambda_declarator_opt): Call the object parameter of the op() "__closure" instead of "this". (cp_parser_lambda_body): Call build_capture_proxy. * semantics.c (build_capture_proxy, is_lambda_ignored_entity): New. (insert_pending_capture_proxies, insert_capture_proxy): New. (is_normal_capture_proxy, is_capture_proxy): New. (add_capture): Add __ to field names here, return capture proxy. (add_default_capture): Use this_identifier, adjust to expect add_capture to return a capture proxy. (outer_lambda_capture_p, thisify_lambda_field): Remove. (finish_id_expression, lambda_expr_this_capture): Adjust. (build_lambda_expr): Initialize LAMBDA_EXPR_PENDING_PROXIES. * pt.c (tsubst_copy_and_build): Check that LAMBDA_EXPR_PENDING_PROXIES is null. From-SVN: r175158
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog25
-rw-r--r--gcc/cp/cp-tree.def2
-rw-r--r--gcc/cp/cp-tree.h14
-rw-r--r--gcc/cp/decl.c3
-rw-r--r--gcc/cp/name-lookup.c13
-rw-r--r--gcc/cp/parser.c32
-rw-r--r--gcc/cp/pt.c3
-rw-r--r--gcc/cp/semantics.c232
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/lambda1.C35
-rw-r--r--gcc/testsuite/g++.dg/warn/Wshadow-6.C16
11 files changed, 299 insertions, 81 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f84bc45..f3fca84 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,30 @@
2011-06-17 Jason Merrill <jason@redhat.com>
+ PR c++/43912
+ Generate proxy VAR_DECLs for better lambda debug info.
+ * cp-tree.h (FUNCTION_NEEDS_BODY_BLOCK): Add lambda operator().
+ (LAMBDA_EXPR_PENDING_PROXIES): New.
+ (struct tree_lambda_expr): Add pending_proxies.
+ * name-lookup.c (pushdecl_maybe_friend_1): Handle capture shadowing.
+ (qualify_lookup): Use is_lambda_ignored_entity.
+ * parser.c (cp_parser_lambda_expression): Don't adjust field names.
+ Call insert_pending_capture_proxies.
+ (cp_parser_lambda_introducer): Use this_identifier.
+ (cp_parser_lambda_declarator_opt): Call the object parameter
+ of the op() "__closure" instead of "this".
+ (cp_parser_lambda_body): Call build_capture_proxy.
+ * semantics.c (build_capture_proxy, is_lambda_ignored_entity): New.
+ (insert_pending_capture_proxies, insert_capture_proxy): New.
+ (is_normal_capture_proxy, is_capture_proxy): New.
+ (add_capture): Add __ to field names here, return capture proxy.
+ (add_default_capture): Use this_identifier, adjust to expect
+ add_capture to return a capture proxy.
+ (outer_lambda_capture_p, thisify_lambda_field): Remove.
+ (finish_id_expression, lambda_expr_this_capture): Adjust.
+ (build_lambda_expr): Initialize LAMBDA_EXPR_PENDING_PROXIES.
+ * pt.c (tsubst_copy_and_build): Check that LAMBDA_EXPR_PENDING_PROXIES
+ is null.
+
* name-lookup.c (pushdecl_maybe_friend_1): Do check for shadowing
of artificial locals.
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index ce11417..12c01cb 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -442,6 +442,8 @@ DEFTREECODE (TRAIT_EXPR, "trait_expr", tcc_exceptional, 0)
none.
LAMBDA_EXPR_CAPTURE_LIST holds the capture-list, including `this'.
LAMBDA_EXPR_THIS_CAPTURE goes straight to the capture of `this', if it exists.
+ LAMBDA_EXPR_PENDING_PROXIES is a vector of capture proxies which need to
+ be pushed once scope returns to the lambda.
LAMBDA_EXPR_MUTABLE_P signals whether this lambda was declared mutable.
LAMBDA_EXPR_RETURN_TYPE holds the return type, if it was specified. */
DEFTREECODE (LAMBDA_EXPR, "lambda_expr", tcc_exceptional, 0)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index cf1c592..2773e34de 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -268,7 +268,8 @@ typedef struct ptrmem_cst * ptrmem_cst_t;
#define BIND_EXPR_BODY_BLOCK(NODE) \
TREE_LANG_FLAG_3 (BIND_EXPR_CHECK (NODE))
#define FUNCTION_NEEDS_BODY_BLOCK(NODE) \
- (DECL_CONSTRUCTOR_P (NODE) || DECL_DESTRUCTOR_P (NODE))
+ (DECL_CONSTRUCTOR_P (NODE) || DECL_DESTRUCTOR_P (NODE) \
+ || LAMBDA_FUNCTION_P (NODE))
#define STATEMENT_LIST_NO_SCOPE(NODE) \
TREE_LANG_FLAG_0 (STATEMENT_LIST_CHECK (NODE))
@@ -661,6 +662,11 @@ enum cp_lambda_default_capture_mode_type {
#define LAMBDA_EXPR_DISCRIMINATOR(NODE) \
(((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator)
+/* During parsing of the lambda, a vector of capture proxies which need
+ to be pushed once we're done processing a nested lambda. */
+#define LAMBDA_EXPR_PENDING_PROXIES(NODE) \
+ (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->pending_proxies)
+
struct GTY (()) tree_lambda_expr
{
struct tree_typed typed;
@@ -668,6 +674,7 @@ struct GTY (()) tree_lambda_expr
tree this_capture;
tree return_type;
tree extra_scope;
+ VEC(tree,gc)* pending_proxies;
location_t locus;
enum cp_lambda_default_capture_mode_type default_capture_mode;
int discriminator;
@@ -5450,10 +5457,15 @@ extern tree lambda_function (tree);
extern void apply_lambda_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 void insert_pending_capture_proxies (void);
+extern bool is_capture_proxy (tree);
+extern bool is_normal_capture_proxy (tree);
extern void register_capture_members (tree);
extern tree lambda_expr_this_capture (tree);
extern tree nonlambda_method_basetype (void);
extern void maybe_add_lambda_conv_op (tree);
+extern bool is_lambda_ignored_entity (tree);
/* in tree.c */
extern int cp_tree_operand_length (const_tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 9f62ea3..59c4a4c 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13060,7 +13060,8 @@ finish_destructor_body (void)
/* Do the necessary processing for the beginning of a function body, which
in this case includes member-initializers, but not the catch clauses of
a function-try-block. Currently, this means opening a binding level
- for the member-initializers (in a ctor) and member cleanups (in a dtor). */
+ for the member-initializers (in a ctor), member cleanups (in a dtor),
+ and capture proxies (in a lambda operator()). */
tree
begin_function_body (void)
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 64a0f9a..953edd5 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -1089,6 +1089,10 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
if (TREE_CODE (oldlocal) == PARM_DECL)
warning_at (input_location, OPT_Wshadow,
"declaration of %q#D shadows a parameter", x);
+ else if (is_capture_proxy (oldlocal))
+ warning_at (input_location, OPT_Wshadow,
+ "declaration of %qD shadows a lambda capture",
+ x);
else
warning_at (input_location, OPT_Wshadow,
"declaration of %qD shadows a previous local",
@@ -4002,13 +4006,8 @@ qualify_lookup (tree val, int flags)
return true;
if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
return false;
- /* In unevaluated context, look past normal capture fields. */
- if (cp_unevaluated_operand && TREE_CODE (val) == FIELD_DECL
- && DECL_NORMAL_CAPTURE_P (val))
- return false;
- /* None of the lookups that use qualify_lookup want the op() from the
- lambda; they want the one from the enclosing class. */
- if (TREE_CODE (val) == FUNCTION_DECL && LAMBDA_FUNCTION_P (val))
+ /* Look through lambda things that we shouldn't be able to see. */
+ if (is_lambda_ignored_entity (val))
return false;
return true;
}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index a9cedcf..49aa35e 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7396,26 +7396,9 @@ cp_parser_lambda_expression (cp_parser* parser)
for (elt = LAMBDA_EXPR_CAPTURE_LIST (lambda_expr);
elt; elt = next)
{
- tree field = TREE_PURPOSE (elt);
- char *buf;
-
next = TREE_CHAIN (elt);
TREE_CHAIN (elt) = newlist;
newlist = elt;
-
- /* Also add __ to the beginning of the field name so that code
- outside the lambda body can't see the captured name. We could
- just remove the name entirely, but this is more useful for
- debugging. */
- if (field == LAMBDA_EXPR_THIS_CAPTURE (lambda_expr))
- /* The 'this' capture already starts with __. */
- continue;
-
- buf = (char *) alloca (IDENTIFIER_LENGTH (DECL_NAME (field)) + 3);
- buf[1] = buf[0] = '_';
- memcpy (buf + 2, IDENTIFIER_POINTER (DECL_NAME (field)),
- IDENTIFIER_LENGTH (DECL_NAME (field)) + 1);
- DECL_NAME (field) = get_identifier (buf);
}
LAMBDA_EXPR_CAPTURE_LIST (lambda_expr) = newlist;
}
@@ -7433,6 +7416,11 @@ cp_parser_lambda_expression (cp_parser* parser)
/* This field is only used during parsing of the lambda. */
LAMBDA_EXPR_THIS_CAPTURE (lambda_expr) = NULL_TREE;
+ /* This lambda shouldn't have any proxies left at this point. */
+ gcc_assert (LAMBDA_EXPR_PENDING_PROXIES (lambda_expr) == NULL);
+ /* And now that we're done, push proxies for an enclosing lambda. */
+ insert_pending_capture_proxies ();
+
if (ok)
return build_lambda_object (lambda_expr);
else
@@ -7499,7 +7487,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
{
cp_lexer_consume_token (parser->lexer);
add_capture (lambda_expr,
- /*id=*/get_identifier ("__this"),
+ /*id=*/this_identifier,
/*initializer=*/finish_this_expr(),
/*by_reference_p=*/false,
explicit_init_p);
@@ -7701,6 +7689,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
{
DECL_INITIALIZED_IN_CLASS_P (fco) = 1;
DECL_ARTIFICIAL (fco) = 1;
+ /* Give the object parameter a different name. */
+ DECL_NAME (DECL_ARGUMENTS (fco)) = get_identifier ("__closure");
}
finish_member_declaration (fco);
@@ -7735,6 +7725,7 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
tree body;
bool done = false;
tree compound_stmt;
+ tree cap;
/* Let the front end know that we are going to be defining this
function. */
@@ -7748,6 +7739,11 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
goto out;
+ /* Push the proxies for any explicit captures. */
+ for (cap = LAMBDA_EXPR_CAPTURE_LIST (lambda_expr); cap;
+ cap = TREE_CHAIN (cap))
+ build_capture_proxy (TREE_PURPOSE (cap));
+
compound_stmt = begin_compound_stmt (0);
/* 5.1.1.4 of the standard says:
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ca4f955..85f2749 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13500,7 +13500,8 @@ tsubst_copy_and_build (tree t,
= RECUR (LAMBDA_EXPR_CAPTURE_LIST (t));
LAMBDA_EXPR_EXTRA_SCOPE (r)
= RECUR (LAMBDA_EXPR_EXTRA_SCOPE (t));
- gcc_assert (LAMBDA_EXPR_THIS_CAPTURE (t) == NULL_TREE);
+ gcc_assert (LAMBDA_EXPR_THIS_CAPTURE (t) == NULL_TREE
+ && LAMBDA_EXPR_PENDING_PROXIES (t) == NULL);
/* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */
determine_visibility (TYPE_NAME (type));
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index a436623..76c1862 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -54,7 +54,6 @@ along with GCC; see the file COPYING3. If not see
static tree maybe_convert_cond (tree);
static tree finalize_nrv_r (tree *, int *, void *);
static tree capture_decltype (tree);
-static tree thisify_lambda_field (tree);
/* Deferred Access Checking Overview
@@ -2830,18 +2829,6 @@ outer_automatic_var_p (tree decl)
&& DECL_CONTEXT (decl) != current_function_decl);
}
-/* Returns true iff DECL is a capture field from a lambda that is not our
- immediate context. */
-
-static bool
-outer_lambda_capture_p (tree decl)
-{
- return (TREE_CODE (decl) == FIELD_DECL
- && LAMBDA_TYPE_P (DECL_CONTEXT (decl))
- && (!current_class_type
- || !DERIVED_FROM_P (DECL_CONTEXT (decl), current_class_type)));
-}
-
/* ID_EXPRESSION is a representation of parsed, but unprocessed,
id-expression. (See cp_parser_id_expression for details.) SCOPE,
if non-NULL, is the type or namespace used to explicitly qualify
@@ -2946,8 +2933,7 @@ finish_id_expression (tree id_expression,
/* Disallow uses of local variables from containing functions, except
within lambda-expressions. */
- if ((outer_automatic_var_p (decl)
- || outer_lambda_capture_p (decl))
+ if (outer_automatic_var_p (decl)
/* It's not a use (3.2) if we're in an unevaluated context. */
&& !cp_unevaluated_operand)
{
@@ -2967,13 +2953,6 @@ finish_id_expression (tree id_expression,
if (decl_constant_var_p (decl))
return integral_constant_value (decl);
- if (TYPE_P (context))
- {
- /* Implicit capture of an explicit capture. */
- context = lambda_function (context);
- initializer = thisify_lambda_field (decl);
- }
-
/* If we are in a lambda function, we can move out until we hit
1. the context,
2. a non-lambda function, or
@@ -8122,6 +8101,7 @@ build_lambda_expr (void)
LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) = CPLD_NONE;
LAMBDA_EXPR_CAPTURE_LIST (lambda) = NULL_TREE;
LAMBDA_EXPR_THIS_CAPTURE (lambda) = NULL_TREE;
+ LAMBDA_EXPR_PENDING_PROXIES (lambda) = NULL;
LAMBDA_EXPR_RETURN_TYPE (lambda) = NULL_TREE;
LAMBDA_EXPR_MUTABLE_P (lambda) = false;
return lambda;
@@ -8399,6 +8379,135 @@ capture_decltype (tree decl)
return type;
}
+/* Returns true iff DECL is a lambda capture proxy variable created by
+ build_capture_proxy. */
+
+bool
+is_capture_proxy (tree decl)
+{
+ return (TREE_CODE (decl) == VAR_DECL
+ && DECL_HAS_VALUE_EXPR_P (decl)
+ && !DECL_ANON_UNION_VAR_P (decl)
+ && LAMBDA_FUNCTION_P (DECL_CONTEXT (decl)));
+}
+
+/* Returns true iff DECL is a capture proxy for a normal capture
+ (i.e. without explicit initializer). */
+
+bool
+is_normal_capture_proxy (tree decl)
+{
+ tree val;
+
+ if (!is_capture_proxy (decl))
+ /* It's not a capture proxy. */
+ return false;
+
+ /* It is a capture proxy, is it a normal capture? */
+ val = DECL_VALUE_EXPR (decl);
+ gcc_assert (TREE_CODE (val) == COMPONENT_REF);
+ val = TREE_OPERAND (val, 1);
+ return DECL_NORMAL_CAPTURE_P (val);
+}
+
+/* VAR is a capture proxy created by build_capture_proxy; add it to the
+ current function, which is the operator() for the appropriate lambda. */
+
+static inline void
+insert_capture_proxy (tree var)
+{
+ cxx_scope *b;
+ int skip;
+ tree stmt_list;
+
+ /* Put the capture proxy in the extra body block so that it won't clash
+ with a later local variable. */
+ b = current_binding_level;
+ for (skip = 0; ; ++skip)
+ {
+ cxx_scope *n = b->level_chain;
+ if (n->kind == sk_function_parms)
+ break;
+ b = n;
+ }
+ pushdecl_with_scope (var, b, false);
+
+ /* And put a DECL_EXPR in the STATEMENT_LIST for the same block. */
+ var = build_stmt (DECL_SOURCE_LOCATION (var), DECL_EXPR, var);
+ stmt_list = VEC_index (tree, stmt_list_stack,
+ VEC_length (tree, stmt_list_stack) - 1 - skip);
+ gcc_assert (stmt_list);
+ append_to_statement_list_force (var, &stmt_list);
+}
+
+/* We've just finished processing a lambda; if the containing scope is also
+ a lambda, insert any capture proxies that were created while processing
+ the nested lambda. */
+
+void
+insert_pending_capture_proxies (void)
+{
+ tree lam;
+ VEC(tree,gc) *proxies;
+ unsigned i;
+
+ if (!current_function_decl || !LAMBDA_FUNCTION_P (current_function_decl))
+ return;
+
+ lam = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (current_function_decl));
+ proxies = LAMBDA_EXPR_PENDING_PROXIES (lam);
+ for (i = 0; i < VEC_length (tree, proxies); ++i)
+ {
+ tree var = VEC_index (tree, proxies, i);
+ insert_capture_proxy (var);
+ }
+ release_tree_vector (LAMBDA_EXPR_PENDING_PROXIES (lam));
+ LAMBDA_EXPR_PENDING_PROXIES (lam) = NULL;
+}
+
+/* MEMBER is a capture field in a lambda closure class. Now that we're
+ inside the operator(), build a placeholder var for future lookups and
+ debugging. */
+
+tree
+build_capture_proxy (tree member)
+{
+ tree var, object, fn, closure, name, lam;
+
+ closure = DECL_CONTEXT (member);
+ fn = lambda_function (closure);
+ lam = CLASSTYPE_LAMBDA_EXPR (closure);
+
+ /* The proxy variable forwards to the capture field. */
+ object = build_fold_indirect_ref (DECL_ARGUMENTS (fn));
+ object = finish_non_static_data_member (member, object, NULL_TREE);
+ if (REFERENCE_REF_P (object))
+ object = TREE_OPERAND (object, 0);
+
+ /* Remove the __ inserted by add_capture. */
+ name = get_identifier (IDENTIFIER_POINTER (DECL_NAME (member)) + 2);
+
+ var = build_decl (input_location, VAR_DECL, name, TREE_TYPE (object));
+ SET_DECL_VALUE_EXPR (var, object);
+ DECL_HAS_VALUE_EXPR_P (var) = 1;
+ DECL_ARTIFICIAL (var) = 1;
+ TREE_USED (var) = 1;
+ DECL_CONTEXT (var) = fn;
+
+ if (name == this_identifier)
+ {
+ gcc_assert (LAMBDA_EXPR_THIS_CAPTURE (lam) == member);
+ LAMBDA_EXPR_THIS_CAPTURE (lam) = var;
+ }
+
+ if (fn == current_function_decl)
+ insert_capture_proxy (var);
+ else
+ VEC_safe_push (tree, gc, LAMBDA_EXPR_PENDING_PROXIES (lam), var);
+
+ return var;
+}
+
/* From an ID and INITIALIZER, create a capture (by reference if
BY_REFERENCE_P is true), add it to the capture-list for LAMBDA,
and return it. */
@@ -8419,7 +8528,18 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
}
/* Make member variable. */
- member = build_lang_decl (FIELD_DECL, id, type);
+ {
+ /* Add __ to the beginning of the field name so that user code
+ won't find the field with name lookup. We can't just leave the name
+ unset because template instantiation uses the name to find
+ instantiated fields. */
+ char *buf = (char *) alloca (IDENTIFIER_LENGTH (id) + 3);
+ buf[1] = buf[0] = '_';
+ memcpy (buf + 2, IDENTIFIER_POINTER (id),
+ IDENTIFIER_LENGTH (id) + 1);
+ member = build_lang_decl (FIELD_DECL, get_identifier (buf), type);
+ }
+
if (!explicit_init_p)
/* Normal captures are invisible to name lookup but uses are replaced
with references to the capture field; we implement this by only
@@ -8435,14 +8555,18 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
LAMBDA_EXPR_CAPTURE_LIST (lambda)
= tree_cons (member, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda));
- if (id == get_identifier ("__this"))
+ if (id == this_identifier)
{
if (LAMBDA_EXPR_CAPTURES_THIS_P (lambda))
error ("already captured %<this%> in lambda expression");
LAMBDA_EXPR_THIS_CAPTURE (lambda) = member;
}
- return member;
+ if (TREE_TYPE (lambda))
+ return build_capture_proxy (member);
+ /* 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;
}
/* Register all the capture members on the list CAPTURES, which is the
@@ -8457,21 +8581,6 @@ void register_capture_members (tree captures)
}
}
-/* Given a FIELD_DECL decl belonging to a closure type, return a
- COMPONENT_REF of it relative to the 'this' parameter of the op() for
- that type. */
-
-static tree
-thisify_lambda_field (tree decl)
-{
- tree context = lambda_function (DECL_CONTEXT (decl));
- tree object = cp_build_indirect_ref (DECL_ARGUMENTS (context),
- RO_NULL,
- tf_warning_or_error);
- return finish_non_static_data_member (decl, object,
- /*qualifying_scope*/NULL_TREE);
-}
-
/* Similar to add_capture, except this works on a stack of nested lambdas.
BY_REFERENCE_P in this case is derived from the default capture mode.
Returns the capture for the lambda at the bottom of the stack. */
@@ -8479,9 +8588,9 @@ thisify_lambda_field (tree decl)
tree
add_default_capture (tree lambda_stack, tree id, tree initializer)
{
- bool this_capture_p = (id == get_identifier ("__this"));
+ bool this_capture_p = (id == this_identifier);
- tree member = NULL_TREE;
+ tree var = NULL_TREE;
tree saved_class_type = current_class_type;
@@ -8494,7 +8603,7 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
tree lambda = TREE_VALUE (node);
current_class_type = TREE_TYPE (lambda);
- member = add_capture (lambda,
+ var = add_capture (lambda,
id,
initializer,
/*by_reference_p=*/
@@ -8502,12 +8611,12 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
&& (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda)
== CPLD_REFERENCE)),
/*explicit_init_p=*/false);
- initializer = thisify_lambda_field (member);
+ initializer = convert_from_reference (var);
}
current_class_type = saved_class_type;
- return member;
+ return var;
}
/* Return the capture pertaining to a use of 'this' in LAMBDA, in the form of an
@@ -8540,8 +8649,7 @@ lambda_expr_this_capture (tree lambda)
if (LAMBDA_EXPR_THIS_CAPTURE (lambda))
{
/* An outer lambda has already captured 'this'. */
- tree cap = LAMBDA_EXPR_THIS_CAPTURE (lambda);
- init = thisify_lambda_field (cap);
+ init = LAMBDA_EXPR_THIS_CAPTURE (lambda);
break;
}
@@ -8563,7 +8671,7 @@ lambda_expr_this_capture (tree lambda)
if (init)
this_capture = add_default_capture (lambda_stack,
- /*id=*/get_identifier ("__this"),
+ /*id=*/this_identifier,
init);
}
@@ -8577,9 +8685,7 @@ lambda_expr_this_capture (tree lambda)
/* To make sure that current_class_ref is for the lambda. */
gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)) == TREE_TYPE (lambda));
- result = finish_non_static_data_member (this_capture,
- NULL_TREE,
- /*qualifying_scope=*/NULL_TREE);
+ result = this_capture;
/* If 'this' is captured, each use of 'this' is transformed into an
access to the corresponding unnamed data member of the closure
@@ -8752,4 +8858,28 @@ maybe_add_lambda_conv_op (tree type)
if (nested)
pop_function_context ();
}
+
+/* Returns true iff VAL is a lambda-related declaration which should
+ be ignored by unqualified lookup. */
+
+bool
+is_lambda_ignored_entity (tree val)
+{
+ /* In unevaluated context, look past normal capture proxies. */
+ if (cp_unevaluated_operand && is_normal_capture_proxy (val))
+ return true;
+
+ /* Always ignore lambda fields, their names are only for debugging. */
+ if (TREE_CODE (val) == FIELD_DECL
+ && CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (val)))
+ return true;
+
+ /* None of the lookups that use qualify_lookup want the op() from the
+ lambda; they want the one from the enclosing class. */
+ if (TREE_CODE (val) == FUNCTION_DECL && LAMBDA_FUNCTION_P (val))
+ return true;
+
+ return false;
+}
+
#include "gt-cp-semantics.h"
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 1adce47..805c5b1 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-06-17 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/debug/dwarf2/lambda1.C: New.
+ * g++.dg/warn/Wshadow-6.C: Adjust.
+
2011-06-17 Janus Weil <janus@gcc.gnu.org>
PR fortran/48699
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/lambda1.C b/gcc/testsuite/g++.dg/debug/dwarf2/lambda1.C
new file mode 100644
index 0000000..ee24eca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/lambda1.C
@@ -0,0 +1,35 @@
+// PR c++/43912
+// { dg-options "-g -std=c++0x -dA -fno-merge-debug-strings -gno-strict-dwarf" }
+
+// Check for the local alias variables that point to the members of the closure.
+// { dg-final { scan-assembler-times "DW_TAG_variable\[^.\]*\.ascii \"j.0\"" 4 } }
+// { dg-final { scan-assembler-times "DW_TAG_variable\[^.\]*\.ascii \"this.0\"" 2 } }
+
+struct A
+{
+ int i;
+ int f()
+ {
+ int j;
+ [&]() { j = i; }();
+ return j;
+ }
+};
+
+template <class T>
+struct B
+{
+ int i;
+ int f()
+ {
+ int j;
+ [&]() { j = i; }();
+ return j;
+ }
+};
+
+int main()
+{
+ A().f();
+ B<int>().f();
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wshadow-6.C b/gcc/testsuite/g++.dg/warn/Wshadow-6.C
index 9b13e3a..fdc37df 100644
--- a/gcc/testsuite/g++.dg/warn/Wshadow-6.C
+++ b/gcc/testsuite/g++.dg/warn/Wshadow-6.C
@@ -33,7 +33,19 @@ void f2(struct S i, int j) {
void f3(int i) {
[=]{
- int j = i;
- int i; // { dg-warning "shadows a member of" }
+ int j = i; // { dg-warning "shadowed declaration" }
+ int i; // { dg-warning "shadows a lambda capture" }
+ i = 1;
};
}
+
+template <class T>
+void f4(int i) {
+ [=]{
+ int j = i; // { dg-warning "shadowed declaration" }
+ int i; // { dg-warning "shadows a lambda capture" }
+ i = 1;
+ };
+}
+
+template void f4<int>(int);