aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-10-14 14:55:04 -0400
committerJason Merrill <jason@redhat.com>2020-10-14 15:44:29 -0400
commit270c5a982ccb4ef83bd9ad37d39cf47461acb55a (patch)
tree47903886f6b3ced46462dd0d088f76f59d1c4a9c
parent8f8cba46b89ad16bac2ce58d554c25b54b0e7c7f (diff)
downloadgcc-270c5a982ccb4ef83bd9ad37d39cf47461acb55a.zip
gcc-270c5a982ccb4ef83bd9ad37d39cf47461acb55a.tar.gz
gcc-270c5a982ccb4ef83bd9ad37d39cf47461acb55a.tar.bz2
c++: Diagnose bogus variadic lambda. [PR97358]
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.
-rw-r--r--gcc/cp/pt.c17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic11.C20
2 files changed, 32 insertions, 5 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 503c0e7..2a9a8fa 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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
index 0000000..aa4ffd7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic11.C
@@ -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);
+}