Hi,
On 09/06/2012 02:03 AM, Jason Merrill wrote:
but note that for:
template <class T>
struct A
{
int select() { return 0; }
};
we have parser->num_template_parameter_lists == 1 and num_templates ==
0. Thus it seems that the case 'num_templates + 1' isn't (just) about
member templates...
That's odd, num_templates should be 1.
Yes, it seems odd, the same happens for template functions, like simply:
template <class T>
void foo();
Really, whatever we do at least the comment should be adjusted not to
mention only member templates.
And I notice that cp_parser_check_declarator_template_parameters has
another copy of the num_template_headers_for_class logic; they should
be merged.
Something like the attached passes testing, the clean-up is nice, but
I'm not sure about the specific details of the existing code vs
num_template_headers_for_class, whether we can just call the latter as I
did and be done.
I think the problem with 24314 is that we try to decide how many
template headers we want before we determine what declaration we're
looking at. When we have a redefinition or specialization, we know
exactly how many headers we want, and we should check accordingly
rather than say N or N+1.
I see. Yesterday at some point I wondered whether we could do that
already when cp_parser_check_template_parameters is called, that is
remove the + 1 case and make the callers more precise. But I understand
not that it's too early. Then, are you under the impression that we
should still have cp_parser_check_template_parameters as-is and add a
check later, or have only the late one?
I'm looking more into this.
Thanks,
Paolo.
Index: parser.c
===================================================================
--- parser.c (revision 191016)
+++ parser.c (working copy)
@@ -20670,55 +20670,25 @@ cp_parser_check_declarator_template_parameters (cp
cp_declarator *declarator,
location_t declarator_location)
{
- unsigned num_templates;
-
- /* We haven't seen any classes that involve template parameters yet. */
- num_templates = 0;
-
switch (declarator->kind)
{
case cdk_id:
- if (declarator->u.id.qualifying_scope)
- {
- tree scope;
+ {
+ unsigned num_templates = 0;
+ tree scope = declarator->u.id.qualifying_scope;
- scope = declarator->u.id.qualifying_scope;
+ 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;
- while (scope && CLASS_TYPE_P (scope))
- {
- /* You're supposed to have one `template <...>'
- for every template class, but you don't need one
- for a full specialization. For example:
+ return cp_parser_check_template_parameters
+ (parser, num_templates, declarator_location, declarator);
+ }
- template <class T> struct S{};
- template <> struct S<int> { void f(); };
- void S<int>::f () {}
-
- is correct; there shouldn't be a `template <>' for
- the definition of `S<int>::f'. */
- if (!CLASSTYPE_TEMPLATE_INFO (scope))
- /* If SCOPE does not have template information of any
- kind, then it is not a template, nor is it nested
- within a template. */
- break;
- if (explicit_class_specialization_p (scope))
- break;
- if (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope)))
- ++num_templates;
-
- scope = TYPE_CONTEXT (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;
-
- return cp_parser_check_template_parameters
- (parser, num_templates, declarator_location, declarator);
-
-
case cdk_function:
case cdk_array:
case cdk_pointer: