簡體   English   中英

如何將Clang置於C ++模式?

[英]How do I put Clang into C++ mode?

我正在使用Clang開發AST變壓器。 它應該將文件名作為輸入,對該文件中的代碼執行一些轉換,並返回轉換后的代碼。 它基於Eli Bendersky的一個有用的例子

這是代碼:

std::string transform(std::string fileName) {

  // CompilerInstance will hold the instance of the Clang compiler for us,
  // managing the various objects needed to run the compiler.
  CompilerInstance compilerInstance;

  compilerInstance.createDiagnostics();

  auto& langOpts = compilerInstance.getLangOpts();
  langOpts.CPlusPlus = true;

  // Initialize target info with the default triple for our platform.
  auto TO = std::make_shared<TargetOptions>();
  TO->Triple = llvm::sys::getDefaultTargetTriple();
  TargetInfo* targetInfo =
      TargetInfo::CreateTargetInfo(compilerInstance.getDiagnostics(), TO);
  compilerInstance.setTarget(targetInfo);

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

  compilerInstance.createSourceManager(fileManager);
  auto& sourceManager = compilerInstance.getSourceManager();

  compilerInstance.createPreprocessor(TU_Module);
  compilerInstance.createASTContext();

  // A Rewriter helps us manage the code rewriting task.
  auto rewriter = clang::Rewriter(sourceManager, compilerInstance.getLangOpts());

  // Set the main file handled by the source manager to the input file.
  const FileEntry* inputFile = fileManager.getFile(fileName);
  sourceManager.setMainFileID(
      sourceManager.createFileID(inputFile, SourceLocation(), SrcMgr::C_User));
  compilerInstance.getDiagnosticClient().BeginSourceFile(
      compilerInstance.getLangOpts(), &compilerInstance.getPreprocessor());

  // Create an AST consumer instance which is going to get called by
  // ParseAST.
  MyASTConsumer consumer(rewriter);

  // Parse the file to AST, registering our consumer as the AST consumer.
  clang::ParseAST(
    compilerInstance.getPreprocessor(), 
    &consumer, 
    compilerInstance.getASTContext());

  // At this point the rewriter's buffer should be full with the rewritten
  // file contents.
  const RewriteBuffer* buffer = rewriter.getRewriteBufferFor(sourceManager.getMainFileID());

  return std::string(buffer->begin(), buffer->end());
}

這是我的輸入程序, negate.cpp

bool negate(bool b) {
    if (b) {
        return false;
    } else {
        return true;
    }
}

當我對此代碼運行transform ,我收到以下錯誤:

negate.cpp:1:1: error: unknown type name 'bool'
bool negate(bool b) {
^

這告訴我它在C模式下工作,而不是C ++模式。 為了確認,我用int替換bool ,用1替換true ,用0替換false

int negate(int b) {
    if (b) {
        return 0;
    } else {
        return 1;
    }
}

這很有用,所以我的問題是:

如何將Clang CompilerInstance放入C ++模式?


更新:

我試着改變調用,但沒有運氣:

  auto& langOpts = compilerInstance.getLangOpts();
  langOpts.CPlusPlus = true;
  langOpts.CPlusPlus11 = true;

  auto* compilerInvocation = new CompilerInvocation();

  compilerInvocation->setLangDefaults(
    langOpts, 
    clang::InputKind::IK_CXX, 
    LangStandard::lang_gnu11);

在執行編譯器之前,必須使用getInvocation() / setInvocation()方法檢查/設置CompilerInvocation結構。 此結構定義語言選項(調用約定,垃圾收集,...),語言類型(C,CXX,Asm,ObjC,...),目標三元組,預處理器選項和語言標准。 它使用setLangDefaults()方法設置。

這是InputKind類,它包含您要解析的語言。

如文檔中所述, setLangDefaults() API

設置一些僅依賴於輸入類型的屬性

通過檢查源代碼,您可以看到以下構造函數調用層次結構:

  • CompilerInstance()
  • CompilerInvocation()
  • CompilerInvocationBase()
  • LangOptions()

LangOptions()構造函數中,您可以看到沒有設置特定/默認語言( LangOptions.def )。 因此需要通過setLangDefaults()特定的API。

你應該這樣:

std::string transform(std::string fileName) {

  CompilerInstance compilerInstance;
  compilerInstance.createDiagnostics();

  CompilerInvocation & invocation = compilerInstance.getInvocation();

  // Initialize target info with the default triple for our platform.
  auto TO = std::make_shared<TargetOptions>();
  TO->Triple = llvm::sys::getDefaultTargetTriple();
  TargetInfo* targetInfo =
      TargetInfo::CreateTargetInfo(compilerInstance.getDiagnostics(), TO);
  compilerInstance.setTarget(targetInfo);

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

  compilerInstance.createSourceManager(fileManager);
  auto& sourceManager = compilerInstance.getSourceManager();

  LangOptions langOpts; 
  langOpts.GNUMode = 1;  
  langOpts.CXXExceptions = 1;  
  langOpts.RTTI = 1;  
  langOpts.Bool = 1;   // <-- Note the Bool option here !
  langOpts.CPlusPlus = 1;  
  PreprocessorOptions &PPOpts = compilerInstance.getPreprocessorOpts();

  invocation.setLangDefaults(langOpts, 
                             clang::IK_CXX,
                             TO->Triple, 
                             PPOpts,
                             clang::LangStandard::lang_cxx0x); 


  compilerInstance.createPreprocessor(TU_Module);
  compilerInstance.createASTContext();

  // A Rewriter helps us manage the code rewriting task.
  auto rewriter = clang::Rewriter(sourceManager, compilerInstance.getLangOpts());

  // Set the main file handled by the source manager to the input file.
  const FileEntry* inputFile = fileManager.getFile(fileName);
  sourceManager.setMainFileID(
      sourceManager.createFileID(inputFile, SourceLocation(), SrcMgr::C_User));
  compilerInstance.getDiagnosticClient().BeginSourceFile(
      compilerInstance.getLangOpts(), &compilerInstance.getPreprocessor());

  // Create an AST consumer instance which is going to get called by
  // ParseAST.
  MyASTConsumer consumer(rewriter);

  // Parse the file to AST, registering our consumer as the AST consumer.
  clang::ParseAST(
    compilerInstance.getPreprocessor(), 
    &consumer, 
    compilerInstance.getASTContext());

  // At this point the rewriter's buffer should be full with the rewritten
  // file contents.
  const RewriteBuffer* buffer = rewriter.getRewriteBufferFor(sourceManager.getMainFileID());

  return std::string(buffer->begin(), buffer->end());
}

在clang教程CIRewriter.cpp中引用 ,這似乎也有點過時了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM