RecursiveASTVisitor not traversing implicit ParmVarDecl's in class instantiation methods?

I thought this was fixed recently...

I've found the related bug:

http://llvm.org/bugs/show_bug.cgi?id=16182

And the commit:

http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20130909/088533.html

It appears that before the patch, parameters of implicit functions were not visited at all. Code was changed to visit parameters, but it visits ParmVarDecl's of the template function, not the instantiated one. I've filed a bug: http://llvm.org/bugs/show_bug.cgi?id=17272

Hi Joshua,

I think something like this should work

  TypeSourceInfo *TSI = D->getTypeSourceInfo();
  if (!TSI || D->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
    for (FunctionDecl::param_const_iterator I = D->param_begin(),
                                            E = D->param_end(); I != E; ++I)
      TRY_TO(TraverseDecl(*I));
  } else {
    TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
  }

In both cases (special member functions and implicit instantiations) we can't rely on TypeSourceInfo to visit the parameter variable declaration, so need to visit them explicitly. And I think we don't need to test shouldVisitTemplate or shouldVisitImplicit because the code would not reach here here if those returned false.

As for the parameter variable's TypeSourceInfo are the same for the template declaration and the implicit instantiations, I don't know if it is intended or a bug. I'll let someone with more Sema knowledge to comment.

Michael.

Thanks, Michael.

That's how I ended up handling the problem, with one exception:

  if (!TSI || D->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {

s/!=/==

There's one thing I only noticed later when verifying the fix. In this case:

template <class T>
static T* Foo() {};

class Bar
{
  friend Bar* Foo<Bar>();
};

"Bar *" isn't visited anymore. Traversing FunctionTypeLoc used to handle function parameters as well as the ResultLoc. Now that this isn't done for implicit instantiations, it has to be explicitly taken care of:

    if (TSI)
      TRY_TO(TraverseTypeLoc(TSI->getTypeLoc().getAs<FunctionTypeLoc>().getResultLoc()));

I still feel this is all hacky. It'd be great if TypeSourceInfo was unique for instantiations.

/Joshua