Reputation: 11
I am working on libtooling with clang. I have developed a tools to find the global variables and where those global variables are referred.
Now, i want to get the function name which uses those Global variables.
Here is the Sample Code
int Var;
int display()
{
Var = 10;
return Var;
}
int main()
{
display();
return 0;
}
Here, i want to get that global variable Var
is referred in Function display
.
How can i get this Output using LibTooling clang? Please Let me know if there is any solution.
Upvotes: 1
Views: 1298
Reputation: 1614
It is possible to do with libTooling
. If you already found DeclRefExpr
nodes that refer to global variables, you can walk up the AST to their FunctionDecl
parents.
On the other hand, walking up the AST requires Clang to construct a mapping from nodes to their parent nodes (which might be pretty expensive for big translation units). Here I've put together a short solution that just finds function referring to global variables and prints their names:
class GlobalVariableFinder final
: public RecursiveASTVisitor<GlobalVariableFinder> {
public:
static bool find(FunctionDecl *CandidateFunction) {
GlobalVariableFinder ActualFinder;
ActualFinder.TraverseDecl(CandidateFunction);
return ActualFinder.Found;
}
bool VisitDeclRefExpr(DeclRefExpr *SymbolUse) {
// we are interested only in variables
if (auto *Declaration = dyn_cast<VarDecl>(SymbolUse->getDecl())) {
Found = Declaration->hasGlobalStorage();
// if we found one global variable use, there is no need in traversing
// this function any further
if (Found) return false;
}
return true;
}
private:
bool Found = false;
};
class VisitingASTConsumer final
: public ASTConsumer,
public RecursiveASTVisitor<VisitingASTConsumer> {
public:
void HandleTranslationUnit(ASTContext &C) {
this->TraverseTranslationUnitDecl(Context->getTranslationUnitDecl());
}
bool VisitFunctionDecl(FunctionDecl *CandidateFunction) {
if (GlobalVariableFinder::find(CandidateFunction)) {
llvm::errs() << CandidateFunction->getQualifiedNameAsString() << "\n";
}
return true;
}
};
If you want to store global variable references, you might want to modify the GlobalVariableFinder
class to include additional logic.
Following solution produces the following output on this snippet of code:
int Var;
int display()
{
Var = 10;
return Var;
}
int foo() {
return Var;
}
int bar() {
return foo();
}
int main()
{
display();
return 0;
}
display
foo
You can notice that it includes only functions that syntactically use global variables. If you want the algorithm to find bar
as well, you'll need to build a call graph of the target program and propagate the information about global variables by the reversed edges of the graph (i.e. from foo
to bar
in our example).
I hope this information is helpful. Happy hacking with Clang!
Upvotes: 1