使用Clang AST构建调用图,将参数链接到参数

时间:2018-12-18 09:52:18

标签: clang abstract-syntax-tree llvm-clang

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

是否可以通过某种方式将函数的参数链接到内部函数调用的参数?

例如,给定以下功能:

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

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

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

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

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

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

谢谢

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

有一个名为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");

2 个答案:

答案 0 :(得分:0)

这是一个简化的示例:

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查询显示匹配结果:

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的参数的函数调用匹配

答案 1 :(得分:0)

有一个名为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");