c++ - 准备调用 ParseAST。 fatal error

标签 c++ parsing compiler-construction clang

我正在阅读《LLVM 核心库入门》一书,并尝试实现第 100 页第 4 章:前端 中的示例。但是在代码的最后一行 clang::ParseAST(CI.getSema());:

出错了
[bash@bash book]$ ./book_clang test.c 
fatal error: error opening file '<invalid loc>': 

我应该添加什么来为 ParseAST 做准备?

代码:

#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Support/CommandLine.h"

#include "clang/Basic/Diagnostic.h"

#include "clang/Frontend/CompilerInstance.h"

#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"

#include "llvm/Support/Host.h"
#include <memory>
#include <string>

#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Lex/Preprocessor.h"

#include "clang/AST/ASTConsumer.h"
#include "clang/Frontend/ASTConsumers.h"

#include "llvm/Support/raw_ostream.h"

#include "clang/Parse/ParseAST.h"

#include "clang/AST/ASTContext.h"


static llvm::cl::opt<std::string> fileName(llvm::cl::Positional, llvm::cl::desc("Input file"), llvm::cl::Required);

int main(int argc, char **argv)
{
    llvm::cl::ParseCommandLineOptions(argc, argv, "My simple front end\n");
    clang::CompilerInstance CI;
    clang::DiagnosticOptions diagnosticOptions;
    CI.createDiagnostics();

    std::shared_ptr<clang::TargetOptions> PTO = std::make_shared<clang::TargetOptions>();
    PTO->Triple = llvm::sys::getDefaultTargetTriple();
    clang::TargetInfo *PTI = clang::TargetInfo::CreateTargetInfo(CI.getDiagnostics(), PTO);
    CI.setTarget(PTI);

    CI.createFileManager();//References getFileSystemOpts(), clang::vfs::getRealFileSystem(), hasVirtualFileSystem(), and setVirtualFileSystem().
    CI.createSourceManager( CI.getFileManager());//References getDiagnostics().
    CI.createPreprocessor(clang::TU_Complete);
    CI.getPreprocessorOpts().UsePredefines = false;

    std::unique_ptr< clang::ASTConsumer > astConsumer = clang::CreateASTPrinter(NULL, "");
    CI.setASTConsumer(std::move(astConsumer));

    CI.createASTContext();
    CI.createSema(clang::TU_Complete, NULL);//after getASTConsumer(), getASTContext(), and getPreprocessor().
    const clang::FileEntry *file =    CI.getFileManager().getFile(fileName);
    if (!file) {
        llvm::errs() << "File not found: " << fileName;
        return 1;
    }
    CI.getSourceManager().createFileID(file, clang::SourceLocation(), clang::SrcMgr::C_User);


    CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0);
    clang::ParseAST(CI.getSema());
    // Print AST statistics
//   CI.getASTContext().PrintStats();
//  CI.getASTContext().Idents.PrintStats();

    return 0;
}

对于可执行文件需要传递c文件,例如: 测试.c

int main() {
char *msg = "Hello, world!\n";
write(1, msg, 14);
return 0;
}

最佳答案

问题解决了。需要为CompilerInstenceSourceManager

设置MainFileID
clang::FileID mainFileID = CI.getSourceManager().createFileID(file,    clang::SourceLocation(), clang::SrcMgr::C_User);
CI.getSourceManager().setMainFileID(mainFileID);

问题是 clang::ParseAST 调用(SSema)S.getPreprocessor().EnterMainSourceFile() ; 调用 SourceMgr.getMainFileID();

void Preprocessor::EnterMainSourceFile() {
assert(NumEnteredSourceFiles == 0 && "Cannot reenter the main file!");
FileID MainFileID = SourceMgr.getMainFileID();

但是 MainFileID 没有设置

更正后的完整代码是:

#include "llvm/Support/CommandLine.h"

#include "clang/Basic/Diagnostic.h"

#include "clang/Frontend/CompilerInstance.h"

#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"

#include "llvm/Support/Host.h"
#include <memory>
#include <string>

#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Lex/Preprocessor.h"

#include "clang/AST/ASTConsumer.h"
#include "clang/Frontend/ASTConsumers.h"

#include "llvm/Support/raw_ostream.h"

#include "clang/Parse/ParseAST.h"

#include "clang/AST/ASTContext.h"


static llvm::cl::opt<std::string> fileName(llvm::cl::Positional, llvm::cl::desc("Input file"), llvm::cl::Required);

int main(int argc, char **argv)
{      
    llvm::cl::ParseCommandLineOptions(argc, argv, "My simple front end\n");

    clang::CompilerInstance CI;
    clang::DiagnosticOptions diagnosticOptions;
    CI.createDiagnostics();

    std::shared_ptr<clang::TargetOptions> PTO = std::make_shared<clang::TargetOptions>();
    PTO->Triple = llvm::sys::getDefaultTargetTriple();
    clang::TargetInfo *PTI = clang::TargetInfo::CreateTargetInfo(CI.getDiagnostics(), PTO);
    CI.setTarget(PTI);

    CI.createFileManager();//References getFileSystemOpts(), clang::vfs::getRealFileSystem(), hasVirtualFileSystem(), and setVirtualFileSystem().
    CI.createSourceManager( CI.getFileManager());//References getDiagnostics().
    CI.createPreprocessor(clang::TU_Complete);
    CI.getPreprocessorOpts().UsePredefines = false;

    std::unique_ptr< clang::ASTConsumer > astConsumer = clang::CreateASTPrinter(NULL, "");
    CI.setASTConsumer(std::move(astConsumer));

    CI.createASTContext();
    CI.createSema(clang::TU_Complete, NULL);//after getASTConsumer(), getASTContext(), and getPreprocessor().
    const clang::FileEntry *file = CI.getFileManager().getFile(fileName);
    if (!file) {
            llvm::errs() << "File not found: " << fileName;
            return 1;
    }
    clang::FileID mainFileID = CI.getSourceManager().createFileID(file, clang::SourceLocation(), clang::SrcMgr::C_User);
    CI.getSourceManager().setMainFileID(mainFileID);


    CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0);
    clang::ParseAST(CI.getSema());
    // Print AST statistics
    CI.getASTContext().PrintStats();
    CI.getASTContext().Idents.PrintStats();

    return 0;
}

关于c++ - 准备调用 ParseAST。 fatal error ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40369401/

相关文章:

c - 为什么编译器在 N 字节边界上对齐 N 字节数据类型?

c++ - 调用显式转换构造函数的 C 风格转换是否正确?

compiler-construction - wxwidgets setup.h“没有这样的文件”

c++ - 如何正确构建 Qt 插件

Javascript 如何在 Web App 中隐藏 Consumer Key 和 Secret?

用于输入数据的 Java 8 Stream 实用程序

javascript - 检查数组元素的第一个字符

c++ - 主函数可以在 C++ 中调用自己吗?

c++ - 为什么迭代器在容器调用分配时不能引用它们所属的容器?

python - ROS CPP 相当于 Python subprocess.call() with shell=True