2

我正在尝试使用 clang 创建一个工具,并且想知道是否可以将包含文件从内存注入到CompilerInstance预处理器。
我的目标是在#include <my_globals.hpp>我的文件中添加一个并动态地包含该文件和适当的内容。所以我有一个ASTFrontendAction这样的:

class MyFrontendAction : public ASTFrontendAction
{
    virtual bool BeginInvocation(CompilerInstance &ci) override{
        auto buffer = llvm::MemoryBuffer::getMemBufferCopy(...);
        ci.createFileManager();
        ci.createSourceManager(ci.getFileManager());
        ci.createPreprocessor(clang::TU_Complete);
        auto& pp = ci.getPreprocessor();
        auto& preprocessorOpts = pp.getPreprocessorOpts();
        preprocessorOpts.clearRemappedFiles();
        preprocessorOpts.addRemappedFile("my_globals.hpp", buffer.release());
        // this seams not to work
        auto& hsi = pp.getHeaderSearchInfo();
        auto& headerSearchOptions = hsi.getHeaderSearchOpts();
        headerSearchOptions.Verbose = true; // this option is used during job

    }
    std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance& ci, StringRef file) override{/* do my parsing */}

};

只要我不包含我的头文件,解析就可以工作。如果我这样做,我会得到一个my_globals.hpp file not found.
所以addRemappedFile不会使这个文件对预处理器可见。我可以添加一些搜索路径,但我怎样才能表明这个文件没有路径?
谁能给我提示我如何解决这个问题。

4

1 回答 1

3

我会回答我自己的问题,也许会有所帮助。虽然PPCallbacks每当预处理器接触文件时都会调用它们,但我发现无法更改内容。所以我的解决方案是提供我自己的FileSystem

class MyFs : public FileSystem{
    ... openFileForRead(const Twine& Path) overwrite
    {
    // in here I create my own File that will contain the data
    // all other functions and when the path is not what I expect I forward it to a FileSystrem
    }
};
class MyFrontendAction : public ASTFrontendAction
{
    virtual bool BeginInvocation(CompilerInstance &ci) override{
        ci.createFileManager(); // now I have a default FS
        llvm::IntrusiveRefCntPtr<vfs::FileSystem> fs(new MyFs(ci.getFileManager().getVirtualFileSystem()));
        ci.setVirtualFileSystem(fs);
        ci.setFileManager(new clang::FileManager(clang::FileSystemOptions{}, fs));
        auto& fm = ci.getFileManager();
        ci.createSourceManager(fm);
        return true;
    }
    std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance& ci, StringRef file) override{/* do my parsing */}

};
于 2017-07-11T13:40:12.033 回答