【问题标题】:Building call graphs using Clang AST, link parameters to arguments使用 Clang AST 构建调用图,将参数链接到参数
【发布时间】:2018-12-18 09:52:17
【问题描述】:

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

有没有办法以某种方式将函数的参数链接到内部函数调用的参数?

例如,给定以下函数:

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

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

我正在寻找一种能够将 ptrchainedIncrement 函数链接到 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");

【问题讨论】:

  • 你能指定你想要的“调用图”的类型吗? AST只是源代码的一种表示,可以构造一个Matcher来匹配函数中的两个simplePointerIncr()。但是如果你想要信息就更复杂了,例如第二个调用是在 3 次迭代的 for 循环中等

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


【解决方案1】:

这是一个简化的例子:

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

【讨论】:

  • 谢谢,我已经添加了我的解决方案
【解决方案2】:

有一个匹配器叫做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");

【讨论】:

    猜你喜欢
    • 2012-03-25
    • 1970-01-01
    • 1970-01-01
    • 2012-04-17
    • 2017-10-04
    • 2021-12-21
    • 2023-03-04
    • 1970-01-01
    • 2017-01-11
    相关资源
    最近更新 更多