c++ - 使用 Clang 查找 If 条件

标签 c++ parsing clang abstract-syntax-tree llvm-clang

我正在尝试使用 Clang 在 C 代码中查找 if 条件。

到目前为止,我所学到的是使用 HandleTopLevelDecl() 查找声明。

我现在要做的是找到一个类似于 HandleTopLevelDecl() 但处理 If-Conditions 的函数。

我的问题是,我走在正确的道路上吗?有没有可以做到这一点的功能?

如果没有,你建议我做什么?

谢谢。

最佳答案

在这个很棒的类(class)的帮助下:http://swtv.kaist.ac.kr/courses/cs453-fall13

特别是这个教程:http://swtv.kaist.ac.kr/courses/cs453-fall13/Clang%20tutorial%20v4.pdf

我已经解决了这个问题。

我需要创建一个 RecursiveASTVisitor 并在访问语句时处理 If 语句。

class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor>
{
public:
    bool VisitStmt(Stmt *s) {

        // Search for If-Statements

        if(isa<IfStmt>(s))
        {
            cerr << "Found IF" << endl;
        }

        return true;
    }

    bool VisitFunctionDecl(FunctionDecl *f) {
        // Print function name
        cerr << f->getNameAsString().c_str() << endl;

        return true;
    }
};

完整代码如下:

#include <cstdio>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <utility>

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Rewrite/Frontend/Rewriters.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace std;


// CompilerInstance
CompilerInstance TheCompInst;

    class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor>
    {
    public:
        bool VisitStmt(Stmt *s) {

            // Search for If-Statements

            if(isa<IfStmt>(s))
            {
                SourceManager &srcmgr = TheCompInst.getSourceManager();

                SourceLocation startLocation = s->getLocStart();
                unsigned int start_lineNum = srcmgr.getExpansionLineNumber(startLocation);

                cerr << "Found IF @ Line: " << start_lineNum << endl;
            }

            return true;
        }

        bool VisitFunctionDecl(FunctionDecl *f) {
            // Print function name
            cerr << f->getNameAsString().c_str() << endl;

            return true;
        }
    };

class MyASTConsumer : public ASTConsumer
{
public:
    MyASTConsumer()
        : Visitor() //initialize MyASTVisitor
    {}

    virtual bool HandleTopLevelDecl(DeclGroupRef DR) {
        for (DeclGroupRef::iterator b = DR.begin(), e = DR.end(); b != e; ++b) {
            // Travel each function declaration using MyASTVisitor
            Visitor.TraverseDecl(*b);
        }
        return true;
    }

private:
    MyASTVisitor Visitor;
};


int main(int argc, char *argv[])
{
    if (argc != 2) {
        llvm::errs() << "Usage: kcov-branch-identify <filename>\n";
        return 1;
    }

    // Diagnostics manage problems and issues in compile 
    TheCompInst.createDiagnostics(NULL, false);

    // Set target platform options 
    // Initialize target info with the default triple for our platform.
    TargetOptions *TO = new TargetOptions();
    TO->Triple = llvm::sys::getDefaultTargetTriple();
    TargetInfo *TI = TargetInfo::CreateTargetInfo(TheCompInst.getDiagnostics(), TO);
    TheCompInst.setTarget(TI);

    // FileManager supports for file system lookup, file system caching, and directory search management.
    TheCompInst.createFileManager();
    FileManager &FileMgr = TheCompInst.getFileManager();

    // SourceManager handles loading and caching of source files into memory.
    TheCompInst.createSourceManager(FileMgr);
    SourceManager &SourceMgr = TheCompInst.getSourceManager();

    // Prreprocessor runs within a single source file
    TheCompInst.createPreprocessor();

    // ASTContext holds long-lived AST nodes (such as types and decls) .
    TheCompInst.createASTContext();

    // A Rewriter helps us manage the code rewriting task.
    Rewriter TheRewriter;
    TheRewriter.setSourceMgr(SourceMgr, TheCompInst.getLangOpts());

    // Set the main file handled by the source manager to the input file.
    const FileEntry *FileIn = FileMgr.getFile(argv[1]);
    SourceMgr.createMainFileID(FileIn);

    // Inform Diagnostics that processing of a source file is beginning. 
    TheCompInst.getDiagnosticClient().BeginSourceFile(TheCompInst.getLangOpts(),&TheCompInst.getPreprocessor());

    // Create an AST consumer instance which is going to get called by ParseAST.
    MyASTConsumer TheConsumer;

    // Parse the file to AST, registering our consumer as the AST consumer.
    ParseAST(TheCompInst.getPreprocessor(), &TheConsumer, TheCompInst.getASTContext());

    return 0;
}

关于c++ - 使用 Clang 查找 If 条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25591013/

相关文章:

c# - GUID 的 COM SAFEARRAY 从 C++ 返回到 C#

c++ - std::list<>::splice 使迭代器无效。理由?

c++ - 是否有类似 map 的容器的实现,以实数作为键,并且可以通过键范围检索一组对象?

c++ - 如何使用libc++ libstdc++混合编译的链接库

c - macOS 和 Linux 下 qsort() 结果存在无法解释的差异

c++ - Spirit X3,这种错误处理方式有用吗?

java - 如何解析一个句子并输出句子的标签和单词?

java - 将整数从用户输入传递到另一个类

html - 解析HTML时的错误处理

c++ - 小型 clang 项目上的 std::terminate() 链接器错误