aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/lambda.c30
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi9.C15
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 ();
+}