diff mbox series

[C++] PR c++/87685 - generic lambda 'this' capture error.

Message ID 20190222064725.29018-1-jason@redhat.com
State New
Headers show
Series [C++] PR c++/87685 - generic lambda 'this' capture error. | expand

Commit Message

Jason Merrill Feb. 22, 2019, 6:47 a.m. UTC
The standard says that in a generic lambda we should speculatively capture
'this' if we see a call to an overload set that contains a non-static member
function, but it seems wrong to reject the program if we can't capture,
since it might not actually be needed.

Tested x86_64-pc-linux-gnu, applying to trunk.

	* lambda.c (lambda_expr_this_capture): Change add_capture_p to int.
	(maybe_generic_this_capture): Pass -1.
---
 gcc/cp/cp-tree.h                                  |  2 +-
 gcc/cp/lambda.c                                   |  9 +++++----
 gcc/testsuite/g++.dg/cpp1y/lambda-generic-this3.C | 13 +++++++++++++
 gcc/cp/ChangeLog                                  |  4 ++++
 4 files changed, 23 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-this3.C


base-commit: a7ea8f9672905a517f73ea2764a4301ddc8e3184
diff mbox series

Patch

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 879712f6dbc..91bc82b85e5 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7151,7 +7151,7 @@  extern bool is_capture_proxy			(tree);
 extern bool is_normal_capture_proxy             (tree);
 extern bool is_constant_capture_proxy           (tree);
 extern void register_capture_members		(tree);
-extern tree lambda_expr_this_capture            (tree, bool);
+extern tree lambda_expr_this_capture            (tree, int);
 extern void maybe_generic_this_capture		(tree, tree);
 extern tree maybe_resolve_dummy			(tree, bool);
 extern tree current_nonlambda_function		(void);
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 7032168fb7b..d178f15a4da 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -730,10 +730,11 @@  add_default_capture (tree lambda_stack, tree id, tree initializer)
 
 /* Return the capture pertaining to a use of 'this' in LAMBDA, in the
    form of an INDIRECT_REF, possibly adding it through default
-   capturing, if ADD_CAPTURE_P is true.  */
+   capturing, if ADD_CAPTURE_P is nonzero.  If ADD_CAPTURE_P is negative,
+   try to capture but don't complain if we can't.  */
 
 tree
-lambda_expr_this_capture (tree lambda, bool add_capture_p)
+lambda_expr_this_capture (tree lambda, int add_capture_p)
 {
   tree result;
 
@@ -829,7 +830,7 @@  lambda_expr_this_capture (tree lambda, bool add_capture_p)
     result = this_capture;
   else if (!this_capture)
     {
-      if (add_capture_p)
+      if (add_capture_p == 1)
 	{
 	  error ("%<this%> was not captured for this lambda function");
 	  result = error_mark_node;
@@ -934,7 +935,7 @@  maybe_generic_this_capture (tree object, tree fns)
 	      && DECL_NONSTATIC_MEMBER_FUNCTION_P (*iter))
 	    {
 	      /* Found a non-static member.  Capture this.  */
-	      lambda_expr_this_capture (lam, true);
+	      lambda_expr_this_capture (lam, /*maybe*/-1);
 	      break;
 	    }
       }
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-this3.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-this3.C
new file mode 100644
index 00000000000..2bd287cc368
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-this3.C
@@ -0,0 +1,13 @@ 
+// PR c++/87685
+// { dg-do compile { target c++14 } }
+
+struct A
+{
+  template <typename T> static void f(T) {}
+  void f() {}
+
+  void foo()
+  {
+    [] (auto&& v) { A::f(v); }; // OK if parameter type is specified
+  }
+};
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a41044683fe..e7780e7eb12 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,9 @@ 
 2019-02-21  Jason Merrill  <jason@redhat.com>
 
+	PR c++/87685 - generic lambda 'this' capture error.
+	* lambda.c (lambda_expr_this_capture): Change add_capture_p to int.
+	(maybe_generic_this_capture): Pass -1.
+
 	PR c++/88394 - ICE with VLA init-capture.
 	* lambda.c (is_normal_capture_proxy): Check DECL_CAPTURED_VARIABLE.