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.
Tested x86_64-pc-linux-gnu, applying to trunk. 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 | 17 +++++++++++----- .../g++.dg/cpp0x/lambda/lambda-variadic11.C | 20 +++++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic11.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 555dc47b464..e98bf83117d 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 00000000000..aa4ffd70df7 --- /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); +} base-commit: 87d75a11a5cb93668ae0bf6d97030e01b2eae3f2 -- 2.18.1