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 | You can now use these static analysis capabilities to find potential bugs in |
| 10 | Chromium code! Note that this capability is quite new, and as of this writing, |
| 11 | there are still a large number of warnings to be fixed in Chromium and especially |
| 12 | in its third_party dependencies. Some of the warnings might be false positives, |
| 13 | see the section on "Addressing false positives" for more information on |
| 14 | resolving them. |
andybons | 222c4ee | 2015-08-25 16:51:03 | [diff] [blame] | 15 | |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 16 | We're still evaluating this tool, please let us know if you find it useful. |
| 17 | |
| 18 | See the [official Clang static analyzer page](http://clang-analyzer.llvm.org/) |
| 19 | for more background information. |
| 20 | |
| 21 | ## Save some time, look at the buildbot logs! |
| 22 | |
| 23 | We run static analysis builds continously, all day long on FYI buildbots. |
| 24 | You can save yourself some time by first inspecting their build logs for errors |
| 25 | before running your own analysis builds. You will probably need to Ctrl-F the |
| 26 | logs to find any issues for the specific files you're interested in. |
| 27 | |
| 28 | You can find the analysis logs in the `compile stdout` step. |
| 29 | * [Linux buildbot logs](https://build.chromium.org/p/chromium.fyi/waterfall?show=Linux%20Clang%20Analyzer) |
| 30 | |
| 31 | ## Enabling static analysis |
| 32 | To get static analysis running for your build, add the following flag to your GN |
| 33 | args. |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 34 | |
| 35 | ``` |
kmarshall | 520f951 | 2017-01-24 23:25:01 | [diff] [blame] | 36 | use_clang_static_analyzer = true |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 37 | ``` |
| 38 | |
Kevin Marshall | 089565ec | 2017-07-13 02:57:21 | [diff] [blame] | 39 | The next time you run your build, you should see static analysis warnings appear |
| 40 | inline with the usual Clang build warnings and errors. Expect some slowdown on |
| 41 | your build; anywhere from a 10% increase on local builds, to well over 100% under Goma |
| 42 | ([crbug](crbug.com/733363)). |
| 43 | |
| 44 | ## Supported checks |
| 45 | Clang's static analyzer comes with a wide variety of checkers. Some of the checks |
| 46 | aren't useful because they are intended for different languages, platforms, or |
| 47 | coding conventions than the ones used for Chromium development. |
| 48 | |
| 49 | The checkers that we are interested in running for Chromium are in the |
| 50 | `analyzer_option_flags` variable in |
| 51 | [clang_static_analyzer_wrapper.py](../build/toolchain/clang_static_analyzer_wrapper.py). |
| 52 | |
| 53 | As of this writing, the checker suites we support are |
| 54 | [core](https://clang-analyzer.llvm.org/available_checks.html#core_checkers), |
| 55 | [cplusplus](https://clang-analyzer.llvm.org/available_checks.html#cplusplus_checkers), and |
| 56 | [deadcode](https://clang-analyzer.llvm.org/available_checks.html#deadcode_checkers). |
| 57 | |
| 58 | To add or remove checkers, simply modify the `-analyzer-checker=` flags. |
| 59 | Remember that checkers aren't free; additional checkers will add to the |
| 60 | analysis time. |
| 61 | |
| 62 | ## Addressing false positives |
| 63 | |
| 64 | Some of the errors you encounter might be false positives, which occurs when the |
| 65 | static analyzer naively follows codepaths which are practically impossible to hit |
| 66 | at runtime. Fortunately, we have a tool at our disposal for guiding the analyzer |
| 67 | away from impossible codepaths: assertion handlers like DCHECK/CHECK/LOG(FATAL). |
| 68 | The analyzer won't check the codepaths which we assert are unreachable. |
| 69 | |
| 70 | An example would be that if the analyzer detected the function argument `*my_ptr` |
| 71 | might be null and dereferencing it would potentially segfault, you would see the |
| 72 | error `warning: Dereference of null pointer (loaded from variable 'my_ptr')`. |
| 73 | If you know for a fact that my_ptr will not be null in practice, then you can |
| 74 | place an assert at the top of the function: `DCHECK(my_ptr)`. The analyzer will |
| 75 | no longer generate the warning. |
| 76 | |
| 77 | Be mindful about only specifying assertions which are factually correct! Don't |
| 78 | DCHECK recklessly just to quiet down the analyzer. :) |
| 79 | |
| 80 | Other types of false positives and their suppressions: |
| 81 | * Unreachable code paths. To suppress, add the `ANALYZER_SKIP_THIS_PATH();` |
| 82 | directive to the relevant code block. |
| 83 | * Dead stores. To suppress, use the macro |
| 84 | `ANALYZER_ALLOW_UNUSED(my_var)`. This also suppresses dead store warnings |
| 85 | on conventional builds without static analysis enabled! |
| 86 | |
| 87 | See the definitions of the ANALYZER_* macros in base/logging.h for more |
| 88 | detailed information about how the annotations are implemented. |
| 89 | |
| 90 | ## Logging bugs |
| 91 | |
| 92 | If you find any issues with the static analyzer, or find Chromium code behaving |
| 93 | badly with the analyzer, please check the `Infra>CodeAnalysis` CrBug component |
| 94 | to look for known issues, or file a bug if it is a new problem. |
| 95 | |
| 96 | *** |
| 97 | |
| 98 | ## Technical details |
| 99 | ### GN hooks |
| 100 | The platform toolchain .gni/BUILD.gn files check for the |
| 101 | `use_clang_static_analyzer` flag and modify the compiler command line so as to |
| 102 | call the analysis wrapper script rather than call the compiler directly. |
| 103 | The flag has no effect on assembler invocations, linker invocations, or |
| 104 | NaCl toolchain builds. |
| 105 | |
| 106 | ### Analysis wrapper script |
| 107 | The entry point for running analysis is the Python script |
| 108 | `//build/toolchain/clang_static_analyzer_wrapper.py` which invokes Clang |
| 109 | with the parameters for running static analysis. |
| 110 | |
| 111 | **Alternatives considered** |
| 112 | A script-less, GN-based solution is not possible because GN's control flows |
| 113 | are very limited in how they may be extended. |
| 114 | |
| 115 | The `scan-build` wrapper script included with Clang does not |
| 116 | work with Goma, so it couldn't be used. |
andybons | 3322f76 | 2015-08-24 21:37:09 | [diff] [blame] | 117 | |