使用 Clang AST 构建调用图,link 参数到参数

Building call graphs using Clang AST, link parameters to arguments

我正在尝试使用 Clang AST 构建调用图。

有没有办法以某种方式 link 将函数的参数转换为内部函数调用的参数?

例如,给定以下函数:

void chainedIncrement(int *ptr) {
    simplePointerIncr(ptr);

    for (int i=0;i<3;i++) {
        simplePointerIncr(ptr);
    }
}

我正在寻找一种方法能够 link ptrchainedIncrement 函数到 simplePointerIncr 函数的参数。这样做将允许构建调用图。 也许有一种方法可以在对参数和参数调用 getId() 时获得相同的 ID。

我尝试使用以下 AST 匹配器:

functionDecl(hasDescendant(callExpr(callee(functionDecl().bind("calleeFunc")),unless(isExpansionInSystemHeader())).bind("callExpr");)).bind("outerFunc")

似乎参数是 Expr 类型,而函数参数是 ParmVarDecl 类型。 假设参数按原样传递,不修改内部函数,有没有办法以某种方式 link 它们?

谢谢

更新:添加了我的解决方案

有一个名为 forEachArgumentWithParam() 的匹配器。它允许将参数绑定到被调用函数的参数。

另一个匹配器,equalsBoundNode() 允许将外部函数的参数绑定到被调用函数的参数。

auto calleeArgVarDecl = declRefExpr(to(varDecl().bind("callerArg")));

auto innerCallExpr = callExpr(
        forEachArgumentWithParam(calleeArgVarDecl, parmVarDecl().bind("calleeParam")),
        callee(functionDecl().bind("calleeFunc")),unless(isExpansionInSystemHeader())).bind("callExpr");

auto fullMatcher = functionDecl(forEachDescendant(innerCallExpr),forEachDescendant(parmVarDecl(equalsBoundNode("callerArg")).bind("outerFuncParam"))).bind("outerFunc");

这是一个简化的例子:

int add2(int var) {
  return var+2;
}
int caller(int var) {
  add2(var);
  for (int i=0; i<3; i++) {
    add2(var);
  }
  return var;
}
int main(int argc, const char **argv) {
  int ret = 0;
  caller(ret);
  return 0;
}

使用 Clang-query 显示匹配器结果:

clang-query> match callExpr(hasAnyArgument(hasAncestor(functionDecl(hasName("caller")))))

Match #1:

~/main.cpp:5:3: note: "root" binds here
  add2(var); 
  ^~~~~~~~~ 

Match #2: 

~/main.cpp:7:5: note: "root" binds here 
  add2(var); 
  ^~~~~~~~~ 
2 matches. 

匹配使用函数参数的函数调用caller

有一个名为 forEachArgumentWithParam() 的匹配器。它允许将参数绑定到被调用函数的参数。

另一个匹配器,equalsBoundNode() 允许将外部函数的参数绑定到被调用函数的参数。

auto calleeArgVarDecl = declRefExpr(to(varDecl().bind("callerArg")));

auto innerCallExpr = callExpr(
        forEachArgumentWithParam(calleeArgVarDecl, parmVarDecl().bind("calleeParam")),
        callee(functionDecl().bind("calleeFunc")),unless(isExpansionInSystemHeader())).bind("callExpr");

auto fullMatcher = functionDecl(forEachDescendant(innerCallExpr),forEachDescendant(parmVarDecl(equalsBoundNode("callerArg")).bind("outerFuncParam"))).bind("outerFunc");