On Tue, Mar 12, 2019 at 04:07:56PM -0400, Jason Merrill wrote: > On 3/12/19 3:59 PM, Marek Polacek wrote: > > As Barry explained in the PR, lambda capture is one of > > > > simple-capture ...[opt] > > ...[opt] init-capture > > > > where init-capture requires an initializer. Here we have > > > > [...xs...] > > > > which is ill-formed as it's mingling both of these. > > > > Bootstrapped/regtested on x86_64-linux, ok for trunk? Or should I defer to > > GCC > > 10? > > > > 2019-03-12 Marek Polacek <pola...@redhat.com> > > > > PR c++/89686 - mixing init-capture and simple-capture in lambda. > > * parser.c (cp_parser_lambda_introducer): Give error when combining > > init-capture and simple-capture. > > > > * g++.dg/cpp2a/lambda-pack-init2.C: New test. > > > > diff --git gcc/cp/parser.c gcc/cp/parser.c > > index f95111169ed..d5d8f364752 100644 > > --- gcc/cp/parser.c > > +++ gcc/cp/parser.c > > @@ -10721,6 +10721,15 @@ cp_parser_lambda_introducer (cp_parser* parser, > > tree lambda_expr) > > { > > cp_lexer_consume_token (parser->lexer); > > capture_init_expr = make_pack_expansion (capture_init_expr); > > + if (init_pack_expansion) > > + { > > + /* We'd already seen '...' so we were expecting an > > + init-capture. But we just saw another '...' which > > + would imply a simple-capture. */ > > + error_at (capture_token->location, > > + "combining init-capture and simple-capture"); > > That diagnostic seems a bit obscure, how about something like "too many > %<...%> in lambda capture"?
Yup, sounds better. > Or perhaps check to see if there's an initializer after the ..., and > complain about the second ... if so, or the first ... if not. I tried but we already give diagnostic for [...xs=xs...] or [...xs=...xs] and similar. But let's at least use a proper location for the '...'. Bootstrapped/regtested on x86_64-linux, ok for trunk? 2019-03-12 Marek Polacek <pola...@redhat.com> PR c++/89686 - mixing init-capture and simple-capture in lambda. * parser.c (cp_parser_lambda_introducer): Give error when combining init-capture and simple-capture. * g++.dg/cpp2a/lambda-pack-init2.C: New test. diff --git gcc/cp/parser.c gcc/cp/parser.c index f95111169ed..69294e20191 100644 --- gcc/cp/parser.c +++ gcc/cp/parser.c @@ -10719,8 +10719,17 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) { + location_t eloc = cp_lexer_peek_token (parser->lexer)->location; cp_lexer_consume_token (parser->lexer); capture_init_expr = make_pack_expansion (capture_init_expr); + if (init_pack_expansion) + { + /* We'd already seen '...' so we were expecting an + init-capture. But we just saw another '...' which + would imply a simple-capture. */ + error_at (eloc, "too many %<...%> in lambda capture"); + continue; + } } } diff --git gcc/testsuite/g++.dg/cpp2a/lambda-pack-init2.C gcc/testsuite/g++.dg/cpp2a/lambda-pack-init2.C new file mode 100644 index 00000000000..cd31f3296e1 --- /dev/null +++ gcc/testsuite/g++.dg/cpp2a/lambda-pack-init2.C @@ -0,0 +1,19 @@ +// PR c++/89686 +// { dg-do compile { target c++2a } } + +template <typename... Ts> +void foo(Ts... xs) +{ + int i = 10; + [...xs...]{}(); // { dg-error "too many ..... in lambda capture" } + [xs...]{}(); + [...xs=xs]{}(); + [i, ...xs...]{}(); // { dg-error "too many ..... in lambda capture" } + [i, xs...]{}(); + [i, ...xs=xs]{}(); +} + +int main() +{ + foo(0, 1, 2); +}