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.

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.

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).

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.

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. :)

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.