diff options
author | Jason Merrill <jason@redhat.com> | 2013-03-04 12:12:32 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2013-03-04 12:12:32 -0500 |
commit | 4b16f9c8759e30a946ef32a79de671ed6460f2bb (patch) | |
tree | f219827cc3d7fcd6a15fc7a47f06fb52d179ad5c | |
parent | 0388c91350e82bf7ad3738566b7d084a3e5e5691 (diff) | |
download | gcc-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/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 63 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi1.C | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this10.C | 4 |
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" } |