PR c++/60065 * parser.c (cp_parser_direct_declarator): Don't save and restore num_template_parameter_lists around call to cp_parser_parameter_declaration_list. (function_being_declared_is_template_p): New predicate. (cp_parser_parameter_declaration_list): Use function_being_declared_is_template_p as predicate for inspecting current function template parameter list length rather than num_template_parameter_lists.
PR c++/60065 * g++.dg/cpp1y/pr60065.C: New testcase. --- gcc/cp/parser.c | 33 ++++++++++++++++++++------------- gcc/testsuite/g++.dg/cpp1y/pr60065.C | 8 ++++++++ 2 files changed, 28 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr60065.C diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 1e4e3df..7e0531b 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -17038,7 +17038,6 @@ cp_parser_direct_declarator (cp_parser* parser, if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED) { tree params; - unsigned saved_num_template_parameter_lists; bool is_declarator = false; /* In a member-declarator, the only valid interpretation @@ -17060,22 +17059,11 @@ cp_parser_direct_declarator (cp_parser* parser, parser->in_declarator_p = true; } - /* Inside the function parameter list, surrounding - template-parameter-lists do not apply. */ - saved_num_template_parameter_lists - = parser->num_template_parameter_lists; - parser->num_template_parameter_lists = 0; - begin_scope (sk_function_parms, NULL_TREE); /* Parse the parameter-declaration-clause. */ params = cp_parser_parameter_declaration_clause (parser); - /* Restore saved template parameter lists accounting for implicit - template parameters. */ - parser->num_template_parameter_lists - += saved_num_template_parameter_lists; - /* Consume the `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); @@ -18109,6 +18097,25 @@ cp_parser_type_specifier_seq (cp_parser* parser, } } +/* Return whether the function currently being declared has an associated + template parameter list. */ + +static bool function_being_declared_is_template_p (cp_parser* parser) +{ + if (!current_template_parms) + return false; + + if (parser->implicit_template_scope) + return true; + + if (at_class_scope_p () + && TYPE_BEING_DEFINED (current_class_type)) + return parser->num_template_parameter_lists != 0; + + return ((int) parser->num_template_parameter_lists > template_class_depth + (current_class_type)); +} + /* Parse a parameter-declaration-clause. parameter-declaration-clause: @@ -18247,7 +18254,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) cp_parameter_declarator *parameter; tree decl = error_mark_node; bool parenthesized_p = false; - int template_parm_idx = (parser->num_template_parameter_lists? + int template_parm_idx = (function_being_declared_is_template_p (parser)? TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (current_template_parms)) : 0); diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60065.C b/gcc/testsuite/g++.dg/cpp1y/pr60065.C new file mode 100644 index 0000000..2aaa1e3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr60065.C @@ -0,0 +1,8 @@ +// PR c++/60065 +// { dg-do compile } +// { dg-options "-std=c++1y" } + +template <int> void foo(auto... x); +template <typename> void foo2(auto... x); +template <int> void foo3(auto... x, auto y, auto... z); +template <typename> void foo4(auto... x, auto y, auto... z); -- 1.9.0