This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PR c++/20118 missing template<> causes weird errors
- From: "Manuel López-Ibáñez" <lopezibanez at gmail dot com>
- To: "Gcc Patch List" <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 29 Oct 2008 19:31:17 +0100
- Subject: Re: PR c++/20118 missing template<> causes weird errors
- References: <6c33472e0808120819u391e318ev814f2a4f2c7d27fc@mail.gmail.com> <6c33472e0808250039r1baec7c0i6bee59214b60418@mail.gmail.com> <6c33472e0810200519n72f21044u58ea4aa8a530aa5c@mail.gmail.com>
PING: http://gcc.gnu.org/ml/gcc-patches/2008-10/msg00807.html
2008/10/20 Manuel López-Ibáñez <lopezibanez@gmail.com>:
> I have updated the patch to a recent revision, bootstrapped and
> regression tested again.
>
> OK for trunk?
>
> Manuel.
>
> 2008/8/25 Manuel López-Ibáñez <lopezibanez@gmail.com>:
>> PING: http://gcc.gnu.org/ml/gcc-patches/2008-08/msg00793.html
>>
>> 2008/8/12 Manuel López-Ibáñez <lopezibanez@gmail.com>:
>>> Bootstrapped and regression tested on x86_64-unknown-linux-gnu with
>>> --enable-languages=all,ada
>>>
>>> OK for trunk?
>>>
>>> 2008-08-12 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
>>>
>>> PR c++/20118
>>> * diagnostic.c (error_at): New.
>>> * toplev.h (error_at): Declare.
>>> cp/
>>> * 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.
>>> testsuite/
>>> * g++.dg/parse/pr20118.C: New.
>>> * g++.dg/template/spec16.C: Update.
>>>
>>
>
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:specializing member .foo<bool>::i. requires .template<>. syntax" }
+
+int main() { return 0; }
+
Index: gcc/testsuite/g++.dg/template/spec16.C
===================================================================
--- gcc/testsuite/g++.dg/template/spec16.C (revision 141233)
+++ gcc/testsuite/g++.dg/template/spec16.C (working copy)
@@ -5,7 +5,7 @@
template <int N>
struct A {
template<int M> 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" }
}
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c (revision 141233)
+++ gcc/cp/parser.c (working copy)
@@ -1909,11 +1909,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
@@ -11651,11 +11651,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);
}
}
@@ -15241,11 +15242,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;
@@ -17140,13 +17142,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:
@@ -17163,34 +17165,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::%E%> "
+ "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);