I am working on an AST transformer using Clang. It is supposed to take a file-name as input, perform some transformations to the code in that file, and return the transformed code. It is based on a helpful example from Eli Bendersky.
Here is the code:
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());
}
Here is my input program, negate.cpp
:
bool negate(bool b) {
if (b) {
return false;
} else {
return true;
}
}
When I run transform
on this code I get the following error:
negate.cpp:1:1: error: unknown type name 'bool'
bool negate(bool b) {
^
This suggests to me that it is working in C mode, not C++ mode. To confirm, I replaced bool
with int
, true
with 1
and false
with 0
:
int negate(int b) {
if (b) {
return 0;
} else {
return 1;
}
}
This worked, so my question is:
How do I put a Clang CompilerInstance
into C++ mode?
Update:
I tried changing the invocation, but no luck:
auto& langOpts = compilerInstance.getLangOpts();
langOpts.CPlusPlus = true;
langOpts.CPlusPlus11 = true;
auto* compilerInvocation = new CompilerInvocation();
compilerInvocation->setLangDefaults(
langOpts,
clang::InputKind::IK_CXX,
LangStandard::lang_gnu11);