diff mbox

[C++] PR c++/79264 another lambda capture

Message ID c0188eef-c460-42b2-0a24-0762b016202c@acm.org
State New
Headers show

Commit Message

Nathan Sidwell Jan. 31, 2017, 3:13 p.m. UTC
PR 79264 is an ICE with concepts and lambdas, but underneath is another 
case of failing to notice this capture.

My fix for 61636 had ignored the 'g<whatever> ()' case of calling a 
template member fn.

This patch adds the smarts for that, and also an assert in 
finish_member_declaration that we're inserting into being-defined 
classes.  The assert in name-lookup used to be good enough, but not anymore.

Committed to trunk.

nathan
diff mbox

Patch

2017-01-31  Nathan Sidwell  <nathan@acm.org>

	PR c++/79264
	* lambda.c (maybe_generic_this_capture): Deal with template-id-exprs.
	* semantics.c (finish_member_declaration): Assert class is being
	defined.

	PR c++/79264
	* g++.dg/cpp1y/pr61636-1.C: Augment.

Index: cp/lambda.c
===================================================================
--- cp/lambda.c	(revision 245028)
+++ cp/lambda.c	(working copy)
@@ -849,13 +849,21 @@  maybe_generic_this_capture (tree object,
 	   interest.  */
 	if (BASELINK_P (fns))
 	  fns = BASELINK_FUNCTIONS (fns);
+	bool id_expr = TREE_CODE (fns) == TEMPLATE_ID_EXPR;
+	if (id_expr)
+	  fns = TREE_OPERAND (fns, 0);
 	for (; fns; fns = OVL_NEXT (fns))
-	  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (OVL_CURRENT (fns)))
-	    {
-	      /* Found a non-static member.  Capture this.  */
-	      lambda_expr_this_capture (lam, true);
-	      break;
-	    }
+	  {
+	    tree fn = OVL_CURRENT (fns);
+
+	    if ((!id_expr || TREE_CODE (fn) == TEMPLATE_DECL)
+		&& DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+	      {
+		/* Found a non-static member.  Capture this.  */
+		lambda_expr_this_capture (lam, true);
+		break;
+	      }
+	  }
       }
 }
 
Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 245028)
+++ cp/semantics.c	(working copy)
@@ -2962,6 +2962,12 @@  finish_member_declaration (tree decl)
   /* We should see only one DECL at a time.  */
   gcc_assert (DECL_CHAIN (decl) == NULL_TREE);
 
+  /* Don't add decls after definition.  */
+  gcc_assert (TYPE_BEING_DEFINED (current_class_type)
+	      /* We can add lambda types when late parsing default
+		 arguments.  */
+	      || LAMBDA_TYPE_P (TREE_TYPE (decl)));
+
   /* Set up access control for DECL.  */
   TREE_PRIVATE (decl)
     = (current_access_specifier == access_private_node);
Index: testsuite/g++.dg/cpp1y/pr61636-1.C
===================================================================
--- testsuite/g++.dg/cpp1y/pr61636-1.C	(revision 245028)
+++ testsuite/g++.dg/cpp1y/pr61636-1.C	(working copy)
@@ -1,4 +1,5 @@ 
 // PR c++/61636
+// PR c++/79264
 // { dg-do compile { target c++14 } }
 
 // ICE because we figure this capture too late.
@@ -28,4 +29,8 @@  void A::b() {
   auto lam2 = [&](auto asdf) { Baz (asdf); };
 
   lam2 (0);
+
+  auto lam3 = [&](auto asdf) { Baz<int> (asdf); };
+
+  lam3 (0);
 }