PR c++/87685 - generic lambda 'this' capture error.
authorJason Merrill <jason@redhat.com>
Fri, 22 Feb 2019 06:47:37 +0000 (01:47 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 22 Feb 2019 06:47:37 +0000 (01:47 -0500)
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.

* lambda.c (lambda_expr_this_capture): Change add_capture_p to int.
(maybe_generic_this_capture): Pass -1.

From-SVN: r269095

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/lambda.c
gcc/testsuite/g++.dg/cpp1y/lambda-generic-this3.C [new file with mode: 0644]

index a41044683fe17fa9a086595b96063af518af231b..e7780e7eb12a36811236a1136079543c0d395417 100644 (file)
@@ -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.
 
index 879712f6dbce7c678f01e56c42f9250705bd44b2..91bc82b85e58be5d3e6f46520aeb7e968a7a5970 100644 (file)
@@ -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);
index 7032168fb7b0ddf57f6a39e09344a4a28bd39c16..d178f15a4da4acc288da73444338e46d2add3505 100644 (file)
@@ -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 (file)
index 0000000..2bd287c
--- /dev/null
@@ -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
+  }
+};