Message ID | CADzB+2m4o-ADUwUh3bgQ8yvQnLVxUkRRmP8u9QB5h6JBZFRm2Q@mail.gmail.com |
---|---|
State | New |
Headers | show |
Series | C++ PATCH for c++/85264, ICE with extra template parameter list | expand |
Hi, On 09/04/2018 21:39, Jason Merrill wrote: > cp_parser_check_template_parameters is supposed to catch when we have > the wrong number of template parameter lists, but it wasn't diagnosing > this case. Fixed by checking whether the thing we're declaring used a > template-id; the case of declaring a primary template, when we allow > one more template parameter list, uses a plain identifier. Nice, it looks like this also fixes the prehistoric c++/24314, which I still had assigned. When I worked a bit on it, relatively recently, in 2012, I failed to properly follow-up to your feedback on the mailing list, but I don't think we really nailed the problem, did we? https://gcc.gnu.org/ml/gcc-patches/2012-09/msg00504.html Or maybe we just tried to do too much, like doing away completely with cp_parser_check_template_parameters in favor of a bit of additional checking in maybe_process_partial_specialization. Paolo.
On Mon, Apr 9, 2018 at 6:55 PM, Paolo Carlini <paolo.carlini@oracle.com> wrote: > On 09/04/2018 21:39, Jason Merrill wrote: >> >> cp_parser_check_template_parameters is supposed to catch when we have >> the wrong number of template parameter lists, but it wasn't diagnosing >> this case. Fixed by checking whether the thing we're declaring used a >> template-id; the case of declaring a primary template, when we allow >> one more template parameter list, uses a plain identifier. > > Nice, it looks like this also fixes the prehistoric c++/24314, which I still > had assigned. Great! > When I worked a bit on it, relatively recently, in 2012, I > failed to properly follow-up to your feedback on the mailing list, but I > don't think we really nailed the problem, did we? > > https://gcc.gnu.org/ml/gcc-patches/2012-09/msg00504.html > > Or maybe we just tried to do too much, like doing away completely with > cp_parser_check_template_parameters in favor of a bit of additional checking > in maybe_process_partial_specialization. I'm sure late checking like we discussed there can also work, but this ended up being a simple way to make the current code work better... Jason
On Tue, Apr 10, 2018 at 9:50 AM, Jason Merrill <jason@redhat.com> wrote: > On Mon, Apr 9, 2018 at 6:55 PM, Paolo Carlini <paolo.carlini@oracle.com> wrote: >> On 09/04/2018 21:39, Jason Merrill wrote: >>> >>> cp_parser_check_template_parameters is supposed to catch when we have >>> the wrong number of template parameter lists, but it wasn't diagnosing >>> this case. Fixed by checking whether the thing we're declaring used a >>> template-id; the case of declaring a primary template, when we allow >>> one more template parameter list, uses a plain identifier. >> >> Nice, it looks like this also fixes the prehistoric c++/24314, which I still >> had assigned. > > Great! > >> When I worked a bit on it, relatively recently, in 2012, I >> failed to properly follow-up to your feedback on the mailing list, but I >> don't think we really nailed the problem, did we? >> >> https://gcc.gnu.org/ml/gcc-patches/2012-09/msg00504.html >> >> Or maybe we just tried to do too much, like doing away completely with >> cp_parser_check_template_parameters in favor of a bit of additional checking >> in maybe_process_partial_specialization. > > I'm sure late checking like we discussed there can also work, but this > ended up being a simple way to make the current code work better... But as discussed in that thread, we should still improve the comment: commit 2072134d123d64535baac00ea4bb6ffbce045caf Author: Jason Merrill <jason@redhat.com> Date: Tue Apr 10 09:42:54 2018 -0400 * parser.c (cp_parser_check_template_parameters): Improve comment. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index d4b62c75c44..849a75a1a51 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -26452,8 +26452,8 @@ cp_parser_check_template_parameters (cp_parser* parser, lists, that's OK. */ if (parser->num_template_parameter_lists == num_templates) return true; - /* If there are more, but only one more, then we are referring to a - member template. That's OK too. */ + /* If there are more, but only one more, and the name ends in an identifier, + then we are declaring a primary template. That's OK too. */ if (!template_id_p && parser->num_template_parameter_lists == num_templates + 1) return true;
commit 770f6eaf7320d908cd39ace3aa155e7ec829982d Author: Jason Merrill <jason@redhat.com> Date: Mon Apr 9 14:03:15 2018 -0400 PR c++/85264 - ICE with excess template-parameter-list. * parser.c (cp_parser_check_template_parameters): Add template_id_p parameter. Don't allow an extra template header if true. (cp_parser_class_head): Pass template_id_p. (cp_parser_elaborated_type_specifier): Likewise. (cp_parser_alias_declaration): Likewise. (cp_parser_check_declarator_template_parameters): Likewise. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 0ffa13de537..0e469259008 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2498,7 +2498,7 @@ static tree cp_parser_maybe_treat_template_as_class static bool cp_parser_check_declarator_template_parameters (cp_parser *, cp_declarator *, location_t); static bool cp_parser_check_template_parameters - (cp_parser *, unsigned, location_t, cp_declarator *); + (cp_parser *, unsigned, bool, location_t, cp_declarator *); static cp_expr cp_parser_simple_cast_expression (cp_parser *); static tree cp_parser_global_scope_opt @@ -17917,6 +17917,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, if (template_parm_lists_apply && !cp_parser_check_template_parameters (parser, /*num_templates=*/0, + /*template_id*/false, token->location, /*declarator=*/NULL)) return error_mark_node; @@ -18971,6 +18972,7 @@ cp_parser_alias_declaration (cp_parser* parser) if (parser->num_template_parameter_lists && !cp_parser_check_template_parameters (parser, /*num_templates=*/0, + /*template_id*/false, id_location, /*declarator=*/NULL)) return error_mark_node; @@ -23117,6 +23119,7 @@ cp_parser_class_head (cp_parser* parser, /* Make sure that the right number of template parameters were present. */ if (!cp_parser_check_template_parameters (parser, num_templates, + template_id_p, type_start_token->location, /*declarator=*/NULL)) { @@ -26391,17 +26394,22 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser, { unsigned num_templates = 0; tree scope = declarator->u.id.qualifying_scope; + bool template_id_p = false; if (scope) num_templates = num_template_headers_for_class (scope); else if (TREE_CODE (declarator->u.id.unqualified_name) == TEMPLATE_ID_EXPR) - /* If the DECLARATOR has the form `X<y>' then it uses one - additional level of template parameters. */ - ++num_templates; + { + /* If the DECLARATOR has the form `X<y>' then it uses one + additional level of template parameters. */ + ++num_templates; + template_id_p = true; + } return cp_parser_check_template_parameters - (parser, num_templates, declarator_location, declarator); + (parser, num_templates, template_id_p, declarator_location, + declarator); } case cdk_function: @@ -26430,6 +26438,7 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser, static bool cp_parser_check_template_parameters (cp_parser* parser, unsigned num_templates, + bool template_id_p, location_t location, cp_declarator *declarator) { @@ -26439,7 +26448,8 @@ cp_parser_check_template_parameters (cp_parser* parser, return true; /* If there are more, but only one more, then we are referring to a member template. That's OK too. */ - if (parser->num_template_parameter_lists == num_templates + 1) + if (!template_id_p + && parser->num_template_parameter_lists == num_templates + 1) return true; /* If there are more template classes than parameter lists, we have something like: diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic176.C b/gcc/testsuite/g++.dg/cpp0x/variadic176.C new file mode 100644 index 00000000000..1d6e3c2f10a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic176.C @@ -0,0 +1,10 @@ +// PR c++/85264 +// { dg-do compile { target c++11 } } + +template<typename> struct A {}; + +template<int> +template<typename... T> +struct A<void(T...)> {}; // { dg-error "too many template-parameter-lists" } + +A<void(int)> a;