From 19030d779a0d27dbdf3f774a15137cec8f4a1550 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 10 Feb 2010 21:12:53 -0500 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 10 ++++++++++ gcc/cp/cp-tree.h | 1 + gcc/cp/parser.c | 8 ++++++-- gcc/cp/semantics.c | 22 +++++++++++++++++----- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7a6e78a20cc..f42f59e5ce6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2010-02-10 Jason Merrill + + 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 PR c++/41896 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 27c820b8ed1..f32c6e86e5c 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 5256883565f..690f2c05eb0 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 796b789199b..985e2c0f464 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. */ -- 2.30.2