summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/docs
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/docs')
-rw-r--r--clang-tools-extra/docs/clang-tidy.rst298
-rw-r--r--clang-tools-extra/docs/index.rst1
2 files changed, 299 insertions, 0 deletions
diff --git a/clang-tools-extra/docs/clang-tidy.rst b/clang-tools-extra/docs/clang-tidy.rst
new file mode 100644
index 00000000000..1ed9b7904cf
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy.rst
@@ -0,0 +1,298 @@
+==========
+Clang-Tidy
+==========
+
+:program:`clang-tidy` is a clang-based C++ linter tool. Its purpose is to
+provide an extensible framework for diagnosing and fixing typical programming
+errors, like style violations, interface misuse, or bugs that can be deduced via
+static analysis. :program:`clang-tidy` is modular and provides a convenient
+interface for writing new checks.
+
+
+Using clang-tidy
+================
+
+:program:`clang-tidy` is a `LibTooling`_-based tool, and it's easier to work
+with if you set up a compile command database for your project (for an example
+of how to do this see `How To Setup Tooling For LLVM`_ ). You can also specify
+compilation options on the command line after ``--``:
+
+.. code-block:: bash
+
+ $ clang-tidy test.cpp -- -Imy_project/include -DMY_DEFINES ...
+
+:program:`clang-tidy` has its own checks and can also run Clang static analyzer
+checks. Each check has a name and the checks to run can be chosen using the
+``-checks=`` and ``-disable-checks=`` options. :program:`clang-tidy` selects the
+checks with names matching the regular expression specified by the ``-checks=``
+option and not matching the one specified by the ``-disable-checks=`` option.
+
+The ``-list-checks`` option lists all the enabled checks. It can be used with or
+without ``-checks=`` and/or ``-disable-checks=``.
+
+There are currently three groups of checks:
+
+* Checks related to the LLVM coding conventions have names starting with
+ ``llvm-``.
+
+* Checks related to the Google coding conventions have names starting with
+ ``google-``.
+
+* Clang static analyzer checks are named starting with ``clang-analyzer-``.
+
+
+The ``-fix`` flag instructs :program:`clang-format` to fix found errors if
+supported by corresponding checks.
+
+An overview of all the command-line options:
+
+.. code-block:: bash
+
+ $ clang-tidy -help
+ USAGE: clang-tidy [options] <source0> [... <sourceN>]
+
+ OPTIONS:
+
+ General options:
+
+ -help - Display available options (-help-hidden
+ for more)
+ -help-list - Display list of available options
+ (-help-list-hidden for more)
+ -version - Display the version of this program
+
+ clang-tidy options:
+
+ -checks=<string> - Regular expression matching the names of
+ the checks to be run.
+ -disable-checks=<string> - Regular expression matching the names of
+ the checks to disable.
+ -fix - Fix detected errors if possible.
+ -list-checks - List all enabled checks and exit.
+ -p=<string> - Build path
+
+ -p <build-path> is used to read a compile command database.
+
+ For example, it can be a CMake build directory in which a file named
+ compile_commands.json exists (use -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
+ CMake option to get this output). When no build path is specified,
+ a search for compile_commands.json will be attempted through all
+ parent paths of the first input file . See:
+ http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html for an
+ example of setting up Clang Tooling on a source tree.
+
+ <source0> ... specify the paths of source files. These paths are
+ looked up in the compile command database. If the path of a file is
+ absolute, it needs to point into CMake's source tree. If the path is
+ relative, the current working directory needs to be in the CMake
+ source tree and the file must be in a subdirectory of the current
+ working directory. "./" prefixes in the relative files will be
+ automatically removed, but the rest of a relative path must be a
+ suffix of a path in the compile command database.
+
+
+.. _LibTooling: http://clang.llvm.org/docs/LibTooling.html
+.. _How To Setup Tooling For LLVM: http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
+
+
+Getting Involved
+================
+
+:program:`clang-tidy` has several own checks and can run Clang static analyzer
+checks, but its power is in the ability to easily write custom checks.
+
+Checks are organized in modules, which can be linked into :program:`clang-tidy`
+with minimal or no code changes in clang-tidy.
+
+Checks can plug the analysis on the preprocessor level using `PPCallbacks`_ or
+on the AST level using `AST Matchers`_. When an error is found, checks can
+report them in a way similar to how Clang diagnostics work. A fix-it hint can be
+attached to a diagnostic message.
+
+The interface provided by clang-tidy makes it easy to write useful and precise
+checks in just a few lines of code. If you have an idea for a good check, the
+rest of this document explains how to do this.
+
+.. _AST Matchers: http://clang.llvm.org/docs/LibASTMatchers.html
+.. _PPCallbacks: http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html
+
+
+Choosing the Right Place for your Check
+---------------------------------------
+
+If you have an idea of a check, you should decide whether it should be
+implemented as a:
+
++ *Clang diagnostic*: if the check is generic enough, targets code patterns that
+ most probably are bugs (rather than style or readability issues), can be
+ implemented effectively and with extremely low false positive rate, it may
+ make a good Clang diagnostic.
+
++ *Clang static analyzer check*: if the check requires some sort of control flow
+ analysis, it should probably be implemented as a static analyzer check.
+
++ *clang-tidy check* is a good choice for linter-style checks, checks that are
+ related to a certain coding style, checks that address code readability, etc.
+
+
+Preparing your Workspace
+------------------------
+
+If you are new to LLVM development, you should read the `Getting Started with
+the LLVM System`_, `Using Clang Tools`_ and `How To Setup Tooling For LLVM`_
+documents to check out and build LLVM, Clang and Clang Extra Tools with CMake.
+
+Once you are done, change to the ``llvm/tools/clang/tools/extra`` directory, and
+let's start!
+
+.. _Getting Started with the LLVM System: http://llvm.org/docs/GettingStarted.html
+.. _Using Clang Tools: http://clang.llvm.org/docs/ClangTools.html
+
+
+The Directory Structure
+-----------------------
+
+:program:`clang-tidy` source code resides in the
+``llvm/tools/clang/tools/extra`` directory and is structured as follows:
+
+::
+
+ clang-tidy/ # Clang-tidy core.
+ ├── ClangTidy.h # Interfaces for users and checks.
+ ├── ClangTidyModule.h # Interface for clang-tidy modules.
+ ├── ClangTidyModuleRegistry.h # Interface for registering of modules.
+ ...
+ ├── google/ # Google clang-tidy module.
+ │   ├── GoogleTidyModule.cpp
+ │   ├── GoogleTidyModule.h
+ ...
+ ├── llvm/ # LLVM clang-tidy module.
+ │   ├── LLVMTidyModule.cpp
+ │   ├── LLVMTidyModule.h
+ ...
+ └── tool/ # Sources of the clang-tidy binary.
+ ...
+ test/clang-tidy/ # Integration tests.
+ ...
+ unittests/clang-tidy/
+ ├── ClangTidyTest.h
+ ├── GoogleModuleTest.cpp
+ ├── LLVMModuleTest.cpp
+ ...
+
+
+Writing a clang-tidy Check
+--------------------------
+
+So you have an idea of a useful check for :program:`clang-tidy`.
+
+You need to decide which module the check belongs to. If the check verifies
+conformance of the code to a certain coding style, it probably deserves a
+separate module and a directory in ``clang-tidy/`` (there are LLVM and Google
+modules already).
+
+After choosing the module, you need to create a class for your check:
+
+.. code-block:: c++
+
+ #include "../ClangTidy.h"
+
+ namespace clang {
+ namespace tidy {
+
+ class MyCheck : public ClangTidyCheck {
+ };
+
+ } // namespace tidy
+ } // namespace clang
+
+Next, you need to decide whether it should operate on the preprocessor level or
+on the AST level. Let's imagine that we need to work with the AST in our check.
+In this case we need to override two methods:
+
+.. code-block:: c++
+
+ ...
+ class ExplicitConstructorCheck : public ClangTidyCheck {
+ public:
+ void registerMatchers(ast_matchers::MatchFinder *Finder);
+ void check(ast_matchers::MatchFinder::MatchResult &Result);
+ };
+
+In the ``registerMatchers`` method we create an AST Matcher (see `AST Matchers`_
+for more information) that will find the pattern in the AST that we want to
+inspect. The results of the matching are passed to the ``check`` method, which
+can further inspect them and report diagnostics.
+
+.. code-block:: c++
+
+ using namespace ast_matchers;
+
+ void ExplicitConstructorCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(constructorDecl().bind("ctor"), this);
+ }
+
+ void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) {
+ const CXXConstructorDecl *Ctor =
+ Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
+ // Do not be confused: isExplicit means 'explicit' keyword is present,
+ // isImplicit means that it's a compiler-generated constructor.
+ if (Ctor->isOutOfLine() || Ctor->isExplicit() || Ctor->isImplicit())
+ return;
+ if (Ctor->getNumParams() == 0 || Ctor->getMinRequiredArguments() > 1)
+ return;
+ SourceLocation Loc = Ctor->getLocation();
+ diag(Loc, "Single-argument constructors must be explicit")
+ << FixItHint::CreateInsertion(Loc, "explicit ");
+ }
+
+(The full code for this check resides in
+``clang-tidy/google/GoogleTidyModule.cpp``).
+
+
+Registering your Check
+----------------------
+
+The check should be registered in the corresponding module with a distinct name:
+
+.. code-block:: c++
+
+ class MyModule : public ClangTidyModule {
+ public:
+ virtual void
+ addCheckFactories(ClangTidyCheckFactories &CheckFactories) LLVM_OVERRIDE {
+ CheckFactories.addCheckFactory(
+ "my-explicit-constructor",
+ new ClangTidyCheckFactory<ExplicitConstructorCheck>());
+ }
+ };
+
+Now we need to register the module in the ``ClangTidyModuleRegistry`` using a
+statically initialized variable:
+
+.. code-block:: c++
+
+ static ClangTidyModuleRegistry::Add<MyModule> X("my-module",
+ "Adds my lint checks.");
+
+
+When using LLVM build system, we need to use the following hack to ensure the
+module is linked into the clang-tidy binary:
+
+Add this near the ``ClangTidyModuleRegistry::Add<MyModule>`` variable:
+
+.. code-block:: c++
+
+ // This anchor is used to force the linker to link in the generated object file
+ // and thus register the MyModule.
+ volatile int MyModuleAnchorSource = 0;
+
+And this to the main translation unit of the clang-tidy binary (or the binary
+you link the ``clang-tidy`` library in) ``clang-tidy/tool/ClangTidyMain.cpp``:
+
+.. code-block:: c++
+
+ // This anchor is used to force the linker to link the MyModule.
+ extern volatile int MyModuleAnchorSource;
+ static int MyModuleAnchorDestination = MyModuleAnchorSource;
+
diff --git a/clang-tools-extra/docs/index.rst b/clang-tools-extra/docs/index.rst
index 13cc10aa421..3a0b172207e 100644
--- a/clang-tools-extra/docs/index.rst
+++ b/clang-tools-extra/docs/index.rst
@@ -16,6 +16,7 @@ Contents
:maxdepth: 1
clang-modernize
+ clang-tidy
modularize
module-map-checker
pp-trace
OpenPOWER on IntegriCloud