简体   繁体   中英

How to get all the function names where the global variables are used?

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.

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 (ie from foo to bar in our example).

I hope this information is helpful. Happy hacking with Clang!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM