When instantiating a template we end up with a rather strange binding hierarchy -- the innermost binding is the template and the next one is the instantiation. Anyway, the upshot is we end up trying to push a tsubst'd lambda into the template itself and die because that's marked as a complete type. All somewhat suspicious.

However, there as a 'scope == ts_lambda' escape on that check, and I'd removed it because it seemed unneeded. Sadly not. As we now never pass ts_lambda into do_pushtag, we have to inspect the type being pushed to determine this check. This gets us back to the older behaviour, but at least we push into the instantiation, not the template because of changes I made earlier.

nathan
--
Nathan Sidwell
2018-03-21  Nathan Sidwell  <nat...@acm.org>

	PR c++/84804
	* name-lookup.c (do_pushtag): Permit lambdas to be pushed into
	complete classes.


	PR c++/84804
	* g++.dg/lookup/pr84804.C: New.

Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c	(revision 258716)
+++ cp/name-lookup.c	(working copy)
@@ -6436,7 +6436,8 @@ do_pushtag (tree name, tree type, tag_sc
 
       if (b->kind == sk_class)
 	{
-	  if (!TYPE_BEING_DEFINED (current_class_type))
+	  if (!TYPE_BEING_DEFINED (current_class_type)
+	      && !LAMBDA_TYPE_P (type))
 	    return error_mark_node;
 
 	  if (!PROCESSING_REAL_TEMPLATE_DECL_P ())
Index: testsuite/g++.dg/lookup/pr84804.C
===================================================================
--- testsuite/g++.dg/lookup/pr84804.C	(revision 0)
+++ testsuite/g++.dg/lookup/pr84804.C	(working copy)
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+// PR c++/84804 ICE instantiating friend with default arg containing a lambda
+template<int> struct A
+{
+  // Note, instantiation injects this into ::, so there can only be one!
+  friend void foo(int i = []{ return 0;}()) {}
+};
+
+void bar()
+{
+  A<0> x;
+}

Reply via email to