Building AST at runtime

Hello there,

I’m having a hard time building a simple AST at runtime. I think that only small pieces are missing, but it’s rather difficult for me to find which ones and where.

The code I have has been created by trial and error regarding the CompilerInstance initialization and the ASTDumpAction.
The sema-part was inspired by what happens in https://github.com/tritao/clang/blob/master/lib/Sema/SemaCLI.cpp.

I’m first trying to create a namespace, for a start.

I get the following error mesage from the code:

error: unknown target triple ‘’, please use -triple or -arch

I thought I provided the required triple in the call to clang::TargetInfo::CreateTargetInfo, passing targetOptions, which “Triple” member has been set to “i386-pc-win32” (which was only a guess, since I did not find a reference for the string syntax of a target triple).

Here’s the code:

#include <clang/Frontend/ASTConsumers.h>

#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/CodeGen/CodeGenAction.h>
#include <clang/Tooling/Tooling.h>
#include <clang/Sema/Sema.h>
#include <clang/Lex/Preprocessor.h>
#include <clang/AST/Decl.h>
#include <clang/AST/ASTContext.h>
#include <clang/Basic/FileManager.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/Basic/IdentifierTable.h>
#include <clang/Basic/SourceLocation.h>
#include <llvm/Support/raw_os_ostream.h>
#include
#include

void clang_sandbox ()
{
clang::FileManager fileManager = clang::FileManager (clang::FileSystemOptions ());
auto targetOptions = new clang::TargetOptions ();
targetOptions->Triple = “i386-pc-win32”;

clang::CompilerInstance instance;
instance.createDiagnostics ();
clang::TargetInfo * target (clang::TargetInfo::CreateTargetInfo (instance.getDiagnostics (), targetOptions));
instance.setTarget (target);
instance.createFileManager ();
instance.createSourceManager (fileManager);
instance.createPreprocessor ();
instance.setASTConsumer (clang::CreateASTPrinter (nullptr, llvm::StringRef ()));
instance.createASTContext ();

auto sema = new clang::Sema (instance.getPreprocessor (), instance.getASTContext (), instance.getASTConsumer (), clang::TU_Complete);

clang::IdentifierTable & identifierTable = sema->getPreprocessor ().getIdentifierTable ();
clang::IdentifierInfo & identifier = identifierTable.get (“blubb”);

clang::TranslationUnitDecl* tu = sema->getASTContext().getTranslationUnitDecl();
clang::DeclContext* declContext = tu->getPrimaryContext();

clang::SourceLocation declSourceLocation;
clang::NamespaceDecl::Create (sema->getASTContext (), declContext, false, declSourceLocation, declSourceLocation, & identifier, nullptr);

instance.setSema (sema);
clang::ASTDumpAction action;
instance.ExecuteAction (action);

std::cout << “\nEnd CLang Sandbox!\n”;
}

Greetings,
Daniel Albuschat

P.S.: Yes, I have been recommended to create C++ code instead of trying to build an AST. But I’d still like to try the AST approach, since I’d like to skip the (time consuming) parsing of the C++ code.

Clang's AST is really complicated and there are a number of undocumented
invariants, so trying to build the AST "raw" is really difficult (I've
never heard of anybody doing it successfully). If you really want to go
this route, looking at lib/Sema/TreeTransform.h is probably your best guide.

-- Sean Silva

Try using llvm::sys::getDefaultTargetTriple().

Also you could try to look into this code to see how I initialize Clang manually (I don’t know if it’s the “correct” way to do it, but it’s been working fine): https://github.com/mono/CppSharp/blob/master/src/Parser/Parser.cpp

2013/7/13 Daniel Albuschat <d.albuschat@gmail.com>