aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-02-10 21:12:53 -0500
committerJason Merrill <jason@gcc.gnu.org>2010-02-10 21:12:53 -0500
commit19030d779a0d27dbdf3f774a15137cec8f4a1550 (patch)
treec026a8558e03de540d0342d079d43fa8908967e5 /gcc/cp
parent94d7ad5fa7705d68d6c05207a871397d9ec2a6ee (diff)
downloadgcc-19030d779a0d27dbdf3f774a15137cec8f4a1550.zip
gcc-19030d779a0d27dbdf3f774a15137cec8f4a1550.tar.gz
gcc-19030d779a0d27dbdf3f774a15137cec8f4a1550.tar.bz2
re PR c++/41896 ([c++0x] Segfault because of a nested lambda function)
PR c++/41896 * semantics.c (outer_lambda_capture_p): Revert. (add_capture): Only finish_member_declaration if we're in the lambda class. (register_capture_members): New. * cp-tree.h: Declare it. * parser.c (cp_parser_lambda_expression): Call it. From-SVN: r156678
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/parser.c8
-rw-r--r--gcc/cp/semantics.c22
4 files changed, 34 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7a6e78a..f42f59e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,6 +1,16 @@
2010-02-10 Jason Merrill <jason@redhat.com>
PR c++/41896
+ * semantics.c (outer_lambda_capture_p): Revert.
+ (add_capture): Only finish_member_declaration if
+ we're in the lambda class.
+ (register_capture_members): New.
+ * cp-tree.h: Declare it.
+ * parser.c (cp_parser_lambda_expression): Call it.
+
+2010-02-10 Jason Merrill <jason@redhat.com>
+
+ PR c++/41896
* semantics.c (outer_lambda_capture_p): Use current_function_decl
instead of current_class_type.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 27c820b..f32c6e8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5193,6 +5193,7 @@ 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 void register_capture_members (tree);
extern tree lambda_expr_this_capture (tree);
extern void maybe_add_lambda_conv_op (tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 5256883..690f2c0 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7072,6 +7072,8 @@ cp_parser_lambda_expression (cp_parser* parser)
it now. */
push_deferring_access_checks (dk_no_deferred);
+ cp_parser_lambda_introducer (parser, lambda_expr);
+
type = begin_lambda_type (lambda_expr);
record_lambda_scope (lambda_expr);
@@ -7079,6 +7081,10 @@ cp_parser_lambda_expression (cp_parser* parser)
/* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */
determine_visibility (TYPE_NAME (type));
+ /* Now that we've started the type, add the capture fields for any
+ explicit captures. */
+ register_capture_members (LAMBDA_EXPR_CAPTURE_LIST (lambda_expr));
+
{
/* Inside the class, surrounding template-parameter-lists do not apply. */
unsigned int saved_num_template_parameter_lists
@@ -7086,8 +7092,6 @@ cp_parser_lambda_expression (cp_parser* parser)
parser->num_template_parameter_lists = 0;
- cp_parser_lambda_introducer (parser, lambda_expr);
-
/* By virtue of defining a local class, a lambda expression has access to
the private variables of enclosing classes. */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 796b789..985e2c0 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2714,9 +2714,8 @@ outer_lambda_capture_p (tree decl)
{
return (TREE_CODE (decl) == FIELD_DECL
&& LAMBDA_TYPE_P (DECL_CONTEXT (decl))
- /* Using current_class_type here causes problems with uses in a
- nested lambda-introducer; see 41896. */
- && DECL_CONTEXT (current_function_decl) != DECL_CONTEXT (decl));
+ && (!current_class_type
+ || !DERIVED_FROM_P (DECL_CONTEXT (decl), current_class_type)));
}
/* ID_EXPRESSION is a representation of parsed, but unprocessed,
@@ -5690,8 +5689,9 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
always visible. */
DECL_NORMAL_CAPTURE_P (member) = true;
- /* Add it to the appropriate closure class. */
- finish_member_declaration (member);
+ /* Add it to the appropriate closure class if we've started it. */
+ if (current_class_type && current_class_type == TREE_TYPE (lambda))
+ finish_member_declaration (member);
LAMBDA_EXPR_CAPTURE_LIST (lambda)
= tree_cons (member, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda));
@@ -5706,6 +5706,18 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
return member;
}
+/* Register all the capture members on the list CAPTURES, which is the
+ LAMBDA_EXPR_CAPTURE_LIST for the lambda after the introducer. */
+
+void register_capture_members (tree captures)
+{
+ if (captures)
+ {
+ register_capture_members (TREE_CHAIN (captures));
+ finish_member_declaration (TREE_PURPOSE (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. */