------- Comment #7 from manu at gcc dot gnu dot org 2008-08-09 23:24 ------- Testing the following patch. Not as good as ICC's diagnostic but close.
Index: gcc/testsuite/g++.dg/parse/pr20118.C =================================================================== --- gcc/testsuite/g++.dg/parse/pr20118.C (revision 0) +++ gcc/testsuite/g++.dg/parse/pr20118.C (revision 0) @@ -0,0 +1,9 @@ +// { dg-do compile } +// { dg-options "-fshow-column" } +template<typename t>struct foo { + static const int i; }; + +const int foo<bool>::i = 5; // { dg-error ":11: error: specializing member foo<bool>::i requires template<> syntax" } + +int main() { return 0; } + Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 138906) +++ gcc/cp/parser.c (working copy) @@ -1905,11 +1905,11 @@ static tree cp_parser_lookup_name_simple static tree cp_parser_maybe_treat_template_as_class (tree, bool); 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 (cp_parser *, bool); static bool cp_parser_constructor_declarator_p @@ -11591,11 +11591,12 @@ cp_parser_elaborated_type_specifier (cp_ || 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)) + token->location, + /*declarator=*/NULL)) return error_mark_node; type = xref_tag (tag_type, identifier, ts, template_p); } } @@ -15049,11 +15050,12 @@ cp_parser_class_head (cp_parser* parser, end of this function; set "type "to the correct return value and use "goto done;" to return. */ /* 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. */ type = NULL_TREE; goto done; @@ -16946,13 +16948,13 @@ cp_parser_check_declarator_template_para == TEMPLATE_ID_EXPR) /* If the DECLARATOR has the form `X<y>' then it uses one 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: case cdk_pointer: case cdk_reference: @@ -16969,34 +16971,42 @@ cp_parser_check_declarator_template_para return false; } /* 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 the same number of template classes and parameter + 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 (parser->num_template_parameter_lists == num_templates + 1) + return true; /* If there are more template classes than parameter lists, we have something like: template <class T> void S<T>::R<T>::f (); */ if (parser->num_template_parameter_lists < num_templates) { - error ("%Htoo few template-parameter-lists", &location); + if (declarator) + error_at (location, "specializing member %<%T::%qE%> " + "requires %<template<>%> syntax", + declarator->u.id.qualifying_scope, + declarator->u.id.unqualified_name); + else + error_at (location, "too few template-parameter-lists"); 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) - 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) - return true; /* Otherwise, there are too many template parameter lists. We have something like: template <class T> template <class U> void S::f(); */ error ("%Htoo many template-parameter-lists", &location); -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20118