Index: clang-tools-extra/docs/clang-tidy/Contributing.rst =================================================================== --- clang-tools-extra/docs/clang-tidy/Contributing.rst +++ clang-tools-extra/docs/clang-tidy/Contributing.rst @@ -22,6 +22,8 @@ check, it will create the check, update the CMake file and create a test; * ``rename_check.py`` does what the script name suggests, renames an existing check; + * :program:`pp-trace` logs method calls on `PPCallbacks` for a source file + and is invaluable in understanding the preprocessor mechanism; * :program:`clang-query` is invaluable for interactive prototyping of AST matchers and exploration of the Clang AST; * `clang-check`_ with the ``-ast-dump`` (and optionally ``-ast-dump-filter``) @@ -70,6 +72,13 @@ .. _Using Clang Tools: https://clang.llvm.org/docs/ClangTools.html .. _How To Setup Clang Tooling For LLVM: https://clang.llvm.org/docs/HowToSetupToolingForLLVM.html +When you `configure the CMake build `_, +make sure that you enable the ``clang-tools-extra`` project to build :program:`clang-tidy`. +Since your new check will have associated documentation, you will also want to install +`Sphinx `_ and enable it in the CMake configuration. +To save build time of the core clang libraries you may want to only enable the ``X86`` +target in the CMake configuration. + The Directory Structure ----------------------- @@ -215,11 +224,191 @@ and `clang-tidy/google/ExplicitConstructorCheck.cpp `_). +If you need to interact macros and preprocessor directives, you will want to +override the method ``registerPPCallbacks``. The ``add_new_check.py`` script +does not generate an override for this method in the starting point for your +new check. + + +Check development tips +---------------------- + +Writing your first check can be a daunting task, particularly if you are unfamiliar +with the LLVM and clang code bases. Here are some suggestions for orienting yourself +in the codebase and working on your check incrementally. + +Guide to useful documentation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Many of the support classes created for LLVM are used by clang, such as `StringRef +`_ +and `SmallVector `_. +These and other commonly used classes are described in the `Important and useful LLVM APIs +`_ and +`Picking the Right Data Structure for the Task +`_ +sections of the `LLVM Programmer's Manual +`_. You don't need to memorize all the +details of these classes; the generated `doxygen documentation `_ +has everything if you need it. In the header `LLVM/ADT/STLExtras.h +`_ you'll find useful versions of the STL +algorithms that operate on LLVM containers, such as `llvm::all_of +`_. + +Clang is implemented on top of LLVM and introduces its own set of classes that you +will interact with while writing your check. The most important of these are the +classes relating the source code locations, source files, ranges of source locations +and the `SourceManager +`_ class. These and +other topics are described in the `"Clang" CFE Internals Manual +`_. Whereas the doxygen generated +documentation serves as a reference to the internals of clang, this document serves +as a guide to other developers. Topics in that manual of interest to a check developer +are: + +- `The Clang "Basic" Library + `_ for + information about diagnostics, fix-it hints and source locations. +- `The Lexer and Preprocessor Library + `_ + for information about tokens, lexing (transforming characters into tokens) and the + preprocessor. +- `The AST Library + `_ + for information about how C++ source statements are represented as an abstract syntax + tree (AST). + +Most checks will interact with C++ source code via the AST. Some checks will interact +with the preprocessor. The input source file is lexed and preprocessed and then parsed +into the AST. Once the AST is fully constructed, the check is run by applying the check's +registered AST matchers against the AST and invoking the check with the set of matched +nodes from the AST. Monitoring the actions of the preprocessor is detached from the +AST construction, but a check can collect information during preprocessing for later +use by the check when nodes are matched by the AST. + +Every syntactic (and sometimes semantic) element of the C++ source code is represented by +different classes in the AST. You select the portions of the AST you're interested in +by composing AST matcher functions. You will want to study carefully the `AST Matcher +Reference `_ to understand +the relationship between the different matcher funtions. + +Using the Transformer library +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The Transformer library allows you to write a check that transforms source code by +expressing the transformation as a ``RewriteRule``. The Transformer library provides +functions for composing edits to source code to create rewrite rules. Unless you need +to perform low-level source location manipulation, you may want to consider writing your +check with the Transformer library. The `Clang Transformer Tutorial +`_ describes the Transformer +library in detail. + +To use the Transformer library, make the following changes to the code generated by +the ``add_new_check.py`` script: + +- Include ``../utils/TransformerClangTidyCheck.h`` instead of ``../ClangTidyCheck.h`` +- Change the base class of your check from ``ClangTidyCheck`` to ``TransformerClangTidyCheck`` +- Delete the override of the ``registerMatchers`` and ``check`` methods in your check class. +- Write a function that creates the ``RewriteRule`` for your check. +- Call the function in your check's constructor to pass the rewrite rule to + ``TransformerClangTidyCheck``'s constructor. + +Developing your check incrementally +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The best way to develop your check is to start with the simple test cases and increase +complexity incrementally. The test file created by the ``add_new_check.py`` script is +a starting point for your test cases. A rough outline of the process looks like this: + +- Write a test case for your check. +- Prototype matchers on the test file using :program:`clang-query`. +- Capture the working matchers in the ``registerMatchers`` method. +- Issue the necessary diagnostics and fix-its in the ``check`` method. +- Add the necessary ``CHECK-MESSAGES`` and ``CHECK-FIXES`` annotations to your + test case to validate the diagnostics and fix-its. +- Build the target ``check-clang-tool`` to confirm the test passes. +- Repeat the process until all aspects of your check are covered by tests. + +The quickest way to prototype your matcher is to use :program:`clang-query` to +interactively build up your matcher. For complicated matchers, build up a matching +expression incrementally and use :program:`clang-query`'s ``let`` command to save named +matching expressions to simplify your matcher. Just like breaking up a huge function +into smaller chunks with an intention revealing name can help you understand a complex +algorithm, breaking up a matcher into smaller matchers with intention revealing names +can help you understand a complicated matcher. Once you have a working matcher, the +C++ api will be virtually identical to your interactively constructed matcher. You can +use local variables to preserve your intention revealing names that you applied to +nested matchers. + +Creating private matchers +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Sometimes you want to match a specific aspect of the AST that isn't provided by the +existing AST matchers. You can create your own private matcher using the same +infrastructure as the public matchers. A private matcher can simplify the processing +in your ``check`` method by eliminating complex hand-crafted AST traversal of the +matched nodes. Using the private matcher allows you to select the desired portions +of the AST directly in the matcher and refer to it by a bound name in the ``check`` +method. + +Unit testing helper code +^^^^^^^^^^^^^^^^^^^^^^^^ + +Private custom matchers are a good example of auxiliary support code for your check +that is best tested with a unit test. It will be easier to test your matchers or +other support classes by writing a unit test than by writing a ``FileCheck`` integration +test. The ``ASTMatchersTests`` target contains unit tests for the public AST matcher +classes and is a good source of testing idioms for matchers. + +Making your check robust +^^^^^^^^^^^^^^^^^^^^^^^^ + +Once you've covered your check with the basic "happy path" scenarios, you'll want to +torture your check with some crazy C++ in order to ensure your check is robust. Running +your check on a large code base, such as Clang/LLVM, is a good way to catch things you +forgot to account for in your matchers. However, the LLVM code base is "reasonable" and +doesn't contain weird template or macro oriented code. + +Some suggestions to ensure your check is robust: + +- Create header files that contain code matched by your check. +- Validate that fix-its are properly applied to test header files with :program:`clang-tidy`. + You will need to perform this test manually until automated support for checking + messages and fix-its is added to the ``check_clang_tidy.py`` script. +- Define macros that contain code matched by your check. +- Define template classes that contain code matched by your check. +- Define template specializations that contain code matched by your check. + +Documenting your check +^^^^^^^^^^^^^^^^^^^^^^ + +The ``add_new_check.py`` script creates entries in the release notes, the list of +checks and a new file for the check documentation itself. It is recommended that you +have a concise summation of what your check does in a single sentence that is repeated +in the release notes, as the first sentence in the doxygen comments in the header file +for your check class and as the first sentence of the check documentation. Avoid the +phrase "this check" in your check summation and check documentation. + +If your check relates to a published coding guideline (C++ Core Guidelines, MISRA, etc.) +or style guide, provide links to the relevant guideline or style guide sections in your +check documentation. + +Provide enough examples of the diagnostics and fix-its provided by the check so that a +user can easily understand what will happen to their code when the check is run. +If there are exceptions or limitations to your check, document them thoroughly. This +will help users understand the scope of the diagnostics and fix-its provided by the check. + +Building the target ``docs-clang-tools-html`` will run the Sphinx documentation generator +and create documentation HTML files in the tools/clang/tools/extra/docs/html directory in +your build tree. Make sure that your check is correctly shown in the release notes and the +list of checks. Make sure that the formatting and structure of your check's documentation +looks correct. + Registering your Check ---------------------- -(The ``add_new_check.py`` takes care of registering the check in an existing +(The ``add_new_check.py`` script takes care of registering the check in an existing module. If you want to create a new module or know the details, read on.) The check should be registered in the corresponding module with a distinct name: @@ -394,7 +583,6 @@ // CHECK-FIXES-USING-B-NOT: using a::B;$ // CHECK-FIXES-NOT: using a::C;$ - There are many dark corners in the C++ language, and it may be difficult to make your check work perfectly in all cases, especially if it issues fix-it hints. The most frequent pitfalls are macros and templates: @@ -411,6 +599,10 @@ macro expansions/template instantiations, but easily break some other expansions/instantiations. +If you need multiple files to exercise all the aspects of your check, it is +recommended you place them in a subdirectory named for the check under ``Inputs``. +This keeps the test directory from getting cluttered. + .. _lit: https://llvm.org/docs/CommandGuide/lit.html .. _FileCheck: https://llvm.org/docs/CommandGuide/FileCheck.html .. _test/clang-tidy/google-readability-casting.cpp: https://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/test/clang-tidy/google-readability-casting.cpp