2012-12-22 31 views
10

Tôi đang tìm kiếm số nhận dạng trong tệp nguồn C++ được phân tích bằng Clang. Đó là một hàm có năm đối số được khai báo ngay trong tệp nguồn (không phải là tiêu đề). Khi tôi cố gắng gọi nó với một đối số, Clang đưa ra một lỗi thích hợp - ngay cả toàn văn của khai báo hàm. Nhưng khi tôi cố gắng tìm kiếm nó với API, Clang khẳng định rằng nó không tồn tại.Không thể tìm thấy số nhận dạng thông qua API Clang nhưng Clang có thể tìm thấy số này khi sử dụng

Dưới đây là các mã có liên quan:

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); 

Tôi đã xác minh rằng identinfo không phải là NULL, và rằng sloc cũng không phải là zero.

Tại sao Clang không thể tìm thấy tên của tôi?

Chỉnh sửa: Tôi đã thành công khi thực hiện đủ điều kiện tra cứu tên trong phạm vi toàn cầu. Thật không may, điều này không hoàn toàn giống như thực hiện tra cứu tên không đủ tiêu chuẩn- ví dụ, không có ADL. Clang vẫn khẳng định rằng một tên hàm không đủ tiêu chuẩn không tồn tại.

Chỉnh sửa: Mã đủ điều kiện tương tự nhưng được cấu trúc lại để tránh phụ thuộc vào thư viện Frontend, vì nó có ngữ nghĩa quyền sở hữu cực kỳ có vấn đề và hành động không thực hiện những gì tôi cần.

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

Bạn có thể đăng mã bằng tra cứu đủ điều kiện không? – osgx

+0

@osgx: Đã hoàn thành theo yêu cầu. – Puppy

+0

Phiên bản LLVM + Clang được sử dụng trong mã của bạn là gì? – osgx

Trả lời

5

Rõ ràng, điều này vừa được biết là đã bị hỏng ngay bây giờ. Tôi đã xem xét triển khai thực hiện LookupName và nó phẳng ra không xử lý trường hợp này.

Tôi sẽ phải sống với tra cứu đủ điều kiện ngay bây giờ.

+0

Bạn có thể minh họa thêm một chút không? Trường hợp nào không được xử lý? – osgx

+0

Một trong những nơi được truyền trong Phạm vi là TUScope. – Puppy

Các vấn đề liên quan