diff options
author | Jason Merrill <jason@redhat.com> | 2020-10-14 14:55:04 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2020-10-14 15:44:29 -0400 |
commit | 270c5a982ccb4ef83bd9ad37d39cf47461acb55a (patch) | |
tree | 47903886f6b3ced46462dd0d088f76f59d1c4a9c | |
parent | 8f8cba46b89ad16bac2ce58d554c25b54b0e7c7f (diff) | |
download | gcc-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.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic11.C | 20 |
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); +} |