Adding support for {Class, ...}TemplateDeclSpecialization to libClang

Hello all,

libclang does currently not allow retrieving information about implicit nor explicit template instantiations. A visitor function passed to clang_visitChildren() will be called for the template definition itself, but not for any template instantiation.

This is a problem when one needs information that requires a knowledge of the actual template parameters, for example the MemberRef access "foo.x" in boop() has an empty spelling and no useful definition cursor set

template <class T> struct Foo { T x; };

template <class T> struct Bar { Foo<T> foo; void boop() { auto x = foo.x; } };

int main() { Bar<int> b; b.boop(); }

The code seems to already have some code considering ClassTemplateSpecializations, namely in libclang/CIndex.cpp, there's a bool CursorVisitor::VisitClassTemplateSpecializationDecl() method. However, it never gets called, which I've verified by placing a debug std::cout in there.

I propose to add code to visit the explicit and implicit specialisations, adding an appropriate CursorType and possibly a function to query whether the Cursor is an implicit or an explicit template specialisation. This would happen in analogy to clang++'s -dump-ast option, putting the specialisations as children below the ClassTemplateDecl as parent.

I've attached a (very dirty) patch as proof of concept: In CursorVisitor::VisitClassTemplateDecl(), it iterates over all specialisations and calls VisitClassTemplateSpecializationDecl() on them.

This is not beautiful yet, because it still won't expose any "Template Specialisation" Cursor to the application, but at least all of its children. Also, function and variable templates might require the same treatment.

Given that the actual Specialisation was visited (and the children only when the visitor function returned CXChildVisit_Recurse), would such a change be merged into upstream libclang? I would really need such a feature, and it seems like a similar request has already been made [1].

What do I need to watch out for when implementing this, to not break any software which uses libclang? (Ideally, it should just return CXChildVisit_Continue on the newly added cursors, so it won't notice much)

And what's the purpose of the existing VisitClassTemplateSpecializationDecl() method in its current state?

Kind regards,


[1] "[cfe-dev] Will libclang ever be able to step through classes defined by template instantiations?", Wed Dec 6 08:35:49 PST 2017

proof_of_concept.patch (1.62 KB)