aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-09-30 13:54:37 -0400
committerJason Merrill <jason@gcc.gnu.org>2009-09-30 13:54:37 -0400
commit71d16049ff0e6a545263fc4e1295661ad0891e0c (patch)
tree80731115f2e9bf48973f1a566959902120924eed
parent1f063d1016c58854d377bea0db152694698f3694 (diff)
downloadgcc-71d16049ff0e6a545263fc4e1295661ad0891e0c.zip
gcc-71d16049ff0e6a545263fc4e1295661ad0891e0c.tar.gz
gcc-71d16049ff0e6a545263fc4e1295661ad0891e0c.tar.bz2
semantics.c (lambda_expr_this_capture): Fix default capture of explicit capture of 'this'.
* semantics.c (lambda_expr_this_capture): Fix default capture of explicit capture of 'this'. From-SVN: r152339
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/semantics.c35
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested.C13
3 files changed, 40 insertions, 13 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ae162d4..f617fb1 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
2009-09-30 Jason Merrill <jason@redhat.com>
+ * semantics.c (lambda_expr_this_capture): Fix default capture
+ of explicit capture of 'this'.
+
+2009-09-30 Jason Merrill <jason@redhat.com>
+
* parser.c (cp_parser_lambda_expression): Don't add __ to __this.
2009-09-30 Jason Merrill <jason@redhat.com>
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 6dec9f8..725bcc2 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5540,7 +5540,6 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
current_class_type = saved_class_type;
return member;
-
}
/* Return the capture pertaining to a use of 'this' in LAMBDA, in the form of an
@@ -5559,6 +5558,7 @@ lambda_expr_this_capture (tree lambda)
{
tree containing_function = TYPE_CONTEXT (TREE_TYPE (lambda));
tree lambda_stack = tree_cons (NULL_TREE, lambda, NULL_TREE);
+ tree init = NULL_TREE;
/* If we are in a lambda function, we can move out until we hit:
1. a non-lambda function,
@@ -5569,9 +5569,20 @@ lambda_expr_this_capture (tree lambda)
tree lambda
= CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (containing_function));
- if (LAMBDA_EXPR_THIS_CAPTURE (lambda)
- || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) == CPLD_NONE)
- break;
+ if (LAMBDA_EXPR_THIS_CAPTURE (lambda))
+ {
+ /* An outer lambda has already captured 'this'. */
+ tree cap = LAMBDA_EXPR_THIS_CAPTURE (lambda);
+ tree lthis
+ = cp_build_indirect_ref (DECL_ARGUMENTS (containing_function),
+ "", tf_warning_or_error);
+ init = finish_non_static_data_member (cap, lthis, NULL_TREE);
+ break;
+ }
+
+ if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) == CPLD_NONE)
+ /* An outer lambda won't let us capture 'this'. */
+ break;
lambda_stack = tree_cons (NULL_TREE,
lambda,
@@ -5580,15 +5591,15 @@ lambda_expr_this_capture (tree lambda)
containing_function = decl_function_context (containing_function);
}
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (containing_function))
- {
- this_capture = add_default_capture (lambda_stack,
- /*id=*/get_identifier ("__this"),
- /* First parameter is 'this'. */
- /*initializer=*/DECL_ARGUMENTS
- (containing_function));
- }
+ if (!init && DECL_NONSTATIC_MEMBER_FUNCTION_P (containing_function)
+ && !LAMBDA_FUNCTION_P (containing_function))
+ /* First parameter is 'this'. */
+ init = DECL_ARGUMENTS (containing_function);
+ if (init)
+ this_capture = add_default_capture (lambda_stack,
+ /*id=*/get_identifier ("__this"),
+ init);
}
if (!this_capture)
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested.C
index 1689865..538775a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested.C
@@ -3,6 +3,16 @@
#include <cassert>
+struct A {
+ int i;
+ A(): i(42) { }
+ int f() {
+ return [this]{
+ return [=]{ return i; }();
+ }();
+ }
+};
+
int main() {
int i = 1;
@@ -47,6 +57,7 @@ int main() {
assert(i == 4);
+ assert (A().f() == 42);
+
return 0;
}
-