==========================================================
How to write RecursiveASTVisitor based ASTFrontendActions.
==========================================================

Introduction
============

In this tutorial you will learn how to create a FrontendAction that uses
a RecursiveASTVisitor to find CXXRecordDecl AST nodes with a specified
name.

Creating a FrontendAction
=========================

When writing a clang based tool like a Clang Plugin or a standalone tool
based on LibTooling, the common entry point is the FrontendAction.
FrontendAction is an interface that allows execution of user specific
actions as part of the compilation. To run tools over the AST clang
provides the convenience interface ASTFrontendAction, which takes care
of executing the action. The only part left is to implement the
CreateASTConsumer method that returns an ASTConsumer per translation
unit.

::

      class FindNamedClassAction : public clang::ASTFrontendAction {
      public:
        virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(
          clang::CompilerInstance &Compiler, llvm::StringRef InFile) {
          return std::unique_ptr<clang::ASTConsumer>(
              new FindNamedClassConsumer);
        }
      };

Creating an ASTConsumer
=======================

ASTConsumer is an interface used to write generic actions on an AST,
regardless of how the AST was produced. ASTConsumer provides many
different entry points, but for our use case the only one needed is
HandleTranslationUnit, which is called with the ASTContext for the
translation unit.

::

      class FindNamedClassConsumer : public clang::ASTConsumer {
      public:
        virtual void HandleTranslationUnit(clang::ASTContext &Context) {
          // Traversing the translation unit decl via a RecursiveASTVisitor
          // will visit all nodes in the AST.
          Visitor.TraverseDecl(Context.getTranslationUnitDecl());
        }
      private:
        // A RecursiveASTVisitor implementation.
        FindNamedClassVisitor Visitor;
      };

Using the RecursiveASTVisitor
=============================

Now that everything is hooked up, the next step is to implement a
RecursiveASTVisitor to extract the relevant information from the AST.

The RecursiveASTVisitor provides hooks of the form bool
VisitNodeType(NodeType \*) for most AST nodes; the exception are TypeLoc
nodes, which are passed by-value. We only need to implement the methods
for the relevant node types.

Let's start by writing a RecursiveASTVisitor that visits all
CXXRecordDecl's.

::

      class FindNamedClassVisitor
        : public RecursiveASTVisitor<FindNamedClassVisitor> {
      public:
        bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {
          // For debugging, dumping the AST nodes will show which nodes are already
          // being visited.
          Declaration->dump();

          // The return value indicates whether we want the visitation to proceed.
          // Return false to stop the traversal of the AST.
          return true;
        }
      };

In the methods of our RecursiveASTVisitor we can now use the full power
of the Clang AST to drill through to the parts that are interesting for
us. For example, to find all class declaration with a certain name, we
can check for a specific qualified name:

::

      bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {
        if (Declaration->getQualifiedNameAsString() == "n::m::C")
          Declaration->dump();
        return true;
      }

Accessing the SourceManager and ASTContext
==========================================

Some of the information about the AST, like source locations and global
identifier information, are not stored in the AST nodes themselves, but
in the ASTContext and its associated source manager. To retrieve them we
need to hand the ASTContext into our RecursiveASTVisitor implementation.

The ASTContext is available from the CompilerInstance during the call to
CreateASTConsumer. We can thus extract it there and hand it into our
freshly created FindNamedClassConsumer:

::

      virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(
        clang::CompilerInstance &Compiler, llvm::StringRef InFile) {
        return std::unique_ptr<clang::ASTConsumer>(
            new FindNamedClassConsumer(&Compiler.getASTContext()));
      }

Now that the ASTContext is available in the RecursiveASTVisitor, we can
do more interesting things with AST nodes, like looking up their source
locations:

::

      bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {
        if (Declaration->getQualifiedNameAsString() == "n::m::C") {
          // getFullLoc uses the ASTContext's SourceManager to resolve the source
          // location and break it up into its line and column parts.
          FullSourceLoc FullLocation = Context->getFullLoc(Declaration->getBeginLoc());
          if (FullLocation.isValid())
            llvm::outs() << "Found declaration at "
                         << FullLocation.getSpellingLineNumber() << ":"
                         << FullLocation.getSpellingColumnNumber() << "\n";
        }
        return true;
      }

Putting it all together
=======================

Now we can combine all of the above into a small example program:

::

      #include "clang/AST/ASTConsumer.h"
      #include "clang/AST/RecursiveASTVisitor.h"
      #include "clang/Frontend/CompilerInstance.h"
      #include "clang/Frontend/FrontendAction.h"
      #include "clang/Tooling/Tooling.h"

      using namespace clang;

      class FindNamedClassVisitor
        : public RecursiveASTVisitor<FindNamedClassVisitor> {
      public:
        explicit FindNamedClassVisitor(ASTContext *Context)
          : Context(Context) {}

        bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {
          if (Declaration->getQualifiedNameAsString() == "n::m::C") {
            FullSourceLoc FullLocation = Context->getFullLoc(Declaration->getBeginLoc());
            if (FullLocation.isValid())
              llvm::outs() << "Found declaration at "
                           << FullLocation.getSpellingLineNumber() << ":"
                           << FullLocation.getSpellingColumnNumber() << "\n";
          }
          return true;
        }

      private:
        ASTContext *Context;
      };

      class FindNamedClassConsumer : public clang::ASTConsumer {
      public:
        explicit FindNamedClassConsumer(ASTContext *Context)
          : Visitor(Context) {}

        virtual void HandleTranslationUnit(clang::ASTContext &Context) {
          Visitor.TraverseDecl(Context.getTranslationUnitDecl());
        }
      private:
        FindNamedClassVisitor Visitor;
      };

      class FindNamedClassAction : public clang::ASTFrontendAction {
      public:
        virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(
          clang::CompilerInstance &Compiler, llvm::StringRef InFile) {
          return std::unique_ptr<clang::ASTConsumer>(
              new FindNamedClassConsumer(&Compiler.getASTContext()));
        }
      };

      int main(int argc, char **argv) {
        if (argc > 1) {
          clang::tooling::runToolOnCode(std::make_unique<FindNamedClassAction>(), argv[1]);
        }
      }

We store this into a file called FindClassDecls.cpp and create the
following CMakeLists.txt to link it:

::

    add_clang_executable(find-class-decls FindClassDecls.cpp)

    target_link_libraries(find-class-decls clangTooling)

When running this tool over a small code snippet it will output all
declarations of a class n::m::C it found:

::

      $ ./bin/find-class-decls "namespace n { namespace m { class C {}; } }"
      Found declaration at 1:29

