Построение графиков вызовов с использованием Clang AST, привязка параметров к аргументам - PullRequest
0 голосов
/ 18 декабря 2018

Я пытаюсь построить граф вызовов с помощью Clang AST.

Есть ли способ каким-либо образом связать параметры функции с аргументами вызова внутренней функции?

Например,учитывая следующую функцию:

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

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

Я искал способ связать функцию ptr из chainedIncrement с аргументом функции simplePointerIncr.Это позволит построить граф вызовов.Может быть, есть способ получить тот же идентификатор при вызове getId() для параметров и аргументов.

Я попытался использовать следующее сопоставление 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 голосов
/ 13 января 2019

Существует сопоставитель с именем 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");
0 голосов
/ 12 января 2019

Вот упрощенный пример:

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

...