2012-12-22 10 views
10

Szukam identyfikatora w pliku źródłowym C++ analizowanym przez Clang. Jest to funkcja, która pobiera pięć argumentów, które są zadeklarowane bezpośrednio w pliku źródłowym (nie nagłówku). Kiedy próbuję wywołać to jednym argumentem, Clang daje odpowiedni błąd - nawet pełny tekst deklaracji funkcji. Ale kiedy próbuję znaleźć to za pomocą API, Clang twierdzi, że nie istnieje.Nie mogę znaleźć identyfikatora za pomocą interfejsu API Clang, ale Clang może go znaleźć po użyciu

Oto odpowiedni kod:

llvm::LLVMContext c; 
clang::CompilerInstance CI; 
llvm::Module m("", c); 
clang::EmitLLVMOnlyAction emit(&c); 
emit.setLinkModule(&m); 

std::string errors; 
llvm::raw_string_ostream error_stream(errors); 
clang::DiagnosticOptions diagopts; 
clang::TextDiagnosticPrinter printer(error_stream, &diagopts); 
llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagids(new clang::DiagnosticIDs); 
clang::DiagnosticsEngine engine(diagids, &diagopts, &printer, false); 
CI.setDiagnostics(&engine); 

clang::TargetOptions target; 
target.Triple = llvm::sys::getDefaultTargetTriple(); 
CI.setTarget(clang::TargetInfo::CreateTargetInfo(engine, &target)); 

CI.getLangOpts().CPlusPlus0x = true; 
CI.getLangOpts().CPlusPlus = true; 

clang::FrontendInputFile f("main.cpp", clang::InputKind::IK_CXX, true); 
emit.BeginSourceFile(CI, f); 

emit.Execute(); 
auto sema = CI.takeSema(); 
auto ast = &CI.getASTContext(); 
CI.resetAndLeakASTContext(); 
emit.EndSourceFile(); 

emit.takeModule(); 
auto identinfo = CI.getPreprocessor().getIdentifierInfo("WriteConsoleW"); 

auto sloc = CI.getSourceManager().getLocForEndOfFile(CI.getSourceManager().translateFile(CI.getFileManager().getFile("main.cpp"))); 
clang::LookupResult lr(*sema, clang::DeclarationName(identinfo), sloc, clang::Sema::LookupNameKind::LookupOrdinaryName); 
auto result = sema->LookupName(lr, sema->TUScope); 

I sprawdzeniu, że nie jest NULL identinfo, a sloc również nie jest zero.

Dlaczego Clang nie może znaleźć mojego imienia?

Edytuj: Udało mi się wykonać wyszukiwanie nazwy kwalifikowanej w zasięgu globalnym. Niestety nie jest to to samo, co wykonywanie bezwarunkowego sprawdzania nazw - na przykład brak ADL. Clang wciąż twierdzi, że nie ma nazwy niewykwalifikowanej.

Edytuj: Kod kwalifikowany jest podobny, ale refaktoryzowany w celu uniknięcia zależności w bibliotece Frontend, ponieważ ma bardzo wątpliwą semantykę własności, a akcja nie robi tego, czego i tak potrzebuję.

clang::CompilerInstance ci; 
clang::FileSystemOptions fso; 
clang::FileManager fm(fso); 

std::string errors; 
llvm::raw_string_ostream error_stream(errors); 
clang::DiagnosticOptions diagopts; 

llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagids(new clang::DiagnosticIDs); 
clang::DiagnosticsEngine engine(diagids, &diagopts, new clang::TextDiagnosticPrinter(error_stream, &diagopts), false); 

clang::SourceManager sm(engine, fm); 

clang::LangOptions langopts; 
langopts.CPlusPlus = true; 
langopts.CPlusPlus0x = true; 

clang::TargetOptions target; 
target.Triple = llvm::sys::getDefaultTargetTriple(); 
auto targetinfo = clang::TargetInfo::CreateTargetInfo(engine, &target); 

auto headeropts = llvm::IntrusiveRefCntPtr<clang::HeaderSearchOptions>(new clang::HeaderSearchOptions()); 
clang::HeaderSearch hs(headeropts, fm, engine, langopts, targetinfo); 

auto x = llvm::IntrusiveRefCntPtr<clang::PreprocessorOptions>(new clang::PreprocessorOptions()); 
clang::Preprocessor p(x, engine, langopts, targetinfo, sm, hs, ci); 

clang::ASTContext astcon(langopts, sm, targetinfo, p.getIdentifierTable(), p.getSelectorTable(), p.getBuiltinInfo(), 1000); 
clang::CodeGenOptions codegenopts; 
clang::CodeGen::CodeGenModule codegen(astcon, codegenopts, m, llvm::DataLayout(&m), engine); 
CodeGenConsumer consumer(&codegen); 
clang::Sema sema(p, astcon, consumer, clang::TranslationUnitKind::TU_Prefix); 

sm.createMainFileID(fm.getFile(filepath)); 
engine.getClient()->BeginSourceFile(langopts, &p); 
clang::ParseAST(sema); 
codegen.Release(); 
engine.getClient()->EndSourceFile(); 
    /* 
for (auto it = astcon.getTranslationUnitDecl()->decls_begin(); it != astcon.getTranslationUnitDecl()->decls_end(); ++it) { 
    if (auto named = llvm::dyn_cast<clang::NamedDecl>(*it)) { 
     std::cout << named->getNameAsString() << "\n"; 
    } 
}*/ 
clang::LookupResult lr(sema, clang::DeclarationName(p.getIdentifierInfo("f")), sm.getLocForEndOfFile(sm.translateFile(fm.getFile(filepath))), clang::Sema::LookupNameKind::LookupOrdinaryName); 
auto result = sema.LookupQualifiedName(lr, astcon.getTranslationUnitDecl()); 
+0

Czy możesz wpisać kod z kwalifikowanym odnośnikiem? – osgx

+0

@osgx: Zrobione zgodnie z życzeniem. – Puppy

+0

Jaka jest wersja LLVM + Clang używana w kodzie? – osgx

Odpowiedz

5

Wygląda na to, że obecnie jest on uszkodzony. Przejrzałem implementację LookupName, a ona nie radzi sobie z tym przypadkiem.

Na razie będę musiał żyć z kwalifikowanym wyszukiwaniem.

+0

Czy możesz zilustrować nieco więcej? Który przypadek nie jest obsługiwany? – osgx

+0

Ten, w którym przekazywany zakres jest TUScope. – Puppy

Powiązane problemy