使用 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 ptr
从 chainedIncrement
函数到 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");
我正在尝试使用 Clang AST 构建调用图。
有没有办法以某种方式 link 将函数的参数转换为内部函数调用的参数?
例如,给定以下函数:
void chainedIncrement(int *ptr) {
simplePointerIncr(ptr);
for (int i=0;i<3;i++) {
simplePointerIncr(ptr);
}
}
我正在寻找一种方法能够 link ptr
从 chainedIncrement
函数到 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");