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;
+}