Clang LibTooling

There are several different ways to make use of Clang’s functionality. We are going to use LibTooling.

In particular, we’ll be using the ClangTool class (defined in the clang/Tooling/Tooling.h header), which relieves us from dealing with low-level details like reading the input source files or creating all the necessary infrastructure for processing them. We use ClangTool for simplicity - for more serious projects, it is likely a better choice to use a RefactoringTool, which creates a database of refactorings that can be serialized and then applied with a separate tool called clang-apply-replacements. This is particularly important if your tool needs to process header files, as they may be included from more than one source file.

ClangTools

In order to create a ClangTool object, we will need a CompilationDatabase (clang/Tooling/CompilationDatabase.h) and an array containing the paths to the source files that should be processed:

ClangTool(const CompilationDatabase &Compilations, ArrayRef<std::string> SourcePaths);

The purpose of the CompilationDatabase is to store all the build commands, so that it may instantiate the Clang infrastructure with the correct parameters for each file that is processed. We will obtain a CompilationDatabase from the command line arguments, by using a CommonOptionsParser object. In the simplest scenario, the CommonOptionsParser will look for an argument consisting of a double dash (–). Arguments following the double dash are compilation arguments (“-I”, “-D” etc) and will be passed on to the Clang infrastructure, whereas the arguments that come before the double dash are tool-specific arguments (see LLVM's command line library). The input source files should come before the double dash.

ourCustomTool -our-custom-option=”some custom value” file1.c file2.c -- -I”some/header/search/path” ; -our-custom-option goes to the tool, -I goes to the CompilationDatabase

Once we have a valid CommonOptionsParser object, we can get the CompilationDatabase using the getCompilations method and the input source files with getSourcePathList:

clang::tooling::ClangTool Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList());

Frontend Actions

We will use the ClangTool in order to run a FrontendAction on each of the input source files. FrontendAction (clang/Frontend/FrontendAction.h) is an abstract class, with several pure virtual methods. For convenience, several subclasses are provided, which offer default implementations for a subset of these pure virtual methods - see, for example, the PreprocessorFrontendAction, for actions that only need to use the preprocessor, or ASTFrontendAction, for actions that use the AST (Abstract Syntax Tree). It is important to note that we can interact with the preprocessor even if we subclass ASTFrontendAction, because building the AST cannot be done without running the preprocessor - on the other hand, if we subclass from PreprocessorFrontendAction we cannot access the AST because it has not been built.

We will subclass ASTFrontendAction, which has only one pure virtual method:

virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, StringRef InFile) = 0;

This method allows us to infiltrate a custom ASTConsumer into the Clang compilation process. It is the ASTConsumer that gives us the possibility to access the AST. It does so by providing several virtual methods that are called at various points in the compilation process - for instance, HandleTranslationUnitDecl, which we’ll be using, is called whenever Clang finishes building the AST for an input source file.

sesiuni/llvm/libtooling.txt · Last modified: 2015/09/08 10:44 by freescale