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 | |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 34 | ## Addressing false positives |
| 35 | |
Nico Weber | db1eca9 | 2019-03-27 17:06:19 | [diff] [blame] | 36 | Some of the errors you encounter will be false positives, which occurs when the |
| 37 | static analyzer naively follows codepaths which are practically impossible to |
| 38 | hit at runtime. Fortunately, we have a tool at our disposal for guiding the |
| 39 | analyzer away from impossible codepaths: assertion handlers like |
| 40 | DCHECK/CHECK/LOG(FATAL). The analyzer won't check the codepaths which we |
| 41 | assert are unreachable. |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 42 | |
Nico Weber | db1eca9 | 2019-03-27 17:06:19 | [diff] [blame] | 43 | An example would be that if the analyzer detected the function argument |
| 44 | `*my_ptr` might be null and dereferencing it would potentially segfault, you |
| 45 | would see the error `warning: Dereference of null pointer (loaded from variable |
| 46 | 'my_ptr')`. If you know for a fact that my_ptr will not be null in practice, |
| 47 | then you can place an assert at the top of the function: `DCHECK(my_ptr)`. The |
| 48 | analyzer will no longer generate the warning. |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 49 | |
| 50 | Be mindful about only specifying assertions which are factually correct! Don't |
| 51 | DCHECK recklessly just to quiet down the analyzer. :) |
| 52 | |
| 53 | Other types of false positives and their suppressions: |
| 54 | * Unreachable code paths. To suppress, add the `ANALYZER_SKIP_THIS_PATH();` |
| 55 | directive to the relevant code block. |
Avi Drissman | 44d8af45 | 2022-01-25 19:08:20 | [diff] [blame^] | 56 | * Dead stores. To suppress, use `[[maybe_unused]]`. This also suppresses dead |
| 57 | store warnings on conventional builds without static analysis enabled! |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 58 | |
Nico Weber | db1eca9 | 2019-03-27 17:06:19 | [diff] [blame] | 59 | See the definitions of the `ANALYZER_*` macros in base/logging.h for more |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 60 | detailed information about how the annotations are implemented. |
| 61 | |
| 62 | ## Logging bugs |
| 63 | |
| 64 | If you find any issues with the static analyzer, or find Chromium code behaving |
| 65 | badly with the analyzer, please check the `Infra>CodeAnalysis` CrBug component |
| 66 | to look for known issues, or file a bug if it is a new problem. |