首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何多次使用Clang LibTooling

如何多次使用Clang LibTooling
EN

Stack Overflow用户
提问于 2020-01-04 16:13:06
回答 3查看 282关注 0票数 5

使用Clang LibTooling的最小源码,这是一种非常常见的方式:

代码语言:javascript
复制
#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;
}

用于调试应用程序的参数为:

代码语言:javascript
复制
"the_only_source_file_to_scan.cpp" --

这很好。

输出是(来自main()上面的"run“方法):

代码语言:javascript
复制
getSourcePathList.size=1
getSourcePathList.size=2
getSourcePathList.size=3

问题是,main()调用run() 3次,上面的参数相同,它只包含一个要扫描的源文件,但每次存储在CommonOptionsParser中的要扫描的源文件列表的大小增加1(列表中的每个项目都是从argv输入的相同文件),它似乎每次都会将要扫描的源文件附加到列表中。

在每次运行中,上面的所有内容都保存在新创建的临时变量中,那么LibTooling如何以及为什么保持上次运行的状态,以及如何“重置”这些状态?

EN

回答 3

Stack Overflow用户

发布于 2021-09-01 02:54:14

使用FixedCompilationDatabase可以绕过这个问题,它可以在一个进程中运行多个clangTool

票数 1
EN

Stack Overflow用户

发布于 2021-09-04 08:35:20

上面代码使用CommonOptionsParser,它的代码在

代码语言:javascript
复制
clang\lib\Tooling\CommonOptionsParser.cpp

在CommonOptionsParser::init方法中有:

代码语言:javascript
复制
  static cl::list<std::string> SourcePaths(...);

每次调用都会将其源代码添加到此静态变量中。因此,正是这个局部静态变量导致了对先前调用的记忆。在每次调用中,这个局部静态变量都会被cl::ParseCommandLineOptions以某种未知的方式修改,因为它根本不会传递到cl::ParseCommandLineOptions中。在SourcePaths被修改之后(即当前调用的源代码被添加到可能已经包含先前调用的源代码的SourcePaths中),它最终被复制到一个实例变量中。

顺便说一句,@AbaoZhang的提示帮助我找到了位置,实际上CommonOptionsParser::init内部使用了FixedCompilationDatabase,但不是针对上述情况。

票数 0
EN

Stack Overflow用户

发布于 2021-11-13 14:16:01

代码语言:javascript
复制
static cl::list<std::string> SourcePaths(...);

@jw_是的,这段代码出了问题。

你可以解决这个问题。

代码语言:javascript
复制
for (auto iter = llvm::cl::AllSubCommands->OptionsMap.begin(); iter != llvm::cl::AllSubCommands->OptionsMap.end(); iter++)
{
    iter->getValue()->setDefault();
}
for (auto iter = llvm::cl::AllSubCommands->PositionalOpts.begin(); iter != llvm::cl::AllSubCommands->PositionalOpts.end(); iter++)
{
    (*iter)->setDefault();
}
for (auto iter = llvm::cl::AllSubCommands->SinkOpts.begin(); iter != llvm::cl::AllSubCommands->SinkOpts.end(); iter++)
{
    (*iter)->setDefault();
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59589065

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档