| name | add-clang-tidy-check |
| description | Creates a new Clang Tidy check in the LLVM project. |
Adding a New Clang-Tidy Check
1. Create the Check Implementation
Files to create:
src/clang-tools-extra/clang-tidy/<module>/<CheckName>Check.h - Header with class declaration
src/clang-tools-extra/clang-tidy/<module>/<CheckName>Check.cpp - Implementation
Key components:
class MyCheck : public ClangTidyCheck {
public:
MyCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override;
};
void MyCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(.bind("name"), this);
}
void MyCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Node = Result.Nodes.getNodeAs<NodeType>("name");
diag(Loc, "message") << FixItHint::CreateRemoval(Range);
}
2. Register the Check
File: src/clang-tools-extra/clang-tidy/<module>/<Module>TidyModule.cpp
#include "MyCheck.h"
CheckFactories.registerCheck<MyCheck>("module-check-name");
File: src/clang-tools-extra/clang-tidy/<module>/CMakeLists.txt
Add MyCheck.cpp to the source list.
3. Create Tests (Test-Driven Development)
File: src/clang-tools-extra/test/clang-tidy/checkers/<module>/check-name.cpp
void test_case() {
}
void test_negative() {
}
Build and run tests:
ninja check-clang-extra-clang-tidy-checkers
python3 bin/llvm-lit -v ../src/clang-tools-extra/test/clang-tidy/checkers/<module>/check-name.cpp
4. Add Documentation
File: src/clang-tools-extra/docs/clang-tidy/checks/<module>/check-name.rst
.. title:: clang-tidy - module-check-name
module-check-name
=================
Brief description of what the check does.
Example
-------
.. code-block:: c++
// Before
code_before();
Transforms to:
.. code-block:: c++
// After
code_after();
File: src/clang-tools-extra/docs/clang-tidy/checks/list.rst
Add entry alphabetically:
:doc:`module-check-name <module/check-name>`, "Yes"
File: src/clang-tools-extra/docs/ReleaseNotes.rst
Under "New checks":
- New :doc:`module-check-name
<clang-tidy/checks/module/check-name>` check.
Brief description.
5. Test on Real Codebase
python3 src/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py \
-p build \
-clang-tidy-binary build/bin/clang-tidy \
-checks='-*,module-check-name' \
'path/.*\.cpp$' 2>&1 | tee diagnostics.txt
python3 ... -fix 'path/.*\.cpp$'
ninja -C build check-<target>
Key Tips
- Start with tests - Write test cases first to define expected behavior
- Keep matchers simple - Do complex checks in
check(), not in matchers
- Use
assert for bound nodes - If matcher succeeded, nodes should exist
- Handle macros gracefully - Check
isMacroID() before emitting fix-its
- Use notes for clarity - Point to relevant locations with
DiagnosticIDs::Note
- Minimize test cases - Remove redundant tests that don't increase coverage
- Test on real code - Run on actual codebase (e.g., MLIR) before finalizing
- Debug with AST dump - When matching fails unexpectedly, dump the AST to see the actual structure:
build/bin/clang -Xclang -ast-dump -fsyntax-only -std=c++17 test.cpp
Files Summary
| Purpose | Path |
|---|
| Check header | src/clang-tools-extra/clang-tidy/<module>/<CheckName>Check.h |
| Check impl | src/clang-tools-extra/clang-tidy/<module>/<CheckName>Check.cpp |
| Module registration | src/clang-tools-extra/clang-tidy/<module>/<Module>TidyModule.cpp |
| CMake | src/clang-tools-extra/clang-tidy/<module>/CMakeLists.txt |
| Test | src/clang-tools-extra/test/clang-tidy/checkers/<module>/check-name.cpp |
| Documentation | src/clang-tools-extra/docs/clang-tidy/checks/<module>/check-name.rst |
| Check list | src/clang-tools-extra/docs/clang-tidy/checks/list.rst |
| Release notes | src/clang-tools-extra/docs/ReleaseNotes.rst |