使用Clang AST StatementMatcher查找嵌套循环

时间:2016-04-27 04:50:52

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

我尝试使用clang StatementMatcher 在嵌套循环中查找变量

for(i=0;i<10;i++)
   for(j=0;j<10;j++)
     //I have i and j

我不确定它是否可以使用单个匹配器处理任何级别的嵌套循环,但如果它可以的话会很好。

现在我可以找到下面有matcher的循环,它不能处理多个嵌套循环和变量(从llvm示例中得到这个)。如果有人可以帮助我,我感激不尽。

StatementMatcher LoopMatcher =
    forStmt(hasLoopInit(declStmt(
hasSingleDecl(varDecl(hasInitializer(integerLiteral(equals(0))))
                              .bind("initVarName")))),
        hasIncrement(unaryOperator(
            hasOperatorName("++"),
            hasUnaryOperand(declRefExpr(
                to(varDecl(hasType(isInteger())).bind("incVarName")))))),
        hasCondition(binaryOperator(
            hasOperatorName("<"),
            hasLHS(ignoringParenImpCasts(declRefExpr(
                to(varDecl(hasType(isInteger())).bind("condVarName"))))),
            hasRHS(expr(hasType(isInteger())))))).bind("forLoop");

ps:如果它变得更容易,我正在寻找像上面那样完美的嵌套循环,内圈周围没有{}。

1 个答案:

答案 0 :(得分:0)

没有办法(据我所知)匹配N-nested for循环而不为每个可能的深度N创建N匹配器。 E.g。

StatementMatcher forLoopLevel2 = forStmt(<someMatcher>, hasDescendant(forStmt())).bind("loop2");

StatementMatcher forLoopLevel3 = forStmt(<someMatcher>, hasDescendant(forStmt(<someMatcher>,hasDescendant(forStmt())))).bind("loop3");

绝对不值得做!

我建议为单个for循环创建一个匹配器,并且对于N级嵌套for循环(每个for循环一次),回调将被简单地触发N次。然后,您可以从每个回调实例中检索变量名称,这将适用于任何深度。这是一些代码..

主要

int main(int argc, const char **argv) {

    MyPrinter Printer;
    MatchFinder Finder;

  StatementMatcher forLoopMatcher = forStmt(hasLoopInit(declStmt(hasSingleDecl(varDecl().bind("initVar")))),
  hasCondition(binaryOperator(hasLHS(ignoringParenImpCasts(declRefExpr(to(varDecl().bind("condVar"))))))),
  hasIncrement(unaryOperator(hasUnaryOperand(declRefExpr(to(varDecl().bind("incVar"))))))
  ).bind("loop");

    Finder.addMatcher(forLoopMatcher, &Printer);

    return Tool.run(newFrontendActionFactory(&Finder).get());
}

确保循环初始化,条件化和递增相同变量的方法。

static bool areSameVariable(const ValueDecl *First, const ValueDecl *Second) {
    return First && Second && First->getCanonicalDecl() == Second->getCanonicalDecl();
}

每当找到for语句时匹配回调

class MyPrinter : public MatchFinder::MatchCallback {
public:
    virtual void run(const MatchFinder::MatchResult &Result) {
      ASTContext *context = Result.Context;

      if(const ForStmt *F = Result.Nodes.getNodeAs<clang::ForStmt>("loop")){
        const VarDecl *initVar = Result.Nodes.getNodeAs<clang::VarDecl>("initVar");
        const VarDecl *condVar = Result.Nodes.getNodeAs<clang::VarDecl>("condVar");
        const VarDecl *incVar = Result.Nodes.getNodeAs<clang::VarDecl>("incVar");

        if(areSameVariable(initVar,condVar) && areSameVariable(initVar, incVar)){
          string name = initVar->getNameAsString();
          outs() << "Variable name is: " + name + "\n";
        }
      }
    }
};

示例输入文件:

int main(void) {
    for(int a=0; a<10; a++){
        for(int b=0; b<10; b++){

        }
    }
    return 0;
}

输出

Variable name is: a
Variable name is: b