diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b11e0049796..847b4850462 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2009-04-10 Manuel López-Ibáñez + + PR c++/20118 + * parser.c (cp_parser_check_template_parameters): Take a + cp_declarator parameter. + (cp_parser_elaborated_type_specifier): Update to + cp_parser_check_template_parameters. + (cp_parser_class_head): Likewise. + (cp_parser_check_declarator_template_parameters): Likewise. + (cp_parser_check_template_parameters): Handle first the non-error + conditions. Give more accurate diagnostics if a declarator is + given. + 2009-04-08 Jason Merrill PR c++/25185 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 18d62cc49ca..68c0ef4ea87 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1913,7 +1913,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_parser *, unsigned, location_t, cp_declarator *); static tree cp_parser_simple_cast_expression (cp_parser *); static tree cp_parser_global_scope_opt @@ -11765,7 +11765,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, there were no qualifying templates. */ if (!cp_parser_check_template_parameters (parser, /*num_templates=*/0, - token->location)) + token->location, + /*declarator=*/NULL)) return error_mark_node; type = xref_tag (tag_type, identifier, ts, template_p); } @@ -15402,7 +15403,8 @@ 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, - type_start_token->location)) + type_start_token->location, + /*declarator=*/NULL)) { /* If something went wrong, there is no point in even trying to process the class-definition. */ @@ -17311,9 +17313,9 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser, additional level of template parameters. */ ++num_templates; - return cp_parser_check_template_parameters (parser, - num_templates, - declarator_location); + return cp_parser_check_template_parameters + (parser, num_templates, declarator_location, declarator); + case cdk_function: case cdk_array: @@ -17334,22 +17336,15 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser, /* NUM_TEMPLATES were used in the current declaration. If that is invalid, return FALSE and issue an error messages. Otherwise, - return TRUE. */ + return TRUE. If DECLARATOR is non-NULL, then we are checking a + declarator and we can print more accurate diagnostics. */ static bool cp_parser_check_template_parameters (cp_parser* parser, unsigned num_templates, - location_t location) + location_t location, + cp_declarator *declarator) { - /* If there are more template classes than parameter lists, we have - something like: - - template void S::R::f (); */ - if (parser->num_template_parameter_lists < num_templates) - { - error ("%Htoo few template-parameter-lists", &location); - return false; - } /* If there are the same number of template classes and parameter lists, that's OK. */ if (parser->num_template_parameter_lists == num_templates) @@ -17357,7 +17352,22 @@ cp_parser_check_template_parameters (cp_parser* parser, /* 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) - return true; + return true; + /* If there are more template classes than parameter lists, we have + something like: + + template void S::R::f (); */ + if (parser->num_template_parameter_lists < num_templates) + { + if (declarator) + error_at (location, "specializing member %<%T::%E%> " + "requires %%> syntax", + declarator->u.id.qualifying_scope, + declarator->u.id.unqualified_name); + else + error_at (location, "too few template-parameter-lists"); + return false; + } /* Otherwise, there are too many template parameter lists. We have something like: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fdee1fae07e..d83fb5e3950 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2009-04-10 Manuel López-Ibáñez + + PR c++/20118 + * g++.dg/parse/pr20118.C: New. + * g++.dg/template/spec16.C: Update. + 2009-04-09 H.J. Lu PR testsuite/35621 @@ -678,7 +684,7 @@ * gfortran.dg/typebound_proc_11.f03: New test. * gfortran.dg/abstract_type_5.f03: New test. -2008-03-29 Tobias Schlüter +2008-03-29 Tobias Schlüter PR fortran/38507 * gfortran.dg/do_4.f: New. diff --git a/gcc/testsuite/g++.dg/parse/pr20118.C b/gcc/testsuite/g++.dg/parse/pr20118.C new file mode 100644 index 00000000000..94e000a6f68 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/pr20118.C @@ -0,0 +1,9 @@ +// { dg-do compile } +// { dg-options "-fshow-column" } +templatestruct foo { + static const int i; }; + +const int foo::i = 5; // { dg-error "11:specializing member .foo::i. requires .template<>. syntax" } + +int main() { return 0; } + diff --git a/gcc/testsuite/g++.dg/template/spec16.C b/gcc/testsuite/g++.dg/template/spec16.C index 881d7a091c2..c872052a864 100644 --- a/gcc/testsuite/g++.dg/template/spec16.C +++ b/gcc/testsuite/g++.dg/template/spec16.C @@ -7,5 +7,5 @@ struct A { template void B () ; }; -void A<0>::B<0>() { // { dg-error "parameter-lists" } +void A<0>::B<0>() { // { dg-error "specializing member 'A<0>::B<0>' requires 'template<>' syntax" } }