https://gcc.gnu.org/g:48c3e5a4f935d6b8cd9ef7c51995e3b29ceb8be7
commit r15-1000-g48c3e5a4f935d6b8cd9ef7c51995e3b29ceb8be7 Author: Jakub Jelinek <ja...@redhat.com> Date: Mon Jun 3 23:07:08 2024 +0200 c++: Fix parsing of abstract-declarator starting with ... followed by opening paren [PR115012] The C++26 P2662R3 Pack indexing paper mentions that both GCC and MSVC don't handle T...[10] parameter declaration when T is a pack. And apparently neither T...(args). While the former will change meaning in C++26, T...(args) is still valid even in C++26. The following patch handles just the T...(args) case in cp_parser_direct_declarator. 2024-06-03 Jakub Jelinek <ja...@redhat.com> PR c++/115012 * parser.cc (cp_parser_direct_declarator): Handle abstract declarator starting with ... followed by opening paren. * g++.dg/cpp0x/variadic185.C: New test. Diff: --- gcc/cp/parser.cc | 15 +++++++++-- gcc/testsuite/g++.dg/cpp0x/variadic185.C | 43 ++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 779625144db..3b2ad25af9f 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -23991,7 +23991,12 @@ cp_parser_direct_declarator (cp_parser* parser, { /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); - if (token->type == CPP_OPEN_PAREN) + if (token->type == CPP_OPEN_PAREN + || (first + && dcl_kind != CP_PARSER_DECLARATOR_NAMED + && token->type == CPP_ELLIPSIS + && cxx_dialect > cxx98 + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN))) { /* This is either a parameter-declaration-clause, or a parenthesized declarator. When we know we are parsing a @@ -24030,6 +24035,11 @@ cp_parser_direct_declarator (cp_parser* parser, Thus again, we try a parameter-declaration-clause, and if that fails, we back out and return. */ + bool pack_expansion_p = token->type == CPP_ELLIPSIS; + + if (pack_expansion_p) + /* Consume the `...' */ + cp_lexer_consume_token (parser->lexer); if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED) { @@ -24173,6 +24183,7 @@ cp_parser_direct_declarator (cp_parser* parser, attrs, parens_loc); declarator->attributes = gnu_attrs; + declarator->parameter_pack_p |= pack_expansion_p; /* Any subsequent parameter lists are to do with return type, so are not those of the declared function. */ @@ -24196,7 +24207,7 @@ cp_parser_direct_declarator (cp_parser* parser, /* If this is the first, we can try a parenthesized declarator. */ - if (first) + if (first && !pack_expansion_p) { bool saved_in_type_id_in_expr_p; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic185.C b/gcc/testsuite/g++.dg/cpp0x/variadic185.C new file mode 100644 index 00000000000..2c04afeda00 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic185.C @@ -0,0 +1,43 @@ +// PR c++/115012 +// { dg-do compile { target { c++11 } } } +// { dg-final { scan-assembler "_Z3fooIJidEEvDpFT_iE" } } +// { dg-final { scan-assembler "_Z3barIiEvPFT_iE" } } +// { dg-final { scan-assembler "_Z3bazIJidEEvDpFT_iE" } } + +template <typename ...T> +void +foo (T... x (int)) +{ +} + +template <typename T> +void +bar (T (int)) +{ +} + +template <typename ...T> +void +baz (T... (int)) +{ +} + +int +f1 (int) +{ + return 0; +} + +double +f2 (int) +{ + return 0; +} + +void +corge () +{ + foo <int, double> (f1, f2); + bar <int> (f1); + baz <int, double> (f1, f2); +}