如何获取使用全局变量的所有函数名称?

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

本文关键字:函数 全局变量 何获取 获取      更新时间:2023-10-16

我正在研究带有 clang 的 libtooling。我开发了一个工具来查找全局变量以及这些全局变量的引用位置。

现在,我想获取使用这些全局变量的函数名称。

这是示例代码

int Var;
int display()
{
Var = 10;
return Var;
}
int main()
{
display();
return 0;
}

在这里,我想获取函数display中引用的全局变量Var

如何使用 LibTooling 叮当声获得此输出?如果有任何解决方案,请告诉我。

可以用libTooling.如果已经找到引用全局变量的DeclRefExpr节点,则可以将 AST 向上移动到其FunctionDecl父节点。

另一方面,沿着 AST 向上走需要 Clang 构建从节点到其父节点的映射(这对于大型翻译单元来说可能非常昂贵(。在这里,我整理了一个简短的解决方案,它只找到引用全局变量的函数并打印它们的名称:

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;
}
};

如果要存储全局变量引用,则可能需要修改GlobalVariableFinder类以包含其他逻辑。

以下解决方案在此代码段上生成以下输出:

int Var;
int display()
{
Var = 10;
return Var;
}
int foo() {
return Var;
}
int bar() {
return foo();
}
int main()
{
display();
return 0;
}
display
foo

您可以注意到,它仅包含语法上使用全局变量的函数。如果你想让算法也找到bar,你需要构建目标程序的调用图,并通过图的反转边缘传播有关全局变量的信息(即在我们的示例中从foo传播到bar(。

我希望这些信息对您有所帮助。与叮当一起快乐!