【问题标题】:finding nested loops with Clang AST StatementMatcher使用 Clang AST StatementMatcher 查找嵌套循环
【发布时间】:2016-04-27 04:50:51
【问题描述】:

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

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

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

现在我可以找到下面带有匹配器的循环,它不能处理多个嵌套循环和变量(从 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:如果它更容易,我正在寻找完美的嵌套循环,如上,内部循环周围没有 {}。

【问题讨论】:

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


    【解决方案1】:

    没有办法(据我所知)匹配 N 嵌套 for 循环,而不为您想要匹配的每个可能的深度 N 创建 N 个匹配器。 例如

    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 语句时的 Match 回调

    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
    

    【讨论】:

    • 您能否也为访问者提供一个模拟实现。用户可以同时查看这两种方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 2018-01-06
    • 1970-01-01
    相关资源
    最近更新 更多