Hi,
On 09/06/2012 07:47 PM, Jason Merrill wrote:
On 09/06/2012 12:18 PM, Paolo Carlini wrote:
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();
That seems right; there is one more set of template parameters than
required for the scope, so foo itself is a primary template. If above
you were talking about when we're looking at "struct A" it is right, too.
I was talking about that, yes. Ok then, per se the current check is
loose but correct...
Really, whatever we do at least the comment should be adjusted not to
mention only member templates.
Yes, it's any case of declaring a primary template.
... modulo the comment.
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 I prefer the code from here and would change
num_template_headers_for_class to match.
Ok, I did that in the below, also passes testing.
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 think it ought to work to only have a late check.
I will look into that.
Thanks!
Paolo.
//////////////////////////
2012-09-07 Paolo Carlini <paolo.carl...@oracle.com>
* pt.c (num_template_headers_for_class): Rework per the code
inline in cp_parser_check_declarator_template_parameters.
* parser.c (cp_parser_check_declarator_template_parameters):
Use num_template_headers_for_class.
Index: pt.c
===================================================================
--- pt.c (revision 191032)
+++ pt.c (working copy)
@@ -2214,9 +2214,9 @@ copy_default_args_to_explicit_spec (tree decl)
int
num_template_headers_for_class (tree ctype)
{
- int template_count = 0;
- tree t = ctype;
- while (t != NULL_TREE && CLASS_TYPE_P (t))
+ int num_templates = 0;
+
+ while (ctype && CLASS_TYPE_P (ctype))
{
/* You're supposed to have one `template <...>' for every
template class, but you don't need one for a full
@@ -2228,21 +2228,20 @@ num_template_headers_for_class (tree ctype)
is correct; there shouldn't be a `template <>' for the
definition of `S<int>::f'. */
- if (CLASSTYPE_TEMPLATE_SPECIALIZATION (t)
- && !any_dependent_template_arguments_p (CLASSTYPE_TI_ARGS (t)))
- /* T is an explicit (not partial) specialization. All
- containing classes must therefore also be explicitly
- specialized. */
+ if (!CLASSTYPE_TEMPLATE_INFO (ctype))
+ /* If CTYPE does not have template information of any
+ kind, then it is not a template, nor is it nested
+ within a template. */
break;
- if ((CLASSTYPE_USE_TEMPLATE (t) || CLASSTYPE_IS_TEMPLATE (t))
- && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
- template_count += 1;
+ if (explicit_class_specialization_p (ctype))
+ break;
+ if (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (ctype)))
+ ++num_templates;
- t = TYPE_MAIN_DECL (t);
- t = DECL_CONTEXT (t);
+ ctype = TYPE_CONTEXT (ctype);
}
- return template_count;
+ return num_templates;
}
/* Do a simple sanity check on the template headers that precede the
Index: parser.c
===================================================================
--- parser.c (revision 191032)
+++ 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: