Hi John,

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.

By undefined template, I am assuming that you mean something like:

----------------------------------------------
template <typename> class A;

const A<int>* foo(const A<int>* a)
{
    return a;
}
----------------------------------------------

where the template class A is never defined while the code still refers to one 
of its instantiations.
 
> 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:

----------------------------------------------
template <typename> class A
{
public:
    void foo();
};

template <> class A<int>;

const A<int>* foo(const A<int>* a)
{
    return a;
}
----------------------------------------------


i.e. where I have declared that a specialization for A<int> exists even though 
I have not defined it. 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 am happy with this behavior, but would it be an issue for others ?   

> 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.

> John.

Cheers,
Benoit 
 
Benoit Belley
Sr Principal Developer
M&E-Product Development Group    
 
Autodesk Canada Inc. 
10 Rue Duke
Montreal, Quebec  H3C 2L7 
Canada
 
Direct 514 954-7154
 
 

<<attachment: image002.gif>>

 

_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to