From 32b8f5df9f05426c82c6de1acaf9ca4aec68039d Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sun, 23 Feb 2020 20:52:41 -0500 Subject: [PATCH] c++: Fix C++20 variadic lambda init-capture grammar. The grammar for variadic init-capture was fixed at the Prague C++ meeting where we finalized C++20. gcc/cp/ChangeLog 2020-02-24 Jason Merrill P0780R2: Resolve lambda init-capture pack grammar. * parser.c (cp_parser_lambda_introducer): Expect &...x=y rather than ...&x=y. --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/parser.c | 15 +++++++++++++-- gcc/testsuite/g++.dg/cpp2a/lambda-pack-init4.C | 10 ++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-pack-init4.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8a3c9f77ad0..cc0f42dfda5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2020-02-24 Jason Merrill + + P0780R2: Resolve lambda init-capture pack grammar. + * parser.c (cp_parser_lambda_introducer): Expect &...x=y rather than + ...&x=y. + 2020-02-22 Marek Polacek PR c++/93882 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index ee534b5db21..87ed2a3a648 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -10620,6 +10620,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) /* Record default capture mode. "[&" "[=" "[&," "[=," */ if (cp_lexer_next_token_is (parser->lexer, CPP_AND) + && !cp_lexer_nth_token_is (parser->lexer, 2, CPP_ELLIPSIS) && !cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME) && !cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_THIS)) LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) = CPLD_REFERENCE; @@ -10715,6 +10716,13 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) continue; } + /* Remember whether we want to capture as a reference or not. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_AND)) + { + capture_kind = BY_REFERENCE; + cp_lexer_consume_token (parser->lexer); + } + bool init_pack_expansion = false; location_t ellipsis_loc = UNKNOWN_LOCATION; if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) @@ -10727,9 +10735,12 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) init_pack_expansion = true; } - /* Remember whether we want to capture as a reference or not. */ - if (cp_lexer_next_token_is (parser->lexer, CPP_AND)) + /* Early C++20 drafts had ...& instead of &...; be forgiving. */ + if (init_pack_expansion && capture_kind != BY_REFERENCE + && cp_lexer_next_token_is (parser->lexer, CPP_AND)) { + pedwarn (cp_lexer_peek_token (parser->lexer)->location, + 0, "%<&%> should come before %<...%>"); capture_kind = BY_REFERENCE; cp_lexer_consume_token (parser->lexer); } diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-pack-init4.C b/gcc/testsuite/g++.dg/cpp2a/lambda-pack-init4.C new file mode 100644 index 00000000000..e7c815b92d4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-pack-init4.C @@ -0,0 +1,10 @@ +// P2095R0 +// { dg-do compile { target c++2a } } +// { dg-options "" } + +template +void f(T... t) +{ + [&...x=t]{}; + [...&x=t]{}; // { dg-warning "7:&" } +} -- 2.30.2