[英]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.