Turning Repeated C++ Review Feedback into clang-tidy Checks

โšก LLVM ๐Ÿ”ง C++ / Clang ๐Ÿ‘ค Helmut Januschka

Automating recurring modernization suggestions so they can be applied consistently.

Status: Ongoing | Merged PR: #116033


The Origin Story

Years ago, while working on Chromium, Peter Kasting introduced me to clang-tidy. During code reviews he'd point out patterns that could be automated - things he'd seen hundreds of times, anti-patterns that kept appearing, modernization opportunities too tedious to do by hand.

I started keeping my own scratchpad, jotting down his suggestions and ideas. That document sat there for years - until I recently picked it back up.

Why clang-tidy Matters for Large Codebases

In a large C++ codebase such as Chromium, recurring modernization patterns are difficult to apply consistently by hand. clang-tidy can identify a specific pattern, explain the replacement, and in suitable cases generate the edit automatically.

Chromium actively uses clang-tidy for ongoing modernization. The base::StringPiece to std::string_view migration, the adoption of std::optional, the move to starts_with/ends_with - all of these are driven by clang-tidy checks that find patterns and transform them at scale.

Extending modernize-use-starts-ends-with

The merged PR extends an existing check to detect a common pattern:

// Before: Creates a temporary string, then compares
if (str.substr(0, 5) == "hello") { ... }

// After: Direct comparison, no allocation
if (str.starts_with("hello")) { ... }

The starts_with method was added in C++20. It's clearer, faster (no temporary string), and expresses intent better.

The PR (#116033) extended modernize-use-starts-ends-with to catch substr patterns. The review process was educational - the LLVM community suggested integrating it into the existing check rather than creating a new one.

Key patterns now detected:

Candidate Checks

Some older review suggestions became practical once C++20 and C++23 facilities were available. The following PRs explore those patterns:

Modernization checks:

Readability checks:

Enhancements:

The Chromium Connection

A code-search sample shows how often several of these patterns occur in Chromium:

Pattern Check Instances
.substr(0, n) == modernize-use-starts-ends-with ~730
.find(x) == 0 modernize-use-starts-ends-with ~1,100
.compare(0, n) modernize-use-starts-ends-with ~50
.subspan(0, n) readability-use-span-first-last ~10

These are candidate matches, not automatic proof that every occurrence should change. The check still needs to account for types, semantics, and cases where a fix would reduce clarity.


The useful part of the scratchpad was preserving concrete review examples until the language and tooling could express them reliably.

Thanks to: