2

I've been able to implement an ASTFrontendAction to create an ASTConsumer, which uses a RescursiveASTVisitor to traverse a translation unit decl, thereby visiting all the nodes of an AST for a given source file. I do this by implementing a ToolAction which is passed to ClangTool::run(ToolAction *action). This tool overrides the ToolAction::runInvocation member function to do some processing between each call to my ASTFrontendAction. So far so good, everything is working as expected, and my custom clang tool is helping me better explore a rather large, over 15 years old code base.

However, every time I want to run my tool, I need to do a full blown parse of the ASTs. As I mentioned, this is a rather large code base, so it takes a while to do a single run. I have gathered, by looking through the code, that it is possible to create and traverse an AST from a saved file, rather than perform the parse. Googling around confirmed that it's possible to save an AST, and by looking at the ClangTool and ASTUnit API, it seems it's pretty easy to do.

While it seems straightforward to save the AST, I have no idea how to make use of a saved AST when running my custom clang tool. Looking at the code path for running a tool, I see there is a point where the AST is created either by parsing a source file or by reading it from a file. What I would like to do is have all my ASTs available in a file(s), so that each run of my tool will create the ASTs from a file, and not need to perform a full parse (which, I assume would be much faster).

Could someone please help? Thanks in advance!

SU3
  • 5,064
  • 3
  • 35
  • 66
JMLoy
  • 121
  • 1
  • 1
  • 6
  • 1
    Did you see the [`ReadAST()`](https://clang.llvm.org/doxygen/classclang_1_1ASTReader.html#af2f0d7be2a912c0423fd541d6d746675) function? Might be of some help if you hadn't already seen it. –  Apr 02 '18 at 00:13
  • I had not seen that, thanks for pointing me to it. – JMLoy Apr 02 '18 at 13:55
  • Though, I'm still a little confused. To use this, I need an instance of `ASTReader`. It's not clear to me how to get one. Can I create my own? Can something provide one for me, if so, what is that thing? Once I have an instance of the `ASTReader`, I think I could use it how I envision. Just pick up all the saved ASTs, read them, and use my `ASTConsumer` to traverse the translation unit. But is this really the only way? I find it odd that there is no way to go through this same process using the normal tooling pipeline. – JMLoy Apr 02 '18 at 14:02
  • Did you find out how to use AST writer and reader? – Joe C Sep 29 '20 at 17:18
  • Roberts's answer worked for me. However, make sure that the versions of Clang that generate the AST and develop the ClangTool are consistent. Otherwise, you will get a PCH format error. – x7903 Jul 28 '21 at 08:50

1 Answers1

0

This worked for me:

clang::CompilerInstance CI;
CI.createDiagnostics();
std::shared_ptr<clang::TargetOptions> TO = std::make_shared<clang::TargetOptions>();
TO->Triple = "x86_64-pc-win32"; // see clang -v
CI.setTarget(clang::TargetInfo::CreateTargetInfo(CI.getDiagnostics(), TO));

std::unique_ptr<ASTUnit> ast = ASTUnit::LoadFromASTFile("TheAstFile.ast", 
    CI.getPCHContainerReader(), 
    ASTUnit::LoadEverything, 
    &CI.getDiagnostics(), 
    CI.getFileSystemOpts());

MyAstConsumer consumer(ast->getASTContext());
consumer.HandleTranslationUnit(ast->getASTContext());
Robzzz
  • 23
  • 5