2016-11-21 10 views
0

私は以下の内容の約100行の単一のcppファイルを持っています。コンパイル時に複数のFrontendActionを実行する場合

#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関数は非常に簡単で、最後に関数を2回呼び出します。この関数が呼び出される2回目に、私はアサーションの失敗を得て、私を驚かせます。

ファイル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) 

問題がある:私は上の複数のアクションを実行したいですコンパイラのインスタンス。アサーションの失敗を起こさないためには、どのような状態をリセットする必要がありますか?

自分で構築するには、静的なclangとllvmライブラリにリンクする必要があります。興味があればここでCMakeLists.txtファイルがあります:

add_clang_executable(clangapitest clangapitest.cpp) 
target_link_libraries(clangapitest clangFrontend) 

私は新しいディレクトリpath/to/llvm/tools/clang/tools/clangapitestを作り、余分なラインadd_subdirectory(clangapitest)を持っているpath/to/llvm/tools/clang/tools/CMakeLists.txtにCMakeLists.txtファイルを調整しました。

答えて

0

まあ、私はそれを理解しました。 doxygen documentation of CompilerInstance::ExecuteActionには、起動オブジェクトと診断オブジェクトが初期化されていて、他の状態がない(したがって、ソースもファイルマネージャもない)ことが示されています。だから次の作品:

SyntaxOnlyAction action; 
instance.setSourceManager(nullptr); 
instance.createDiagnostics(); 
if (instance.ExecuteAction(action)) 
{ 
    std::cout << "Action succeeded.\n"; 
} 
else 
{ 
    std::cout << "Action failed.\n"; 
} 
関連する問題