自分は現役のフリーランスCエンジニアで、組み込み寄りの案件が多い。ずっと困っていたのがコードレビューの属人化だった。レビュアーによって指摘のバラつきが大きいし、MISRA準拠の確認は目視で毎回時間が溶ける。「前に指摘したやつ、本当に直った?」を定量的に追えない。
そこで、「人が目で見る前に機械で潰せる層」を段階に分けて整理した。結論だけ先に言うと、レビューで人間が頭を使うべきは設計判断だけにして、それ以外は L0〜L3 の4段で機械に落とす、という運用にしたら属人性がかなり消えた。この記事はその4段の中身と、各段で何が拾えて何が拾えないかの記録。
前提: 最初の砦はコンパイラ(L0)。自作ツールではない
先に大事なことを書いておく。C の安全性チェックの一段目は、静的解析ツールでも自作ツールでもなく、コンパイラの警告だ。ここをサボって高級なツールから入るのは順番が逆で、コスパが悪い。
自分は CI とローカルの両方で、まずこれを全部有効にして警告ゼロを強制している。
# GCC
gcc -std=c11 -Wall -Wextra -Wpedantic -Werror -fanalyzer -c foo.c
# Clang
clang -std=c11 -Weverything -Werror -c foo.c
-Werror で警告をビルドエラーに昇格させ、「L0 の警告がゼロにならない PR はレビューに入らない」を運用ルールにした。GCC の -fanalyzer は NULL 参照や解放後使用まで踏み込んでくれるし、Clang の -Weverything は一旦全部出してからノイズを個別に抑制していく。
契約をコンパイラに教えるのも L0 の仕事だ。
// NULL を渡してはいけない引数はコンパイラに宣言する(NULL 契約の第一選択)
void parse(const char *buf) __attribute__((nonnull));
// 戻り値を無視されたら困る関数は警告させる
int try_lock(lock_t *l) __attribute__((warn_unused_result));
nonnull と warn_unused_result を付けておくと、契約違反をコンパイル時に弾ける。ここまでで、低級なミスの大半は人間のレビュー前に死ぬ。
L1: コンパイラが見ないパターンを clang-tidy / cppcheck で拾う
L0 を通っても残るものがある。命名規約、関数の複雑度、一部の未初期化・範囲外、コンパイラが警告にしないイディオムの誤用。ここは clang-tidy と cppcheck の担当。
clang-tidy foo.c -- -std=c11
cppcheck --enable=all --std=c11 foo.c
L0+L1 で、「機械が定型で判定できる欠陥」はだいたい網羅できる。ここまでは無料の既存ツールで完結する。まずここを固めるのが先。
L0〜L1 で埋まらない層が、属人性の正体だった
問題は、L0/L1 を全部やっても残る層があることだった。自分の現場でレビューが属人化していた本当の原因はここにある。
- MISRA 準拠の体系的なチェック(ルール単位で「どこが違反か」を一覧にしたい)
- 仕様書との照合(「この関数、仕様どおりに例外処理してる?」をコードと突き合わせたい)
- リスクの分類(検出を重大度で仕分けして、直す順番を決めたい)
- 大規模コードベースでの影響範囲(数万行で「この変更、どこに波及する?」)
- 修正の定量追跡(前回の指摘が今回で減ったか)
これらは clang-tidy/cppcheck のスコープの外で、結局レビュアーの経験に頼っていた。=属人化。
L2: 設計レビューの壁打ちは creview(無料)に投げる
「設計として妥当か」の一次判断は、C 設計レビュー AI の creview に投げるようにした。無料で配布している。GitHub にある(github.com/ponfreelance/creview)。ここは人間のレビューの前段の壁打ち役。
L3: 監査レベルは自分で作った——CSAF
そして L0〜L2 で埋まらなかった「MISRA 準拠チェック・仕様書照合・リスク分類・監査レポート」を、自分用に作ったのが CSAF(C-Safety-audit-framework) だ。現場の課題から生まれたので、必要なものだけ入っている。
- libclang による AST 解析。ソースをテキストとして正規表現で舐めるのではなく、Clang の構文木を直接読む。コメント中の偶然の一致や記述スタイルの違いに惑わされない
- MISRA 違反検出だけでなく、仕様書との照合も AST ベース
- 検出をリスク分類し、HTML レポートに出力
- ローカル完結(コードを外に出さない。受託だと重要)
csaf audit --mode SAFETY --repo ./src
コマンド一発で、レビュー前に「機械で言えることは全部言い終わった」状態を作れる。人間のレビューは、そこから先の設計判断だけに集中できる。
商用の静的解析ツール(数十万円〜)の基本機能に相当する部分を、買い切り ¥4,980・ソースコード付きにしてある。自分のプロジェクト独自ルールも追加できる。全部を自作するのは大変だけど L3 の層は欲しい、という人向け。
→ CSAF(¥4,980・BOOTH): https://cutt.ly/5tKoVA2h
ブラウザで30秒体験できるデモを置きました(2026-07 追記)
CSAF がどんな指摘を出すか、インストール不要で試せる簡易デモを用意しました。
C コードを貼ると、危険箇所を A / B / C のリスク分類つきで指摘します
(AI による体験版です。製品版は libclang による決定的な静的解析で、結果の揺らぎはありません)。
👉 CSAF 体験デモ(ブラウザで動きます)
※実行には Claude アカウント(無料プラン可)でのログインが必要です
まとめ: 4段に分けると「人が頭を使う場所」だけ残る
| 段 | 何を | ツール | 費用 |
|---|---|---|---|
| L0 | コンパイラ警告ゼロを強制 | gcc/clang の -Wall -Wextra -Werror -fanalyzer 等 |
無料 |
| L1 | 定型パターン検出 | clang-tidy / cppcheck | 無料 |
| L2 | 設計レビューの壁打ち | creview | 無料 |
| L3 | MISRA準拠・仕様照合・リスク分類・監査レポート | CSAF | ¥4,980 |
順番が大事で、L0 を飛ばして上の層から入らない。まずコンパイラで警告ゼロ、次に clang-tidy/cppcheck、それでも埋まらない監査層だけを L2/L3 で埋める。この順で機械に落とすと、レビューで人間が見るのは「設計として正しいか」だけになって、属人性がかなり消えた。
著者:ぽん(@pon_freelance)