Найти If-условия с помощью Clang

Я пытаюсь найти условия if в C-коде, используя Clang.

До сих пор я научился находить объявления с помощью HandleTopLevelDecl().

Сейчас я пытаюсь найти функцию, похожую на HandleTopLevelDecl(), но обрабатывающую условия If.

У меня вопрос, на правильном ли я пути? есть ли функция, которая может это сделать?

А если нет, то что посоветуете мне делать?

Спасибо.


person M.Nour    schedule 31.08.2014    source источник
comment
Есть много видов заявлений. Объявления — это один тип, операторы перехода — другой вид. Может, надо поискать где-нибудь повыше?   -  person Kerrek SB    schedule 31.08.2014
comment
Было бы полезно, если бы вы объяснили, чего вы пытаетесь достичь после того, как нашли условия if. Я могу придумать методы, которые просто сканируют исходный код вплоть до изучения созданного машинного кода, в зависимости от того, какова ваша реальная цель [эти решения могут включать или не включать лязг, опять же, в зависимости от того, что вы на самом деле пытаетесь делать]   -  person Mats Petersson    schedule 31.08.2014
comment
Мне нужно знать доступ для чтения/записи к переменным внутри if-условий. Например: Если(у==1) х=2; иначе z=3; Теперь я знаю, что либо у x есть доступ на запись, либо у z есть доступ на запись не одновременно, и мне нужно знать это из кода. Таким образом, первый шаг в этом — найти область действия If-условий, а затем найти тип доступа для переменных, включая: x++, func(x) ... и т. д..   -  person M.Nour    schedule 01.09.2014


Ответы (2)


С помощью этого замечательного курса: 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;
}
person M.Nour    schedule 02.09.2014

В clang есть специальные функции для всех видов Stmts и Decls. В данном конкретном случае это будет VisitIfStmt. Убедитесь, что IfStmt включен в RecusiveASTVisitor.h.

РекурсивныйASTVisitor.h -

#define STMT(CLASS, PARENT)                                                    \
bool WalkUpFrom##CLASS(CLASS *S) {                                           \
  TRY_TO(WalkUpFrom##PARENT(S));                                             \
  TRY_TO(Visit##CLASS(S));                                                   \
  return true;                                                               \
}                                                                            \
bool Visit##CLASS(CLASS *S) { return true; }
#include "clang/AST/StmtNodes.inc"

clang/AST/StmtNodes.inc -

#ifndef IFSTMT
#  define IFSTMT(Type, Base) STMT(Type, Base)
#endif
IFSTMT(IfStmt, Stmt)
#undef IFSTMT

Вместе они создают функцию VisitIfStmt(IfStmt*) в классе.

person shraiysh    schedule 14.10.2019