| # Don't write a clang plugin | 
 |  | 
 | [TOC] | 
 |  | 
 | Make sure you really want to write a clang plugin. | 
 |  | 
 | *   The clang plugin api is not stable. If you write a plugin, _you_ are | 
 |     responsible for making sure it's updated when we update clang. | 
 | *   If you're adding a generally useful warning, it should be added to upstream | 
 |     clang, not to a plugin. | 
 | *   You should not use a clang plugin to do things that can be done in a | 
 |     PRESUBMIT check (e.g. checking that the headers in a file are sorted). | 
 |  | 
 | Valid reasons for writing a plugin are for example: | 
 |  | 
 | *   You want to add a chromium-specific error message. | 
 | *   You want to write an automatic code rewriter. | 
 |  | 
 | In both cases, please inform | 
 | [clang@chromium.org](https://groups.google.com/a/chromium.org/group/clang/topics) | 
 | of your plans before you pursue them. | 
 |  | 
 | # Having said that | 
 |  | 
 | clang currently has minimal documentation on its plugin interface; it's mostly | 
 | doxygen annotations in the source. This is an attempt to be half map to the | 
 | header files/half tutorial. | 
 |  | 
 | # Building your plugin | 
 |  | 
 | ## Just copy the clang build system | 
 |  | 
 | I suggest you make a new dir in `llvm/tools/clang/examples/` and copy the | 
 | Makefile from `PrintFunctionNames` there. This way, you'll just leverage the | 
 | existing clang build system. You can then build your plugin with | 
 |  | 
 |     make -C llvm/tools/clang/examples/myplugin | 
 |  | 
 | See [Using plugins](clang.md) on how to use your plugin while building chromium | 
 | with clang. | 
 |  | 
 | ## Use the interface in tools/clang/plugins/ChromeClassTester.h | 
 |  | 
 | Here's a canned interface that filters code, only passing class definitions in | 
 | non-blacklisted headers. The users of `ChromeClassTester` are good code to study | 
 | to see what you can do. | 
 |  | 
 | ## Or if you're doing something really different, copy PrintFunctionNames.cpp | 
 |  | 
 | `PrintFunctionNames.cpp` is a plugin in the clang distribution. It is the Hello | 
 | World of plugins. As a most basic skeleton, it's a good starting point. Change | 
 | all the identifiers that start with `PrintFunction` to your desired name. Take | 
 | note of the final line: | 
 |  | 
 | ```cpp | 
 | static FrontendPluginRegistry::Add<PrintFunctionNamesAction> | 
 | X("print-fns", "print function names"); | 
 | ``` | 
 |  | 
 | This registers your `PluginASTAction` with a string plugin name that can be | 
 | invoked on the command line. Note that everything else is in an anonymous | 
 | namespace; all other symbols aren't exported. | 
 |  | 
 | Your `PluginASTAction` subclass exists just to build your `ASTConsumer`, which | 
 | receives declarations, sort of like a SAX parser. | 
 |  | 
 | ## Your ASTConsumer | 
 |  | 
 | There is doxygen documentation on when each `ASTConsumer::Handle` method is | 
 | called in `llvm/tools/clang/include/clang/AST/ASTConsumer.h`. For this | 
 | tutorial, I'll assume you only want to look at type definitions (struct, class, | 
 | enum definitions), so we'll start with: | 
 |  | 
 | ```cpp | 
 | class TagConsumer : public ASTConsumer { | 
 |   public: | 
 |     virtual void HandleTagDeclDefinition(TagDecl *D) { | 
 |     } | 
 | }; | 
 | ``` | 
 |  | 
 | The data type passed in is the `Decl`, which is a giant class hierarchy spanning | 
 | the following files: | 
 |  | 
 | *   `llvm/tools/clang/include/clang/AST/DeclBase.h`: declares the `Decl` class, | 
 |     along with some utility classes you won't use. | 
 | *   `llvm/tools/clang/include/clang/AST/Decl.h`: declares subclasses of `Decl`, | 
 |     for example, `FunctionDecl` (a function declaration), `TagDecl` (the base class for struct/class/enum/etc), `TypedefDecl`, etc. | 
 | *   `llvm/tools/clang/include/clang/AST/DeclCXX.h`: C++ specific types. | 
 |     You'll find most Decl subclasses dealing with templates here, | 
 |     along with things like `UsingDirectiveDecl`, `CXXConstructorDecl`, etc. | 
 |  | 
 | The interface on these classes is massive; We'll only cover some of the basics, | 
 | but some basics about source location and errors. | 
 |  | 
 | ## Emitting Errors | 
 |  | 
 | Lots of location information is stored in the `Decl` tree. Most `Decl` | 
 | subclasses have multiple methods that return a `SourceLocation`, but lets use | 
 | `TagDecl::getInnerLocStart()` as an example. (`SourceLocation` is defined in | 
 | `llvm/tools/clang/include/clang/Basic/SourceLocation.h`, for reference.) | 
 |  | 
 | Errors are emitted to the user through the `CompilerInstance`. You will probably want to pass the `CompilerInstance` object passed to `ASTAction::CreateASTConsumer` to your ASTConsumer subclass for reporting. You interact with the user through the `Diagnostic` object. You could report errors to the user like this: | 
 |  | 
 | ```cpp | 
 | void emitWarning(CompilerInstance& instance, SourceLocation loc, const char* error) { | 
 |     FullSourceLoc full(loc, instance.getSourceManager()); | 
 |     unsigned id = instance.getCustomDiagID(Diagnostic::Warning, error); | 
 |     DiagnosticBuilder B = instance.getDiagnostics().Report(full, id); | 
 | } | 
 | ``` | 
 |  | 
 | (The above is the simplest error reporting. See | 
 | `llvm/tools/clang/include/clang/Basic/Diagnostic.h` for all the things you can | 
 | do, like `FixItHint`s if you want to get fancy!) | 
 |  | 
 | ## Downcast early, Downcast often | 
 |  | 
 | The clang library will give you the most general types possible. For example | 
 | `TagDecl` has comparably minimal interface. The library is designed so you will | 
 | be downcasting all the time, and you won't use the standard `dynamic_cast<>()` | 
 | builtin to do it. Instead, you'll use llvm/clang's home built RTTI system: | 
 |  | 
 | ```cpp | 
 |   virtual void HandleTagDeclDefinition(TagDecl* tag) { | 
 |     if (CXXRecordDecl* record = dyn_cast<CXXRecordDecl>(tag)) { | 
 |       // Do stuff with |record|. | 
 |     } | 
 |   } | 
 | ``` | 
 |  | 
 | ## A (not at all exhaustive) list of things you can do with (CXX)RecordDecl | 
 |  | 
 | *   Iterate across all constructors (`CXXRecordDecl::ctor_begin()`, | 
 |     `CXXReocrdDecl::ctor_end()`) | 
 | *   `CXXRecordDecl::isPOD()`: is this a Plain Old Datatype (a type that has no | 
 |     construction or destruction semantics)? | 
 | *   Check if certain properties of the class: `CXXRecordDecl::isAbstract()`, | 
 |     `CXXRecordDecl::hasTrivialConstructor()`, | 
 |     `CXXRecordDecl::hasTrivialDestructor()`, etc. | 
 | *   Iterate across all fields/member variables (`RecordDecl::field_begin()`, | 
 |     `RecordDecl::field_end()`) | 
 | *   Iterate across all of the base classes of a record type | 
 |     (`CXXRecordDecl::bases_begin()`, `CXXRecordDecl::bases_end()`) | 
 | *   Get the simple string name `NamedDecl::getNameAsString()`. (This method is | 
 |     deprecated, but the replacement assert()s on error conditions). (If you had | 
 |     `struct One {}`, this method would return "One".) | 
 |  | 
 | ## Modifying existing plugins | 
 |  | 
 | If you want to add additional checks to the existing plugins, be sure to add the | 
 | new diagnostic behind a flag (there are several examples of this in the plugins | 
 | already). The reason for this is that the plugin is bundled with clang, and the | 
 | new check will get deployed with the next clang roll. If your check fires, then | 
 | the next clang roll would now be blocked on cleaning up the whole codebase for | 
 | your check – and even if the check doesn't fire at the moment, maybe that | 
 | regresses until the next clang roll happens. If your new check is behind a flag, | 
 | then the clang roll can happen first, and you can add the flag to enable your | 
 | check after that, and then turn on the check everywhere once you know that the | 
 | codebase is clean. |