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:

Reply via email to