On Sep 1, 2010, at 11:10 AM, Benoit Belley wrote:
> Le 2010-08-30 à 21:37, John McCall a écrit :
>> On Aug 30, 2010, at 6:08 PM, John McCall wrote:
>>> On Aug 30, 2010, at 5:33 PM, Benoit Belley wrote:
>>>> I think that I’ll need a bit more explanation here. The infinite recursion
>>>> occurs while traversing the instantiations of the class template
>>>> definition and I do want to traverse these instantiations. That’s the
>>>> whole point of my proposed change.
>>>
>>> Yes, I understood that. My point is that you're visiting the
>>> instantiations regardless of whether the current template declaration
>>> you're visiting is a redeclaration or not. This creates two problems:
>>> first, you end up visiting the instantiations multiple times if the
>>> template is redeclared; and second, if the template is redeclared within
>>> itself (which can only be done with friend declarations), you end up
>>> visiting it recursively, which blows up the stack. The solution is to only
>>> visit implicit instantiations when you visit a pattern definition.
>>>
>>> template <class T> class A; // <- don't visit any instantiations here
>>> class B { template <class T> friend class A; }; // <- or here
>>> template <class T> class A { ... }; // <- okay to visit implicit
>>> instantiations here
>>
>> A few more notes.
>>
>> First, note that my proposal means that you won't be visiting implicit
>> instantiations for undefined templates. I'm assuming that's okay;
>> otherwise, you'll need to use different logic (I think visiting
>> instantiations for the first declaration should be sufficient).
>>
>
> I’m also ok with not visiting implicit instantiations for undefined templates.
Okay, that makes sense.
>> Second, have you considered what you want to do with incomplete
>> instantiations? These arise when a template specialization is written but
>> not required to be a complete type. My thought is that these should be
>> ignored, but you may feel differently.
>>
>
> No, I have not considered them up to now. By incomplete instantiation, do you
> mean the following:
> i.e. where I have declared that a specialization for A<int> exists even
> though I have not defined it.
No, I mean something like this:
template <class T> struct A { T foo; };
int bar(A<T> &a) { return 0; }
i.e. where a specialization of A was used but not required to be a complete
type and so template instantiation was never done.
> If so, my RecursiveASTVisitor to behave like expected, i.e. the instantiation
> for A<int> is never visited.
>
>> Third, you need to decide what you want to do with instantiations of partial
>> specializations. A significant issue here is that it's possible to have
>> complete instantiations of a template without having a definition for the
>> primary template. I think the most appropriate general solution is to visit
>> instantiations whenever you reach their pattern; for example:
>> template <class T> class A { ... }; // visit A<bool>, A<int> here
>> template <class T> class A<T*> { ... }; // visit A<char*>, A<int*> here
>>
>
> Ok, I fixed this using:
>
> CXXRecordDecl* TempDecl = D->getTemplatedDecl();
> TRY_TO(TraverseDecl(TempDecl));
> TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
> // Explicit class intantiations and specializations will be
> // traversed from the context of their declaration. There
> // is therefore no need to traverse them for here.
> //
> // In addition, we only traverse the class instantiations when the
> // class template is class template definition or the canonical
> // declaration when no definition of the class exists.
> if (TempDecl) {
> CXXRecordDecl* DefDecl = TempDecl->getDefinition();
> CXXRecordDecl* CanoDecl = TempDecl->getCanonicalDecl();
> if (TempDecl == DefDecl || (!DefDecl && TempDecl == CanoDecl)) {
> TRY_TO(TraverseImplicitClassInstantiations(D));
> }
> }
>
> Note that the behavior ends-up being slightly different from what you
> suggested. The instantiations are always traverse in the scope of a class
> declaration ClassTemplateDecl (either the definition or the canonical
> declaration when no definition exists). Instantiations of partial
> specialization are not traverse in the scope of the
> ClassTemplatePartialSpecializationDeclaration.
I guess this is fine, although please try to avoid doing the getDefinition() /
getCanonicalDecl() work if we're not visiting instantiations. If someone cares
about exact ordering of visitation, we can change it then and it shouldn't hurt
you.
>> Finally, it looks like there's an existing bug (with a FIXME) where we're
>> not visiting the bodies of explicit specializations. If you could fix
>> TraverseClassTemplateSpecializationDecl to visit the record when either your
>> flag is set *or* it's an explicit specialization, that would be good.
>>
>
> Sure.
Thanks.
John.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits