This repository was archived by the owner on Oct 26, 2026. It is now read-only.
Repository navigation
Expand file tree
/
Copy path.clang-tidy
More file actions
90 lines (85 loc) · 6.54 KB
/
Copy path.clang-tidy
File metadata and controls
90 lines (85 loc) · 6.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# ripwire clang-tidy — ADVISORY, except for one narrow gating subset (scripts/tidycheck.sh).
#
# THIS FILE never fails a build: `WarningsAsErrors` is empty, and the CI step that runs it is
# `continue-on-error: true`. The reason is not timidity, it is scope. clang-tidy's default catalogue
# argues for a different C++ than the one CONTRIBUTING.md §3 asks for — bounds-checked containers,
# no C arrays, no `(int)x` casts, RAII everywhere — and this codebase is deliberately data-oriented:
# POD structs, SoA arrays, 32-bit handles, arena allocation, `ASSUME` instead of exceptions. A gate
# built from those checks would spend its life being suppressed. So the selection below is curated
# down to the classes that find real defects in code shaped like this one, and even those only report.
#
# WHAT GATES (0.6.3). scripts/tidycheck.sh runs `--checks='-*,<its GATING list>' --warnings-as-errors='*'`
# over the same five TUs, as its own CI step. It admits a check only when (a) every finding it can make is
# a program that computes a silently wrong answer and (b) it sat at ZERO rows here when admitted. Measured
# 2026-09-24 on 60b65f02, clang-tidy 22.1.8, the five CI TUs, rows de-duplicated by file:line:col:
# gated, 0 rows: bugprone-use-after-move (1 row, below), bugprone-dangling-handle 0,
# bugprone-sizeof-expression 0, bugprone-integer-division 0, bugprone-infinite-loop 0,
# clang-analyzer-core.* 0.
# The one use-after-move row, src/ingest_parsepool.h:528, is not a bug: the worker's `bytes` buffer is
# moved into the pending queue and every path to the next read refills it with readFile first. The
# moved-from state is now stated with `bytes.clear()` after the move — the check's own definition of a
# reinitialisation — rather than silenced with NOLINT.
# not gated: misc-redundant-expression 3 rows, all noise (u32() != A || u32() != B reads two
# different words; a static_assert that checks two masks which happen to share a type; a
# `!= npos` a later `<= 40` implies). Low noise, so it joins the advisory list below.
# concurrency-mt-unsafe 62 rows, 0 that can race: 45 getenv, 9 strerror, 6 exit, 1 setenv,
# 1 system. The only setenv is githarden's startup hardening, before any thread exists, so
# no getenv can race it, worker thread or not; exit is argument parsing; strerror
# formats a stderr line; glibc's and Apple's system() serialise themselves. Too noisy to
# report, so it is NOT in the advisory list.
# modernize-use-override 0 rows (src/ declares no virtual function), gated at first and
# moved to the advisory list after review: it reports a function that DOES override a base
# and only lacks the `override` keyword, so none of its findings is a wrong answer. (A
# drifted signature that overrides nothing is not what it reports.)
# A new finding in the gating subset is a bug to fix; a gated check that turns out to be noisy is removed
# from GATING with its count, the way it was admitted. Local run: scripts/tidycheck.sh (it SKIPs, loudly,
# without clang-tidy 22; on macOS it finds Homebrew's keg-only /opt/homebrew/opt/llvm@22/bin/clang-tidy).
#
# The `bugprone-*` family earns its place on evidence: the snprintf-truncation class it covers is a
# HIGH this repo actually shipped and had to fix. `bugprone-integer-division` and
# `bugprone-sizeof-expression` are called out for the same reason — both are silent-wrong-answer bugs
# in exactly the arithmetic (rank normalisation, CSR row sizing) this code is made of.
#
# Run it locally against the dev build's compile database:
# cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON && cmake --build build -j
# /opt/homebrew/opt/llvm@22/bin/clang-tidy -p build --quiet src/main.cpp src/ingest.cpp src/pagerank.cpp
# Use clang-tidy 22 to match the pinned clang-format major; older majors carry different check sets. On macOS a
# Homebrew clang-tidy also needs --extra-arg=-isysroot$(xcrun --show-sdk-path) to find the SDK headers.
Checks: >
-*,
bugprone-*,
bugprone-integer-division,
bugprone-sizeof-expression,
clang-analyzer-*,
performance-*,
misc-dangling-*,
misc-redundant-expression,
modernize-use-override,
-readability-*,
-modernize-avoid-c-arrays,
-cppcoreguidelines-pro-bounds-*
# Only our own headers. third_party/ is vendored verbatim (THIRD_PARTY.md) and is not ours to relint;
# system and tree-sitter headers would drown the report.
HeaderFilterRegex: '(^|/)src/.*\.(h|inl)$'
ExcludeHeaderFilterRegex: '(^|/)third_party/'
# Advisory posture. Do not populate WarningsAsErrors without also budgeting the suppression work —
# see the header note above, and re-read it before deciding a check "should obviously be a gate".
WarningsAsErrors: ''
# No automatic fixes. `-fix` on a data-oriented tree rewrites layout decisions that were made on purpose.
FormatStyle: none
# bugprone-easily-swappable-parameters is set to REVEAL, because the rows are real. Measured 2026-09-10 on e63e2d43
# with the style job's toolchain and version.h stamped: every one of the 209 rows the upstream defaults report was
# read and labeled. 208 are role pairs where a swap compiles and silently changes the answer — (root, pa
3E1D
th),
# (fileId, line), (topN, budgetBytes), out-parameter pairs — and 1 is noise. So every option that shrinks the table
# silences real rows. Counted per option: ModelImplicitConversions=false 31, MinimumLength=3 192, ignoring the
# string_view suffix 54, the name lists a;b;x;y / from;to;lo;hi;start;stop;open;close / second;lo;hi 4 / 9 / 1, and a
# name-affix threshold of 3 8. None of those is set. The two options below only ADD rows, and every added row is real:
# NamePrefixSuffixSilenceDissimilarityThreshold 0 (upstream 1): +3. Names one character apart were silenced as
# "similar", which hid archViolates(la, lb), findStringValue(vs, ve) and parseCappedCsvPair(capA, capB).
# QualifiersMix true (upstream false): +15. A const T& input beside a T& output, e.g. readFile(path, out): a swap
# compiles whenever the caller's input is a mutable lvalue, the common case here. These rows are also debt against
# CONTRIBUTING.md §3 "Interfaces" (structured-binding returns over out-params).
# SuppressParametersUsedTogether stays true: false adds 440 rows, most of them (a, b) / (i, n) noise.
CheckOptions:
bugprone-easily-swappable-parameters.NamePrefixSuffixSilenceDissimilarityThreshold: 0
bugprone-easily-swappable-parameters.QualifiersMix: true