Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Clang LibTooling multiple times

Minimul source that use Clang LibTooling which is a very common way:

#include "pch.h"

#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
#include "clang/Driver/Options.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include <iostream>

using namespace std;
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
using namespace llvm;

class ExampleVisitor : public RecursiveASTVisitor<ExampleVisitor> {
public:
    explicit ExampleVisitor(CompilerInstance *CI) {}
};

class ExampleASTConsumer : public ASTConsumer {
private:
    CompilerInstance *CI;
public: 
    explicit ExampleASTConsumer(CompilerInstance *CI) : CI(CI) {}   
    virtual void HandleTranslationUnit(ASTContext &Context) {
        ExampleVisitor(CI).TraverseDecl(Context.getTranslationUnitDecl());
    }
};

class ExampleFrontendAction : public ASTFrontendAction {
public:
    virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) {
        return  std::unique_ptr<ASTConsumer>(new ExampleASTConsumer(&CI)); 
    }
};

void run(int argc, const char **argv, llvm::cl::OptionCategory& tc) {
    CommonOptionsParser op(argc, argv, tc);
    ClangTool Tool(op.getCompilations(), op.getSourcePathList());
    std::cout <<"getSourcePathList.size="<< op.getSourcePathList().size()<<"\n";
    int result = Tool.run(newFrontendActionFactory<ExampleFrontendAction>().get()); 
}

int main(int argc, const char **argv) {
    llvm::cl::OptionCategory tc1("c1");
    llvm::cl::OptionCategory tc2("c2");
    llvm::cl::OptionCategory tc3("c3");
    run(argc, argv,tc1);
    run(argc, argv,tc2);
    run(argc, argv,tc3);
    std::cin.get();
    return 0;
}

the parameters to debug the application is:

"the_only_source_file_to_scan.cpp" --

which is fine.

The output is (from the method "run" above main()):

getSourcePathList.size=1
getSourcePathList.size=2
getSourcePathList.size=3

The problem is that main() calls run() 3 times with the same above parameter which contains only 1 source file to scan, but each time the size of the source-to-scan list stored in CommonOptionsParser increase by one (every item in the list is the same file input from argv), it just seems to append the source file to scan to the list each time.

Everything above is saved in newly created temporary variables in each run, then how and why does LibTooling keep states of the last run and how to "reset" these states?

like image 579
jw_ Avatar asked Nov 06 '22 10:11

jw_


1 Answers

use FixedCompilationDatabase could circumvent this problem, it can run multiple clangTool in one process

like image 80
Abao Zhang Avatar answered Nov 15 '22 06:11

Abao Zhang