blob: 39a51336da708b361692b636c73df09ac50d6327 [file] [log] [blame] [view]
# The Clang Static Analyzer
The Clang C/C++ compiler comes with a static analyzer which can be used to find
bugs using path sensitive analysis. Path sensitive analysis is
a technique that explores all the possible branches in code and
records the codepaths that might lead to bad or undefined behavior,
like an uninitialized reads, use after frees, pointer leaks, and so on.
You can now use these static analysis capabilities to find potential bugs in
Chromium code! Note that this capability is quite new, and as of this writing,
there are still a large number of warnings to be fixed in Chromium and especially
in its third_party dependencies. Some of the warnings might be false positives,
see the section on "Addressing false positives" for more information on
resolving them.
We're still evaluating this tool, please let us know if you find it useful.
See the [official Clang static analyzer page](http://clang-analyzer.llvm.org/)
for more background information.
## Save some time, look at the buildbot logs!
We run static analysis builds continously, all day long on FYI buildbots.
You can save yourself some time by first inspecting their build logs for errors
before running your own analysis builds. You will probably need to Ctrl-F the
logs to find any issues for the specific files you're interested in.
You can find the analysis logs in the `compile stdout` step.
* [Linux buildbot logs](https://build.chromium.org/p/chromium.fyi/waterfall?show=Linux%20Clang%20Analyzer)
## Enabling static analysis
To get static analysis running for your build, add the following flag to your GN
args.
```
use_clang_static_analyzer = true
```
The next time you run your build, you should see static analysis warnings appear
inline with the usual Clang build warnings and errors. Expect some slowdown on
your build; anywhere from a 10% increase on local builds, to well over 100% under Goma
([crbug](crbug.com/733363)).
## Supported checks
Clang's static analyzer comes with a wide variety of checkers. Some of the checks
aren't useful because they are intended for different languages, platforms, or
coding conventions than the ones used for Chromium development.
The checkers that we are interested in running for Chromium are in the
`analyzer_option_flags` variable in
[clang_static_analyzer_wrapper.py](../build/toolchain/clang_static_analyzer_wrapper.py).
As of this writing, the checker suites we support are
[core](https://clang-analyzer.llvm.org/available_checks.html#core_checkers),
[cplusplus](https://clang-analyzer.llvm.org/available_checks.html#cplusplus_checkers), and
[deadcode](https://clang-analyzer.llvm.org/available_checks.html#deadcode_checkers).
To add or remove checkers, simply modify the `-analyzer-checker=` flags.
Remember that checkers aren't free; additional checkers will add to the
analysis time.
## Addressing false positives
Some of the errors you encounter might be false positives, which occurs when the
static analyzer naively follows codepaths which are practically impossible to hit
at runtime. Fortunately, we have a tool at our disposal for guiding the analyzer
away from impossible codepaths: assertion handlers like DCHECK/CHECK/LOG(FATAL).
The analyzer won't check the codepaths which we assert are unreachable.
An example would be that if the analyzer detected the function argument `*my_ptr`
might be null and dereferencing it would potentially segfault, you would see the
error `warning: Dereference of null pointer (loaded from variable 'my_ptr')`.
If you know for a fact that my_ptr will not be null in practice, then you can
place an assert at the top of the function: `DCHECK(my_ptr)`. The analyzer will
no longer generate the warning.
Be mindful about only specifying assertions which are factually correct! Don't
DCHECK recklessly just to quiet down the analyzer. :)
Other types of false positives and their suppressions:
* Unreachable code paths. To suppress, add the `ANALYZER_SKIP_THIS_PATH();`
directive to the relevant code block.
* Dead stores. To suppress, use the macro
`ANALYZER_ALLOW_UNUSED(my_var)`. This also suppresses dead store warnings
on conventional builds without static analysis enabled!
See the definitions of the ANALYZER_* macros in base/logging.h for more
detailed information about how the annotations are implemented.
## Logging bugs
If you find any issues with the static analyzer, or find Chromium code behaving
badly with the analyzer, please check the `Infra>CodeAnalysis` CrBug component
to look for known issues, or file a bug if it is a new problem.
***
## Technical details
### GN hooks
The platform toolchain .gni/BUILD.gn files check for the
`use_clang_static_analyzer` flag and modify the compiler command line so as to
call the analysis wrapper script rather than call the compiler directly.
The flag has no effect on assembler invocations, linker invocations, or
NaCl toolchain builds.
### Analysis wrapper script
The entry point for running analysis is the Python script
`//build/toolchain/clang_static_analyzer_wrapper.py` which invokes Clang
with the parameters for running static analysis.
**Alternatives considered**
A script-less, GN-based solution is not possible because GN's control flows
are very limited in how they may be extended.
The `scan-build` wrapper script included with Clang does not
work with Goma, so it couldn't be used.