aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2013-03-04 12:12:32 -0500
committerJason Merrill <jason@gcc.gnu.org>2013-03-04 12:12:32 -0500
commit4b16f9c8759e30a946ef32a79de671ed6460f2bb (patch)
treef219827cc3d7fcd6a15fc7a47f06fb52d179ad5c
parent0388c91350e82bf7ad3738566b7d084a3e5e5691 (diff)
downloadgcc-4b16f9c8759e30a946ef32a79de671ed6460f2bb.zip
gcc-4b16f9c8759e30a946ef32a79de671ed6460f2bb.tar.gz
gcc-4b16f9c8759e30a946ef32a79de671ed6460f2bb.tar.bz2
re PR c++/56464 ([C++11] Crashes when using implicit this in a lambda capture in member initializer)
PR c++/56464 PR c++/54383 * semantics.c (lambda_expr_this_capture): Handle NSDMI and non-class scopes. From-SVN: r196437
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/semantics.c63
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi1.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this10.C4
4 files changed, 63 insertions, 21 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index eb030f1..8243e67 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2013-03-04 Jason Merrill <jason@redhat.com>
+
+ PR c++/56464
+ PR c++/54383
+ * semantics.c (lambda_expr_this_capture): Handle NSDMI
+ and non-class scopes.
+
2013-03-01 Paolo Carlini <paolo.carlini@oracle.com>
* decl.c (grokdeclarator): Remove dead code.
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 8038aa2..ab3d16e 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -9442,41 +9442,62 @@ lambda_expr_this_capture (tree lambda)
if (!this_capture
&& LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE)
{
- tree containing_function = TYPE_CONTEXT (LAMBDA_EXPR_CLOSURE (lambda));
- tree lambda_stack = tree_cons (NULL_TREE, lambda, NULL_TREE);
+ tree lambda_stack = 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,
+ 1. a non-lambda function or NSDMI,
2. a lambda function capturing 'this', or
3. a non-default capturing lambda function. */
- while (LAMBDA_FUNCTION_P (containing_function))
- {
- tree lambda
- = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (containing_function));
+ for (tree tlambda = lambda; ;)
+ {
+ lambda_stack = tree_cons (NULL_TREE,
+ tlambda,
+ lambda_stack);
- if (LAMBDA_EXPR_THIS_CAPTURE (lambda))
+ if (LAMBDA_EXPR_EXTRA_SCOPE (tlambda)
+ && TREE_CODE (LAMBDA_EXPR_EXTRA_SCOPE (tlambda)) == FIELD_DECL)
{
- /* An outer lambda has already captured 'this'. */
- init = LAMBDA_EXPR_THIS_CAPTURE (lambda);
+ /* In an NSDMI, we don't have a function to look up the decl in,
+ but the fake 'this' pointer that we're using for parsing is
+ in scope_chain. */
+ init = scope_chain->x_current_class_ptr;
+ gcc_checking_assert
+ (init && (TREE_TYPE (TREE_TYPE (init))
+ == current_nonlambda_class_type ()));
break;
}
- if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) == CPLD_NONE)
- /* An outer lambda won't let us capture 'this'. */
+ tree closure_decl = TYPE_NAME (LAMBDA_EXPR_CLOSURE (tlambda));
+ tree containing_function = decl_function_context (closure_decl);
+
+ if (containing_function == NULL_TREE)
+ /* We ran out of scopes; there's no 'this' to capture. */
break;
- lambda_stack = tree_cons (NULL_TREE,
- lambda,
- lambda_stack);
+ if (!LAMBDA_FUNCTION_P (containing_function))
+ {
+ /* We found a non-lambda function. */
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (containing_function))
+ /* First parameter is 'this'. */
+ init = DECL_ARGUMENTS (containing_function);
+ break;
+ }
- containing_function = decl_function_context (containing_function);
- }
+ tlambda
+ = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (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 (LAMBDA_EXPR_THIS_CAPTURE (tlambda))
+ {
+ /* An outer lambda has already captured 'this'. */
+ init = LAMBDA_EXPR_THIS_CAPTURE (tlambda);
+ break;
+ }
+
+ if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (tlambda) == CPLD_NONE)
+ /* An outer lambda won't let us capture 'this'. */
+ break;
+ }
if (init)
this_capture = add_default_capture (lambda_stack,
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi1.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi1.C
new file mode 100644
index 0000000..94dc254
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi1.C
@@ -0,0 +1,10 @@
+// PR c++/56464
+// { dg-do run { target c++11 } }
+
+struct bug { bug*a = [&]{ return [=]{return this;}(); }(); };
+int main()
+{
+ bug b;
+ if (b.a != &b)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this10.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this10.C
new file mode 100644
index 0000000..b4b8e72
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this10.C
@@ -0,0 +1,4 @@
+// PR c++/54383
+// { dg-do compile { target c++11 } }
+
+auto foo = [&](int a) { return a > this->b; }; // { dg-error "this" }