我有一个大约100行的cpp文件,其中包含以下内容。
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/FrontendActions.h>
#include <iostream>
// The filename that will be processed (twice).
static const char* FILENAME = "simple.cpp";
// System header locations, you may need to
// adjust these.
static const char* SYSTEM_HEADERS[] =
{
"/usr/include/c++/5.4.0",
"/usr/include/x86_64-linux-gnu/c++/5.4.0",
"/usr/include/c++/5.4.0/backward",
"/usr/local/lib/clang/4.0.0/include",
"/usr/include/x86_64-linux-gnu",
"/usr/include"
};
// Location for builtin headers. You may need to
// adjust this.
static const char* RESOURCE_DIR = "/usr/local/lib/clang/4.0.0";
// Uncomment this to see header search paths.
// #define PRINT_HEADER_SEARCH_PATHS
// Constructs a CompilerInvocation
// that must be fed to a CompilerInstance.
clang::CompilerInvocation* makeInvocation();
// Executes a single SyntaxOnlyAction on
// the given CompilerInstance.
void secondCallThisFunctionFails(clang::CompilerInstance& instance);
int main()
{
using namespace clang;
CompilerInstance instance;
instance.createDiagnostics();
instance.setInvocation(makeInvocation());
instance.getFrontendOpts().Inputs.emplace_back
(
FILENAME,
FrontendOptions::getInputKindForExtension(FILENAME)
);
// First call is OK.
secondCallThisFunctionFails(instance);
// Second call results in assertion failures.
secondCallThisFunctionFails(instance);
return 0;
}
clang::CompilerInvocation* makeInvocation()
{
using namespace clang;
auto invocation = new CompilerInvocation();
invocation->TargetOpts->Triple = llvm::sys::getDefaultTargetTriple();
invocation->setLangDefaults(
*invocation->getLangOpts(),
IK_CXX,
llvm::Triple(invocation->TargetOpts->Triple),
invocation->getPreprocessorOpts(),
LangStandard::lang_cxx11);
auto& headerSearchOpts = invocation->getHeaderSearchOpts();
#ifdef PRINT_HEADER_SEARCH_PATHS
headerSearchOpts.Verbose = true;
#else
headerSearchOpts.Verbose = false;
#endif
headerSearchOpts.UseBuiltinIncludes = true;
headerSearchOpts.UseStandardSystemIncludes = true;
headerSearchOpts.UseStandardCXXIncludes = true;
headerSearchOpts.ResourceDir = RESOURCE_DIR;
for (const auto sytemHeader : SYSTEM_HEADERS)
{
headerSearchOpts.AddPath(sytemHeader, frontend::System, false, false);
}
return invocation;
}
void secondCallThisFunctionFails(clang::CompilerInstance& instance)
{
using namespace clang;
SyntaxOnlyAction action;
if (instance.ExecuteAction(action))
{
std::cout << "Action succeeded.\n";
}
else
{
std::cout << "Action failed.\n";
}
}
如您所见,main函数非常简单,最后调用函数两次。第二次调用这个函数时,我得到一个断言失败,让我感到惊讶。
文件simple.cpp
的内容是
// test wether we actually configured C++11 or greater
#include <thread>
int main() { return 0; }
我的机器上的这个程序的输出是:
Action succeeded.
clangapitest: ../tools/clang/lib/Basic/SourceManager.cpp:819: clang::FileID clang::SourceManager::getFileIDLoaded(unsigned int) const: Assertion `0 && "Invalid SLocOffset or bad function choice"' failed.
Aborted (core dumped)
问题是:我想在CompilerInstance上执行多个操作。为了不让断言失败,我需要重置什么状态?
要自己构建它,你必须链接一些静态clang和llvm库。如果感兴趣的话,这里是CMakeLists.txt文件:
add_clang_executable(clangapitest clangapitest.cpp)
target_link_libraries(clangapitest clangFrontend)
我制作了一个新目录path/to/llvm/tools/clang/tools/clangapitest
并调整了path/to/llvm/tools/clang/tools/CMakeLists.txt
中的CMakeLists.txt文件,以增加一行add_subdirectory(clangapitest)
。
答案 0 :(得分:1)
好吧,我明白了。在 CompoloInstance :: ExecuteAction的doxygen文档中,它声明了一个调用对象和诊断对象应该已经初始化,没有其他状态(因此没有源或文件管理器)。因此,以下工作:
&#xA;&#xA; SyntaxOnlyAction操作;&#xA; instance.setSourceManager(nullptr);&#xA; instance.createDiagnostics();&#xA ; if(instance.ExecuteAction(action))&#xA; {&#xA; std :: cout&lt;&lt; “行动成功。\ n”;&#xA;}&#xA;其他&#xA; {&#xA; std :: cout&lt;&lt; “行动失败。\ n”;&#xA;}&#xA;
&#xA;