I would like to write plugin that prints out all the functions that are called and what function they are being called from, later on I would like to know if a function pointer was called. I’m wondering what the best approach would be.
I think I should use a ASTConsumer and implement the HandleTranslationUnit method. From there I would have a ASTContext and I’m not entirely sure where I could find the function calls.
Thanks
Have your consumer also inherit from RecursiveASTVisitor, and then implement VisitCallExpr. Example code that I have done can be found here: .
Hi,
I'm a clang newbie but I'm also trying to write a plugin (see
http://github.com/achauve/cppanalyze) and I'm using the following
skeleton to get a hand on all declarations and statements:
class MyConsumer : public ASTConsumer, public RecursiveASTVisitor<MyConsumer>
{
//===--------------------------------------------------------------------===//
// ASTConsumer virtual interface
//===--------------------------------------------------------------------===//
virtual void HandleTranslationUnit(ASTContext &context)
{
// traverse AST to visit declarations and statements
TranslationUnitDecl* tu_decl = context.getTranslationUnitDecl();
TraverseDecl(tu_decl);
}
//===\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-===//
// RecursiveASTVisitor implicit interface
//===\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-===//
/// Visit call statements
bool VisitCallExpr\(CallExpr \*node\)
\{
if \(node\->getDirectCallee\(\)\)
\{
FunctionDecl \*func\_decl = node\->getDirectCallee\(\);
// ... do whatever you want with the function declarations
of the functions that were called
}
return true;
}
};
I'm not sure this is the best solution but as far as I tested it it works fine.
Adrien
I do not see the VisitCallExpr method in the code or in Doxygen.
It looks like the RecursiveASTVisitor class can give me statements, where statements become expressions become function calls by inheritance. Or am I missing something?
Thanks again
So, most of the functions in RecursiveASTVisitor are defined via macro calls, which makes finding out what they are difficult. For my own sanity, I used a simple plugin to dump out all of the functions of RecursiveASTVisitor; their output can be found at <http://www.tjhsst.edu/~jcranmer/visitorfuncs.txt>\.
I have been editing the PrintFunctionNames example(llvm/tools/clang/examples) and the trivial VisitCallExpr() method I implemented does not run. Does anyone mind taking a look at it?
The full file is here: https://gist.github.com/1015907
Thanks again
You need to launch at some time the traversal of the AST. One way is
to call Traverse in the virtual method HandleTranslationUnit.
Please see my first answer to this thread.
Adrien
I see the equivlanent TraverseStmt() method now, but I do not see a way to get statments fron the ASTContext.
Also, from CallExpr *node, is it possible to print the names of the function being called and what called it? Since there seems to be no real Symbol Table I’m not sure if this information is gone at this point or not.
Thanks again everyone
From CallExpr, you can use getDirectCallee() to get a FunctionDecl* of the function being called (assuming it's not a function pointer call); since FunctionDecl is a subclass of NamedDecl, you can use that decl to get the name of the function.
As for getting the function it's in, I'm sure there's a way to do it, I just don't know it off the top of my head.
Do you happen to know anything about the TraverseStmt() method from my previous post any chance? Thats stopping me from digging in more.
(I see the equivalent TraverseStmt() method now, but I do not see a way to get statements fron the ASTContext.)
Thanks
What you need to do is start the traversing in the HandleTranslationUnit method. So long as you keep returning true in the methods you implement, you will visit every node. (Side note: there's no way to disable visiting particular subtrees, as far as I can see...)
That part I follow. For declarations all Adrien had todo was:
virtual void HandleTranslationUnit(ASTContext &context) {
TranslationUnitDecl* tu_decl = context.getTranslationUnitDecl();
TraverseDecl(tu_decl);
}
I would need something like this, but I don’t know what I can pull from the context that will be useful. Basically I don’t know what the commented out line should look like.
virtual void HandleTranslationUnit(ASTContext &context) {
//Stmt *s = context???
TraverseStmt(s);
}
No, what Adrien has is sufficient to traverse statements as well. TraverseDecl(tu_decl) will traverse the entire AST, which includes statements and expressions. That's why you have the RecursiveASTVisitor: it figures out how to visit all of the subchildren for you so you just have to worry about implementing VisitStmt and figuring out what to do on all of the statements in the file.
I am still a bit confused.
Do you mean implement VisitCallExpr()? I have that implemented and it does not run. VisitStmt() has a implmentation that only returns true, does this mean its not as simple as you said before?
Better yet, am I missing a example or something that maybe I could hack away at?
Thanks for putting up with this
<https://github.com/jcranmer/dxr/blob/clang/xref-tools/cxx-clang/dxr-index.cpp> is an example plugin that I'm using for my current project (a smart source code reference generator).
That is the same file from before and still does not help me. It does not look like statements inherit declarations so I think I need something more than that.