==========================================================
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 clang::ASTConsumer *CreateASTConsumer(
          clang::CompilerInstance &Compiler, llvm::StringRef InFile) {
          return 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 clang::ASTConsumer *CreateASTConsumer(
        clang::CompilerInstance &Compiler, llvm::StringRef InFile) {
        return 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->getLocStart());
          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->getLocStart());
            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 clang::ASTConsumer *CreateASTConsumer(
          clang::CompilerInstance &Compiler, llvm::StringRef InFile) {
          return new FindNamedClassConsumer(&Compiler.getASTContext());
        }
      };

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

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

::

    set(LLVM_USED_LIBS clangTooling)

    add_clang_executable(find-class-decls FindClassDecls.cpp)

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

