c++ - 无法通过 Clang API 找到标识符,但 Clang 在使用时可以找到它

标签 c++ clang

我正在 Clang 解析的 C++ 源文件中查找标识符。这是一个带有五个参数的函数,这些参数在源文件(而不是标题)中声明。当我试图用一个参数调用它时,Clang 给出了一个适当的错误——甚至是函数声明的全文。但是当我尝试使用 API 查找它时,Clang 坚持认为它不存在。

相关代码如下:

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

我已验证 identinfo 不为 NULL,并且 sloc 也不为零。

为什么 Clang 找不到我的名字?

编辑:我已经成功地在全局范围内执行合格 名称查找。不幸的是,这与执行非限定名称查找并不完全相同——例如,没有 ADL。 Clang 仍然坚持不存在不合格的函数名。

编辑:限定代码类似但经过重构以避免对前端库的依赖,因为它具有极其可疑的所有权语义,并且该操作无论如何都不能满足我的需要。

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

最佳答案

显然,这只是已知现在被破坏了。我查看了 LookupName 实现,它完全不能处理这种情况。

我现在将不得不接受合格的查找。

关于c++ - 无法通过 Clang API 找到标识符,但 Clang 在使用时可以找到它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13999066/

相关文章:

c++ - 获取寄存器/缓存中的当前值?

c++ - 从派生类的 friend 那里使用基类的 protected 静态函数

c++ - 调用另一个相关对象的 protected 虚函数(用于代理)

c++ - 如何使用 clang 生成类似于 gcc-xml 的元数据输出?

c++ - 用零填充 vector

c++ - Xcode 的 C++ 语言设置的 'Compiler Default' 是什么?

c++ - 使用私有(private)成员初始化静态常量,非整数类成员

c++ - dynamic_cast 到具有未知模板参数的派生类型

c++ - Clang 和 Gcc 不同意实例化后的显式特化

c++ - clang:如何在 OS X 中进行分析时获取源信息