* parser.c (cp_parser_elaborated_type_specifier): Only consider template parameter lists outside of function parameter scope.
* g++.dg/cpp1y/pr61537.C: New testcase. --- gcc/cp/parser.c | 28 +++++++++++++++++++--------- gcc/testsuite/g++.dg/cpp1y/pr61537.C | 24 ++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr61537.C diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 41200a0..736d012 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -15081,6 +15081,15 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, return cp_parser_make_typename_type (parser, parser->scope, identifier, token->location); + + /* Template parameter lists apply only if we are not within a + function parameter list. */ + bool template_parm_lists_apply + = parser->num_template_parameter_lists; + for (cp_binding_level *s = current_binding_level; s; s = s->level_chain) + if (s->kind == sk_function_parms) + template_parm_lists_apply = false; + /* Look up a qualified name in the usual way. */ if (parser->scope) { @@ -15123,7 +15132,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, decl = (cp_parser_maybe_treat_template_as_class (decl, /*tag_name_p=*/is_friend - && parser->num_template_parameter_lists)); + && template_parm_lists_apply)); if (TREE_CODE (decl) != TYPE_DECL) { @@ -15136,9 +15145,9 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE) { - bool allow_template = (parser->num_template_parameter_lists - || DECL_SELF_REFERENCE_P (decl)); - type = check_elaborated_type_specifier (tag_type, decl, + bool allow_template = (template_parm_lists_apply + || DECL_SELF_REFERENCE_P (decl)); + type = check_elaborated_type_specifier (tag_type, decl, allow_template); if (type == error_mark_node) @@ -15224,15 +15233,16 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, ts = ts_global; template_p = - (parser->num_template_parameter_lists + (template_parm_lists_apply && (cp_parser_next_token_starts_class_definition_p (parser) || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))); /* An unqualified name was used to reference this type, so there were no qualifying templates. */ - if (!cp_parser_check_template_parameters (parser, - /*num_templates=*/0, - token->location, - /*declarator=*/NULL)) + if (template_parm_lists_apply + && !cp_parser_check_template_parameters (parser, + /*num_templates=*/0, + token->location, + /*declarator=*/NULL)) return error_mark_node; type = xref_tag (tag_type, identifier, ts, template_p); } diff --git a/gcc/testsuite/g++.dg/cpp1y/pr61537.C b/gcc/testsuite/g++.dg/cpp1y/pr61537.C new file mode 100644 index 0000000..55761cd --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr61537.C @@ -0,0 +1,24 @@ +// PR c++/61537 +// { dg-do compile { target c++1y } } +// { dg-options "" } + +struct A {}; + +template <typename T> +struct B +{ + template <typename U> + void f(U, struct A); +}; + +template <typename T> +template <typename U> +void B<T>::f(U, struct A) +{ +} + +int main() +{ + B<char> b; + b.f(42, A()); +} -- 2.0.0