无法使用llvm和clang解析C ++ [英] failing to parse C++ using llvm and clang

查看:243
本文介绍了无法使用llvm和clang解析C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用llvm编写一个小工具来解析C和C ++代码,但我似乎无法成功解析C ++。

I'm writing a little tool with llvm to parse C and C++ code, but I can't seem to get it to successfully parse C++ at all. I'm probably missing something obvious.

这是我到目前为止:

#include <iostream>

#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"

#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/LangStandard.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/DirectoryLookup.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Parse/ParseAST.h"

class MyASTConsumer : public clang::ASTConsumer {
    public:
        bool HandleTopLevelDecl(clang::DeclGroupRef d);
        virtual ~MyASTConsumer() { }
};

bool MyASTConsumer::HandleTopLevelDecl(clang::DeclGroupRef d)
{
    for(auto ii = d.begin(); ii != d.end(); ii++)
    {
        printf("decl type: %s\n", (*ii)->getDeclKindName()); 
        auto namedDecl = llvm::dyn_cast<clang::NamedDecl>(*ii);
        if(namedDecl)
        {
            printf("name: %s\n", namedDecl->getName().data());
        }
    }

    return true;
}

int main(int, char **argv)
{
    using clang::CompilerInstance;
    using clang::TargetOptions;
    using clang::TargetInfo;
    using clang::FileEntry;
    using clang::DiagnosticOptions;
    using clang::TextDiagnosticPrinter;
    using clang::SrcMgr::CharacteristicKind;
    using clang::StringRef;
    using clang::DirectoryLookup;
    using llvm::MemoryBuffer;
    using clang::LangOptions;
    using clang::FrontendOptions;
    using clang::LangStandard;
    using clang::CompilerInvocation;
    using clang::InitializePreprocessor;
    using clang::Preprocessor;
    using clang::PreprocessorOptions;
    using clang::HeaderSearch;
    using clang::HeaderSearchOptions;

    CompilerInstance ci;
    DiagnosticOptions diagnosticOptions;
    ci.createDiagnostics();

    CompilerInvocation *invocation = new CompilerInvocation;

    LangOptions &langOpts = ci.getLangOpts();
    langOpts.RTTI = 1;
    langOpts.Bool = 1;
    langOpts.CPlusPlus11 = 1;
    langOpts.GNUKeywords = 1;
    langOpts.CXXExceptions = 1;
    langOpts.POSIXThreads = 1;
    langOpts.SpellChecking = 1;

    invocation->setLangDefaults(langOpts, clang::IK_CXX, LangStandard::lang_gnucxx11);

    ci.setInvocation(invocation);

    llvm::IntrusiveRefCntPtr<TargetOptions> pto( new TargetOptions() );
    pto->Triple = llvm::sys::getDefaultTargetTriple();

    llvm::IntrusiveRefCntPtr<TargetInfo> pti(TargetInfo::CreateTargetInfo(ci.getDiagnostics(), pto.getPtr()));
    ci.setTarget(pti.getPtr());

    ci.createFileManager();
    auto &fileManager = ci.getFileManager();

    ci.createSourceManager(fileManager);

    llvm::IntrusiveRefCntPtr<HeaderSearchOptions> headerSearchOpts( new HeaderSearchOptions() );

    ci.createPreprocessor();
    auto &pp = ci.getPreprocessor();
    pp.setPredefines(builtinMacros);

    HeaderSearch &headerSearch = pp.getHeaderSearchInfo();

    for(auto &inc: builtinIncludePaths)
    {
        auto dirEntry = fileManager.getDirectory(StringRef(inc), true);
        DirectoryLookup dirLookup(dirEntry, CharacteristicKind::C_System, false);
        headerSearch.AddSearchPath (dirLookup, true);
    }

    MyASTConsumer *astConsumer = new MyASTConsumer();
    ci.setASTConsumer(astConsumer);

    ci.createASTContext();

    const FileEntry *pFile = fileManager.getFile(argv[1]);
    auto &sourceManager = ci.getSourceManager();

    sourceManager.createMainFileID(pFile);
    ci.getDiagnosticClient().BeginSourceFile(
        ci.getLangOpts(),
        &pp
    );

    clang::ParseAST(pp, astConsumer, ci.getASTContext());
    ci.getDiagnosticClient().EndSourceFile();

    return 0;
}

它解析C很好,但它的错误出在 namespace 关键字和 externC{块。到目前为止,我被骗了。

It does parse C just fine, but it errors out on the namespace keyword and extern "C" { blocks. So far I'm stumped. If anyone has a clue, something I'm missing, please share.

推荐答案

我相信我找出了问题所在。在调用编译器实例上的很多方法之前,应该在编译器实例上调用 setInvocation ,因为它实际上只是代理调用。

I believe I figured out the problem. You should always call setInvocation on the compiler instance before calling a lot of the methods on the compiler instance, as it actually just proxies to the invocation.

在创建CompilerInvocation对象后,我移动了 setInvocation 调用,现在可以正常工作。

I moved the setInvocation call to right after the CompilerInvocation object is created, and things now work.

这篇关于无法使用llvm和clang解析C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆