c++: Diagnose bogus variadic lambda. [PR97358]
authorJason Merrill <jason@redhat.com>
Wed, 14 Oct 2020 18:55:04 +0000 (14:55 -0400)
committerJason Merrill <jason@redhat.com>
Wed, 14 Oct 2020 19:44:29 +0000 (15:44 -0400)
If the lambda has a capture pack, it cannot be used unexpanded within the
body of the lambda.  If you want to expand the pack across multiple lambdas,
don't capture the whole pack.

gcc/cp/ChangeLog:

PR c++/97358
* pt.c (check_for_bare_parameter_packs): Diagnose use of
capture pack.

gcc/testsuite/ChangeLog:

PR c++/97358
* g++.dg/cpp0x/lambda/lambda-variadic11.C: New test.

gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic11.C [new file with mode: 0644]

index 503c0e722fad880669a56431cf16cacedcb5486a..2a9a8fafaca59d1adfa487c55b462d050e2147fa 100644 (file)
@@ -4230,11 +4230,6 @@ check_for_bare_parameter_packs (tree t, location_t loc /* = UNKNOWN_LOCATION */)
   if (!processing_template_decl || !t || t == error_mark_node)
     return false;
 
-  /* A lambda might use a parameter pack from the containing context.  */
-  if (current_class_type && LAMBDA_TYPE_P (current_class_type)
-      && CLASSTYPE_TEMPLATE_INFO (current_class_type))
-    return false;
-
   if (TREE_CODE (t) == TYPE_DECL)
     t = TREE_TYPE (t);
 
@@ -4244,6 +4239,18 @@ check_for_bare_parameter_packs (tree t, location_t loc /* = UNKNOWN_LOCATION */)
   cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
   delete ppd.visited;
 
+  /* It's OK for a lambda to have an unexpanded parameter pack from the
+     containing context, but do complain about unexpanded capture packs.  */
+  if (current_class_type && LAMBDA_TYPE_P (current_class_type)
+      && CLASSTYPE_TEMPLATE_INFO (current_class_type))
+    for (; parameter_packs;
+        parameter_packs = TREE_CHAIN (parameter_packs))
+      {
+       tree pack = TREE_VALUE (parameter_packs);
+       if (is_capture_proxy (pack))
+         break;
+      }
+
   if (parameter_packs)
     {
       if (loc == UNKNOWN_LOCATION)
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic11.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic11.C
new file mode 100644 (file)
index 0000000..aa4ffd7
--- /dev/null
@@ -0,0 +1,20 @@
+// PR c++/97358
+// { dg-do compile { target c++11 } }
+
+template <typename... T> void foo (T... x) {}
+
+template <typename... T> void bar (T... x)
+{
+  foo ([x...] { return x; }...); // { dg-error "not expanded|no parameter packs" }
+#if __cpp_init_captures >= 201803L
+  foo ([...y = x] { return y; }...); // { dg-error "not expanded|no parameter packs" "" { target c++20 } }
+#endif
+}
+
+void
+test ()
+{
+  bar ();
+  bar (1);
+  bar (2.0, 3LL, 4);
+}