diff options
author | Jason Merrill <jason@redhat.com> | 2018-03-05 17:14:38 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2018-03-05 17:14:38 -0500 |
commit | 91e534b0d41cd1a91172f544f6f5bcdff47cc740 (patch) | |
tree | 4c17fd35553270c8bf48c90b5dfdab9b94519c51 | |
parent | 9a25c5ce6e2677ae33ba489bd18335332f5e2560 (diff) | |
download | gcc-91e534b0d41cd1a91172f544f6f5bcdff47cc740.zip gcc-91e534b0d41cd1a91172f544f6f5bcdff47cc740.tar.gz gcc-91e534b0d41cd1a91172f544f6f5bcdff47cc740.tar.bz2 |
PR c++/84708 - ICE with lambda in local class NSDMI.
* lambda.c (lambda_expr_this_capture): Handle local class NSDMI
context.
From-SVN: r258264
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/lambda.c | 30 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi9.C | 15 |
3 files changed, 39 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5e62b1c..3523b7e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2018-03-05 Jason Merrill <jason@redhat.com> + + PR c++/84708 - ICE with lambda in local class NSDMI. + * lambda.c (lambda_expr_this_capture): Handle local class NSDMI + context. + 2018-03-05 Jakub Jelinek <jakub@redhat.com> PR c++/84684 diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index 3f77df0..345b210 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -757,25 +757,31 @@ lambda_expr_this_capture (tree lambda, bool add_capture_p) tlambda, lambda_stack); - if (LAMBDA_EXPR_EXTRA_SCOPE (tlambda) - && !COMPLETE_TYPE_P (LAMBDA_EXPR_CLOSURE (tlambda)) - && TREE_CODE (LAMBDA_EXPR_EXTRA_SCOPE (tlambda)) == FIELD_DECL) + tree closure = LAMBDA_EXPR_CLOSURE (tlambda); + tree containing_function + = decl_function_context (TYPE_NAME (closure)); + + tree ex = LAMBDA_EXPR_EXTRA_SCOPE (tlambda); + if (ex && TREE_CODE (ex) == FIELD_DECL) { - /* 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. But if the closure is already complete, we're - in an instantiation of a generic lambda, and the fake 'this' - is gone. */ - init = scope_chain->x_current_class_ptr; + /* Lambda in an NSDMI. We don't have a function to look up + 'this' in, but we can find (or rebuild) the fake one from + inject_this_parameter. */ + if (!containing_function && !COMPLETE_TYPE_P (closure)) + /* If we're parsing a lambda in a non-local class, + we can find the fake 'this' in scope_chain. */ + init = scope_chain->x_current_class_ptr; + else + /* Otherwise it's either gone or buried in + function_context_stack, so make another. */ + init = build_this_parm (NULL_TREE, DECL_CONTEXT (ex), + TYPE_UNQUALIFIED); gcc_checking_assert (init && (TREE_TYPE (TREE_TYPE (init)) == current_nonlambda_class_type ())); break; } - 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; diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi9.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi9.C new file mode 100644 index 0000000..8f41d4e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi9.C @@ -0,0 +1,15 @@ +// PR c++/84708 +// { dg-do run { target c++11 } } + +int main() +{ + struct Z + { + int i; + int b = ([&] { return i; }()); + Z(int i): i(i) {} + } z (42); + + if (z.b != 42) + __builtin_abort (); +} |