使用 Clang LibTooling 的 Minimul 源代码,这是一种非常常见的方式:
#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_only_source_file_to_scan.cpp" --
这很好。
输出是(来自 main() 上面的方法“run”):
getSourcePathList.size=1
getSourcePathList.size=2
getSourcePathList.size=3
问题是 main() 使用相同的上述参数调用 run() 3 次,其中仅包含要扫描的 1 个源文件,但每次存储在 CommonOptionsParser 中的源扫描列表的大小都会增加一(每个项目在该列表是来自 argv 的相同文件输入),它似乎只是每次都将要扫描的源文件附加到列表中。
以上所有内容都保存在每次运行中新创建的临时变量中,那么 LibTooling 如何以及为什么保持上次运行的状态以及如何“重置”这些状态?