blob: 604bb96a69712f0411357600d83d6cf645c0f1dd [file] [log] [blame] [view]
rdevlin.croninbe2898eb2016-07-13 01:20:361# Clang Tidy
2
3[TOC]
4
rdevlin.croninbe2898eb2016-07-13 01:20:365## Introduction
6
7[clang-tidy](http://clang.llvm.org/extra/clang-tidy/) is a clang-based C++
8“linter” tool. Its purpose is to provide an extensible framework for diagnosing
9and fixing typical programming errors, like style violations, interface misuse,
10or bugs that can be deduced via static analysis.
11
George Burgess IV288fcf52019-12-18 02:19:4612## Where is it?
rdevlin.croninbe2898eb2016-07-13 01:20:3613
George Burgess IV288fcf52019-12-18 02:19:4614clang-tidy is available in two places in Chromium:
Daniel McArdleb26068f2019-03-07 16:29:3215
George Burgess IV288fcf52019-12-18 02:19:4616- In Chromium checkouts
17- In code review on Gerrit
Daniel McArdleb26068f2019-03-07 16:29:3218
George Burgess IV288fcf52019-12-18 02:19:4619Clang-tidy automatically runs on any CL that Chromium committers upload to
20Gerrit, and will leave code review comments there. This is the recommended way
21of using clang-tidy.
Daniel McArdleb26068f2019-03-07 16:29:3222
George Burgess IV288fcf52019-12-18 02:19:4623## Enabled checks
rdevlin.croninbe2898eb2016-07-13 01:20:3624
George Burgess IV288fcf52019-12-18 02:19:4625Chromium globally enables a subset of all of clang-tidy's checks (see
26`${chromium}/src/.clang-tidy`). We want these checks to cover as much as we
27reasonably can, but we also strive to strike a reasonable balance between signal
28and noise on code reviews. Hence, a large number of clang-tidy checks are
29disabled.
30
31### Adding a new check
32
George Burgess IV80430342020-06-05 19:16:1733New checks require review from [email protected]. If you propose a check and it
34gets approved, you may turn it on, though please note that this is only
George Burgess IV288fcf52019-12-18 02:19:4635provisional approval: we get signal from users clicking "Not Useful" on
36comments. If feedback is overwhelmingly "users don't find this useful," the
37check may be removed.
38
George Burgess IV80430342020-06-05 19:16:1739Traditionally, petitions to add checks include [an
40evaluation](https://docs.google.com/document/d/1i1KmXtDD4j_qjhmAdGlJ6UkYXByVX1Kp952Zusdcl5k/edit?usp=sharing)
41of the check under review. Crucially, this includes two things:
42
43- a count of how many times this check fires across Chromium
44- a random sample (>30) of places where the check fires across Chromium
45
46It's expected that the person proposing the check has manually surveyed every
47clang-tidy diagnostic in the sample, noting any bugs, odd behaviors, or
48interesting patterns they've noticed. If clang-tidy emits FixIts, these are
49expected to be considered by the evaluation, too.
50
51An example of a previous proposal email thread is
52[here](https://groups.google.com/a/chromium.org/g/cxx/c/iZ6-Y9ZhC3Q/m/g-8HzqmbAAAJ).
53
54#### Evaluating: running clang-tidy across Chromium
55
56Running clang-tidy requires some setup. First, you'll need to sync clang-tidy,
57which requires adding `checkout_clang_tidy` to your `.gclient` file:
58
59```
60solutions = [
61 {
62 'custom_vars': {
63 'checkout_clang_tidy': True,
64 },
65 }
66]
67```
68
69Your next run of `gclient runhooks` should cause clang-tidy to be synced.
70
71To run clang-tidy across all of Chromium, you'll need a checkout of Chromium's
72[build/](https://chromium.googlesource.com/chromium/tools/build) repository.
73Once you have that and a Chromium `out/` dir with an `args.gn`, running
74clang-tidy across all of Chromium is a single command:
75
76```
77$ cd ${chromium}/src
Peter Kasting0dc33482020-10-19 01:48:2978$ ${chromium_build}/recipes/recipe_modules/tricium_clang_tidy/resources/tricium_clang_tidy.py \
George Burgess IV80430342020-06-05 19:16:1779 --base_path $PWD \
80 --out_dir out/Linux \
81 --findings_file all_findings.json \
82 --clang_tidy_binary $PWD/third_party/llvm-build/Release+Asserts/bin/clang-tidy \
83 --all
84```
85
86All clang-tidy checks are run on Linux builds of Chromium, so please set up your
87`args.gn` to build Linux.
88
89`all_findings.json` is where all of clang-tidy's findings will be dumped. The
90format of this file is detailed in `tricium_clang_tidy.py`.
91
92**Note** that the above command will use Chromium's top-level `.clang-tidy` file
93(or `.clang-tidy` files scattered throughout `third_party/`, depending on the
94files we lint. In order to test a *new* check, you'll have to add it to
95Chromium's top-level `.clang-tidy` file.
96
George Burgess IV898f7c82020-01-21 21:04:0697### Ignoring a check
98
99If a check is invalid on a particular piece of code, clang-tidy supports `//
100NOLINT` and `// NOLINTNEXTLINE` for ignoring all lint checks in the current and
101next lines, respectively. To suppress a specific lint, you can put it in
102parenthesis, e.g., `// NOLINTNEXTLINE(modernize-use-nullptr)`. For more, please
103see [the documentation](
104https://clang.llvm.org/extra/clang-tidy/#suppressing-undesired-diagnostics).
105
106**Please note** that adding comments that exist only to silence clang-tidy is
107actively discouraged. These comments clutter code, can easily get
108out-of-date, and don't provide much value to readers. Moreover, clang-tidy only
109complains on Gerrit when lines are touched, and making Chromium clang-tidy clean
110is an explicit non-goal; making code less readable in order to silence a
111rarely-surfaced complaint isn't a good trade-off.
112
113If clang-tidy emits a diagnostic that's incorrect due to a subtlety in the code,
114adding an explanantion of what the code is doing with a trailing `NOLINT` may be
115fine. Put differently, the comment should be able to stand on its own even if we
116removed the `NOLINT`. The fact that the comment also silences clang-tidy is a
117convenient side-effect.
118
119For example:
120
121Not OK; comment exists just to silence clang-tidy:
122
123```
124// NOLINTNEXTLINE
125for (int i = 0; i < arr.size(); i++) {
126 // ...
127}
128```
129
130Not OK; comment exists just to verbosely silence clang-tidy:
131
132```
133// Clang-tidy doesn't get that we can't range-for-ize this loop. NOLINTNEXTLINE
134for (int i = 0; i < arr.size(); i++) {
135 // ...
136}
137```
138
139Not OK; it's obvious that this loop modifies `arr`, so the comment doesn't
140actually clarify anything:
141
142```
143// It'd be invalid to make this into a range-for loop, since the body might add
144// elements to `arr`. NOLINTNEXTLINE
145for (int i = 0; i < arr.size(); i++) {
146 if (i % 4) {
147 arr.push_back(4);
148 arr.push_back(2);
149 }
150}
151```
152
153OK; comment calls out a non-obvious property of this loop's body. As an
154afterthought, it silences clang-tidy:
155
156```
157// It'd be invalid to make this into a range-for loop, since the call to `foo`
158// here might add elements to `arr`. NOLINTNEXTLINE
159for (int i = 0; i < arr.size(); i++) {
160 foo();
161 bar();
162}
163```
164
165In the end, as always, what is and isn't obvious at some point is highly
166context-dependent. Please use your best judgement.
167
George Burgess IV288fcf52019-12-18 02:19:46168## But I want to run it locally
169
170If you want to sync the officially-supported `clang-tidy` to your workstation,
171add the following to your .gclient file:
172
rdevlin.croninbe2898eb2016-07-13 01:20:36173```
George Burgess IV288fcf52019-12-18 02:19:46174solutions = [
175 {
176 'custom_vars': {
177 'checkout_clang_tidy': True,
178 },
179 },
180]
rdevlin.croninbe2898eb2016-07-13 01:20:36181```
182
George Burgess IV288fcf52019-12-18 02:19:46183If you already have `solutions` and `custom_vars`, just add
184`checkout_clang_tidy` to the existing `custom_vars` map.
rdevlin.croninbe2898eb2016-07-13 01:20:36185
George Burgess IV288fcf52019-12-18 02:19:46186Once the above update has been made, run `gclient runhooks`, and clang-tidy
187should appear at `src/third_party/llvm-build/Release+Asserts/bin/clang-tidy` if
188your Chromium tree is sufficiently up-to-date.
rdevlin.croninbe2898eb2016-07-13 01:20:36189
George Burgess IV288fcf52019-12-18 02:19:46190### Running clang-tidy locally
rdevlin.croninbe2898eb2016-07-13 01:20:36191
George Burgess IV288fcf52019-12-18 02:19:46192**Note** that the local flows with clang-tidy are experimental, and require an
193LLVM checkout. Tricium is happy to run on WIP CLs, and we strongly encourage its
194use.
195
196That said, assuming you have the LLVM sources available, you'll need to bring
197your own `clang-apply-replacements` binary if you want to use the `-fix` option
198noted below.
rdevlin.croninbe2898eb2016-07-13 01:20:36199
Jan Wilken Dörriec0a93c172021-04-12 17:12:05200**Note:** If you're on a system that offers a clang tools through its package
201manager (e.g., on Debian/Ubuntu, `sudo apt-get install clang-tidy clang-tools`),
202you might not need an LLVM checkout to make the required binaries and scripts
203(`clang-tidy`, `run-clang-tidy` and `clang-apply-replacements`) available in
204your `$PATH`. However, the system packaged binaries might be several versions
205behind Chromium's toolchain, so not all flags are guaranteed to work. If this is
206a problem, consider building clang-tidy from the same revision the current
207toolchain is using, rather than filing a bug against the toolchain component.
208
rdevlin.croninbe2898eb2016-07-13 01:20:36209Running clang-tidy is (hopefully) simple.
Dirk Pranke6e1ce9f2019-10-29 22:53:532101. Build chrome normally.
rdevlin.croninbe2898eb2016-07-13 01:20:36211```
212ninja -C out/Release chrome
213```
George Burgess IV288fcf52019-12-18 02:19:462142. Enter the build directory
rdevlin.croninbe2898eb2016-07-13 01:20:36215```
216cd out/Release
217```
George Burgess IV288fcf52019-12-18 02:19:462183. Export Chrome's compile command database
219```
220gn gen . --export-compile-commands
221```
rdevlin.croninbe2898eb2016-07-13 01:20:362224. Run clang-tidy.
223```
Peter Kasting0dc33482020-10-19 01:48:29224<PATH_TO_LLVM_SRC>/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py \
Takuto Ikuta2800dd82018-04-24 09:19:37225 -p . \# Set the root project directory, where compile_commands.json is.
rdevlin.croninbe2898eb2016-07-13 01:20:36226 # Set the clang-tidy binary path, if it's not in your $PATH.
227 -clang-tidy-binary <PATH_TO_LLVM_BUILD>/bin/clang-tidy \
228 # Set the clang-apply-replacements binary path, if it's not in your $PATH
229 # and you are using the `fix` behavior of clang-tidy.
230 -clang-apply-replacements-binary \
231 <PATH_TO_LLVM_BUILD>/bin/clang-apply-replacements \
Peter Kasting0dc33482020-10-19 01:48:29232 # The checks to employ in the build. Use `-*,...` to omit default checks.
rdevlin.croninbe2898eb2016-07-13 01:20:36233 -checks=<CHECKS> \
234 -header-filter=<FILTER> \# Optional, limit results to only certain files.
235 -fix \# Optional, used if you want to have clang-tidy auto-fix errors.
Peter Kasting0dc33482020-10-19 01:48:29236 'chrome/browser/.*' # A regex of the files you want to check.
rdevlin.croninbe2898eb2016-07-13 01:20:36237
238Copy-Paste Friendly (though you'll still need to stub in the variables):
Raul Tambree1c88012019-03-11 15:28:20239<PATH_TO_LLVM_SRC>/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py \
Takuto Ikuta2800dd82018-04-24 09:19:37240 -p . \
rdevlin.croninbe2898eb2016-07-13 01:20:36241 -clang-tidy-binary <PATH_TO_LLVM_BUILD>/bin/clang-tidy \
242 -clang-apply-replacements-binary \
243 <PATH_TO_LLVM_BUILD>/bin/clang-apply-replacements \
244 -checks=<CHECKS> \
245 -header-filter=<FILTER> \
246 -fix \
Peter Kasting0dc33482020-10-19 01:48:29247 'chrome/browser/.*'
rdevlin.croninbe2898eb2016-07-13 01:20:36248```
249
Peter Kasting0dc33482020-10-19 01:48:29250Note that the source file regex must match how the build specified the file.
251This means that on Windows, you must use (escaped) backslashes even from a bash
252shell.
rdevlin.croninbe2898eb2016-07-13 01:20:36253
George Burgess IV288fcf52019-12-18 02:19:46254### Questions
rdevlin.croninbe2898eb2016-07-13 01:20:36255
George Burgess IV288fcf52019-12-18 02:19:46256Questions about the local flow? Reach out to [email protected],
257[email protected], or [email protected].
258
259Questions about the Gerrit flow? Email [email protected] or
Eric Food0430a92022-01-24 17:54:54260[email protected], or file a bug against `Infra>LUCI>BuildService>PreSubmit>Tricium`.
George Burgess IV288fcf52019-12-18 02:19:46261Please CC [email protected] on any of these.
262
rdevlin.croninbe2898eb2016-07-13 01:20:36263Discoveries? Update the doc!