|  | # 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](http://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. |