I need to preprocess some C++ files to automatically insert code for testing and profiling, and I need to do it with the clang API.
For now, I want to be able to do the following: If there is a function:
int SomeFn(int a, int b, int c) {
doStuff();
}
I want to preprocess it, that it looks like this:
int SomeFn(int a, int b, int c) {
cout << "SomeFn is invoked with the following arguments: a=" << a << ", b=" << b << ", c=" << c << endl;
doStuff();
}
I've tried to extend ASTConsumer
and use the methods HandleTopLevelDecl
and HandleTopLevelSingleDecl
and check if the passed Decls
are FunctionDecls
and downcast them, so I can get their names and body-locations.
But I can't handle class-methods that way, only global functions.
I found a function in the ASTConsumer
class HandleTagDeclDefinition(TagDecl* D)
. The documentation says:
This callback is invoked each time a TagDecl (e.g. struct, union, enum, class) is completed.
But it looks like this method isn't even invoked, when I test it.
So my question is, what would be the right way to do this task? And how are C++ classes are represented in the clang API? Maybe someone knows, where I can find examples because the clang API is poorly documented.
UPDATE:
I know there is also the concept of Visitors
and there is a method VisitRecordDecl(RecordDecl *D)
. The documentation says that RecordDecl
represents classes. So I extended RecursiveASTVisitor
and implemented VisitRecordDecl(RecordDecl *D)
but it seems, that this method isn't invoked neither.
Instead VisitVarDecl
is invoked, when a class definition is find, as if it is seen as a variable declaration.
So I'm a bit confused. I hope, someone can help...
UPDATE2:
I tried to parse another file and this time clang found one RecordDecl
. But the file defined one struct and two classes, so I think my clang code parses C instead of C++. Are there any settings to switch between C and C++ ?