andybons | 222c4ee | 2015-08-25 16:51:03 | [diff] [blame] | 1 | # The Clang Static Analyzer |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 2 | |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 3 | The Clang C/C++ compiler comes with a static analyzer which can be used to find |
| 4 | bugs using path sensitive analysis. Path sensitive analysis is |
| 5 | a technique that explores all the possible branches in code and |
| 6 | records the codepaths that might lead to bad or undefined behavior, |
| 7 | like an uninitialized reads, use after frees, pointer leaks, and so on. |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 8 | |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 9 | See the [official Clang static analyzer page](http://clang-analyzer.llvm.org/) |
| 10 | for more background information. |
| 11 | |
Nico Weber | db1eca9 | 2019-03-27 17:06:19 | [diff] [blame] | 12 | We used to have a bot that continuously ran with the static analyzer, |
| 13 | but people used to not look at it much. |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 14 | |
Nico Weber | db1eca9 | 2019-03-27 17:06:19 | [diff] [blame] | 15 | The static analyzer can still be invoked with [clang-tidy](clang_tidy.md). |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 16 | |
Nico Weber | db1eca9 | 2019-03-27 17:06:19 | [diff] [blame] | 17 | ## Recommended checks |
| 18 | Clang's static analyzer comes with a wide variety of checkers. Some of the |
| 19 | checks aren't useful because they are intended for different languages, |
| 20 | platforms, or coding conventions than the ones used for Chromium development. |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 21 | |
Nico Weber | db1eca9 | 2019-03-27 17:06:19 | [diff] [blame] | 22 | Checkers we found useful were: |
Daniel McArdle | b26068f | 2019-03-07 16:29:32 | [diff] [blame] | 23 | |
Nico Weber | db1eca9 | 2019-03-27 17:06:19 | [diff] [blame] | 24 | -analyzer-checker=core |
| 25 | -analyzer-checker=cpp |
| 26 | -analyzer-checker=unix |
| 27 | -analyzer-checker=deadcode |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 28 | |
| 29 | As of this writing, the checker suites we support are |
| 30 | [core](https://clang-analyzer.llvm.org/available_checks.html#core_checkers), |
| 31 | [cplusplus](https://clang-analyzer.llvm.org/available_checks.html#cplusplus_checkers), and |
| 32 | [deadcode](https://clang-analyzer.llvm.org/available_checks.html#deadcode_checkers). |
| 33 | |
Andrew Williams | 042e060 | 2022-01-27 13:56:23 | [diff] [blame] | 34 | To easily run these checks against Chromium code via clang-tidy, follow |
| 35 | [these](clang_tidy.md#evaluating_running-clang_tidy-across-chromium) |
| 36 | instructions to pull down `tricium_clang_tidy.py` and then pass the following |
| 37 | argument when invoking the script (`-*` disables all checks and then the |
| 38 | remaining check name globs enable each category of checks): |
| 39 | ``` |
| 40 | --tidy_checks="-*,clang-analyzer-core*,clang-analyzer-cplusplus*,clang-analyzer-unix*,clang-analyzer-deadcode*" |
| 41 | ``` |
| 42 | A full list of Clang analyzer checks can be found in the |
| 43 | [Clang-Tidy Checks List](https://clang.llvm.org/extra/clang-tidy/checks/list.html). |
| 44 | |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 45 | ## Addressing false positives |
| 46 | |
Nico Weber | db1eca9 | 2019-03-27 17:06:19 | [diff] [blame] | 47 | Some of the errors you encounter will be false positives, which occurs when the |
| 48 | static analyzer naively follows codepaths which are practically impossible to |
| 49 | hit at runtime. Fortunately, we have a tool at our disposal for guiding the |
| 50 | analyzer away from impossible codepaths: assertion handlers like |
| 51 | DCHECK/CHECK/LOG(FATAL). The analyzer won't check the codepaths which we |
| 52 | assert are unreachable. |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 53 | |
Nico Weber | db1eca9 | 2019-03-27 17:06:19 | [diff] [blame] | 54 | An example would be that if the analyzer detected the function argument |
| 55 | `*my_ptr` might be null and dereferencing it would potentially segfault, you |
| 56 | would see the error `warning: Dereference of null pointer (loaded from variable |
| 57 | 'my_ptr')`. If you know for a fact that my_ptr will not be null in practice, |
| 58 | then you can place an assert at the top of the function: `DCHECK(my_ptr)`. The |
| 59 | analyzer will no longer generate the warning. |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 60 | |
| 61 | Be mindful about only specifying assertions which are factually correct! Don't |
| 62 | DCHECK recklessly just to quiet down the analyzer. :) |
| 63 | |
| 64 | Other types of false positives and their suppressions: |
| 65 | * Unreachable code paths. To suppress, add the `ANALYZER_SKIP_THIS_PATH();` |
| 66 | directive to the relevant code block. |
Avi Drissman | 44d8af45 | 2022-01-25 19:08:20 | [diff] [blame] | 67 | * Dead stores. To suppress, use `[[maybe_unused]]`. This also suppresses dead |
| 68 | store warnings on conventional builds without static analysis enabled! |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 69 | |
Nico Weber | db1eca9 | 2019-03-27 17:06:19 | [diff] [blame] | 70 | See the definitions of the `ANALYZER_*` macros in base/logging.h for more |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 71 | detailed information about how the annotations are implemented. |
| 72 | |
| 73 | ## Logging bugs |
| 74 | |
| 75 | If you find any issues with the static analyzer, or find Chromium code behaving |
| 76 | badly with the analyzer, please check the `Infra>CodeAnalysis` CrBug component |
| 77 | to look for known issues, or file a bug if it is a new problem. |