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.

See the official Clang static analyzer page for more background information.

We used to have a bot that continuously ran with the static analyzer, but people used to not look at it much.

The static analyzer can still be invoked with clang-tidy.

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

Checkers we found useful were:

-analyzer-checker=core
-analyzer-checker=cpp
-analyzer-checker=unix
-analyzer-checker=deadcode

As of this writing, the checker suites we support are core, cplusplus, and deadcode.

To easily run these checks against Chromium code via clang-tidy, follow these instructions to pull down tricium_clang_tidy.py and then pass the following argument when invoking the script (-* disables all checks and then the remaining check name globs enable each category of checks):

--tidy_checks="-*,clang-analyzer-core*,clang-analyzer-cplusplus*,clang-analyzer-unix*,clang-analyzer-deadcode*"

A full list of Clang analyzer checks can be found in the Clang-Tidy Checks List.

Addressing false positives

Some of the errors you encounter will 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 [[maybe_unused]]. 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.