C++ PATCH for c++/84520, ICE with generic lambda in NSDMI

Message ID CADzB+2mB4=dbBVLGC6mCgoDegiOUBUJTVcHsa5645ByLwrSrvQ@mail.gmail.com
State New
Headers show
Series
  • C++ PATCH for c++/84520, ICE with generic lambda in NSDMI
Related show

Commit Message

Jason Merrill Feb. 27, 2018, 2:33 a.m.
lambda_expr_this_capture assumes that we can find the fake 'this'
inserted while parsing an NSDMI, but it isn't there if we are
instantiating, rather than parsing, a generic lambda.

Tested x86_64-pc-linux-gnu, applying to trunk/7/6.
commit 9c64c953f0595e88cd911d488a415c8568934864
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Feb 26 18:01:05 2018 -0500

            PR c++/84520 - ICE with generic lambda in NSDMI.
    
            * lambda.c (lambda_expr_this_capture): Don't look for fake NSDMI
            'this' in a generic lambda instantiation.

Patch

diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 6a798266f12..3f77df037a2 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -758,11 +758,14 @@  lambda_expr_this_capture (tree lambda, bool add_capture_p)
                                     lambda_stack);
 
 	  if (LAMBDA_EXPR_EXTRA_SCOPE (tlambda)
+	      && !COMPLETE_TYPE_P (LAMBDA_EXPR_CLOSURE (tlambda))
 	      && TREE_CODE (LAMBDA_EXPR_EXTRA_SCOPE (tlambda)) == 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.  */
+		 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;
 	      gcc_checking_assert
 		(init && (TREE_TYPE (TREE_TYPE (init))
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-nsdmi1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-nsdmi1.C
new file mode 100644
index 00000000000..89ce519d812
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-nsdmi1.C
@@ -0,0 +1,8 @@ 
+// PR c++/84520
+// { dg-do compile { target c++14 } }
+
+struct A
+{
+  static void foo(int);
+  void (*f)(int) = [](auto i) { foo(i); };
+};