C++ 怎么编写自定义的 Clang-Tidy 静态检查插件检查团队特定的编码规范

雨明姑娘_4411

雨明姑娘_4411

2026-10-22

881人浏览

原创

clang-tidy插件必须实现clangtidycheck派生类并注册到clangtidymodule,缺一不可;需用ast匹配器定位模式,check()中须三重防护避免崩溃。

c++ 怎么编写自定义的 clang-tidy 静态检查插件检查团队特定的编码规范

Clang-Tidy 插件需要什么基础组件

必须实现 ClangTidyCheck 派生类,并注册到 ClangTidyModule;不提供完整模块注册,插件加载时会静默失败,连 -list-checks 都看不到你的检查项。

关键结构缺一不可:

  • MyCustomCheck 类继承自 clang::tidy::ClangTidyCheck,重写 registerMatchers() 和 check()
  • 一个继承 ClangTidyModule 的模块类,重写 createCheck() 并在 addCheckFactories() 中注册
  • CMakeLists.txt 里用 add_clang_library() 构建动态库(不是可执行文件),且链接 clangTooling、clangAST、clangLex 等依赖
  • 编译产物必须是 .so(Linux/macOS)或 .dll(Windows),且文件名符合 libMyModule.so 格式(Clang-Tidy 通过前缀 lib + 模块名识别)

怎么写 registerMatchers 定位团队规范中的典型模式

不能靠字符串匹配,必须用 Clang AST 匹配器(ast_matchers)。比如团队禁止裸指针成员变量,就得匹配 fieldDecl(hasType(pointerType())),而不是搜 "*"。

常见误判点:

  • 忽略模板上下文:用 fieldDecl() 默认不匹配类模板中的成员,需加 unless(isInstantiated()) 或显式处理 isTemplateInstantiation()
  • 过度匹配:varDecl() 会抓到函数内局部变量,加 hasParent(cxxRecordDecl()) 才能限定为类成员
  • 类型穿透不足:pointerType() 不匹配 const T*,要用 pointsTo(anything()) 或组合 qualType(hasCanonicalType(pointerType()))

示例:检查是否用了非 const 引用参数(团队要求输入参数尽量 const&)

void MyCustomCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(
      parmVarDecl(
          hasType(references(qualType(unless(isConstQualified()),
                                      hasCanonicalType(referenceType(pointee(qualType()))))))
      ).bind("nonConstRefParam"), this);
}

check() 里怎么安全生成诊断信息并避免崩溃

AST 节点可能为空、未完成解析或跨翻译单元失效,直接调 Node.getNodeAs<parmvardecl>("nonConstRefParam")->getType().getAsString()</parmvardecl> 很容易段错误。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

必须做三重防护:

  • 用 if (const auto *Param = Node.getNodeAs<parmvardecl>("nonConstRefParam"))</parmvardecl> 判空
  • 用 Param->getType().isNull() 检查类型有效性(尤其模板推导失败时)
  • 诊断位置用 Param->getLocation(),但要先 if (!Param->getLocation().isValid()) return;
  • 修复建议(FixItHint)只对源码存在的 token 生效;若想改模板特化里的参数,基本不可行——别硬塞 FixItHint::CreateReplacement()

示例中生成警告:

void MyCustomCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *Param = Result.Nodes.getNodeAs<parmvardecl>("nonConstRefParam");
  if (!Param || !Param->getLocation().isValid() || Param->getType().isNull())
    return;
  diag(Param->getLocation(), "non-const lvalue reference parameter violates team guideline")
      getLocation(), "const ");
}</parmvardecl>

怎么让插件被 clang-tidy 正确加载和调试

加载失败时不会报错,只会跳过——最常见原因是路径、命名或符号导出问题。

  • 插件路径必须通过 -plugin-path= 显式指定,且该路径下只能放 .so 文件,不能有子目录
  • 模块名(即 ClangTidyModule 子类名)必须与 add_clang_library(libMyModule) 中的库名一致,且首字母小写(Clang-Tidy 内部会把模块名转成小写再拼接 lib 前缀)
  • 确保符号可见:CMake 中添加 set_property(TARGET MyModule PROPERTY POSITION_INDEPENDENT_CODE ON),并用 __attribute__((visibility("default"))) 导出模块类
  • 调试时加 -debug 参数,观察日志里是否有 Loading module 'mymodule';没有就说明注册或路径错了

运行命令示例:

clang-tidy -plugin-path=/path/to/plugins -checks="-*,mymodule-non-const-ref-param" foo.cpp

最难调的是匹配逻辑和 AST 生命周期——节点在 check() 里看似可用,但一旦涉及 getDescribedClassTemplate() 或 getTemplateSpecializationKind(),极易因 Sema 未完成而返回空。这类问题没有通用解法,只能结合 -ast-dump 看实际 AST 结构,再调整 matcher 条件。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关专题

更多
c++和c语言的区别有哪些
c++和c语言的区别有哪些

c++和c语言的区别:1、面向对象编程(OOP)支持不同;2、新增特性不同;3、标准库不同;4、编译方式不同;5、命名空间不同等等。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.14

2248

9

c++和python学习顺序推荐
c++和python学习顺序推荐

一般建议先学习C++,再学习Python,因为这样可以逐步从较为底层的编程语言向更高级的语言过渡。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

1019

6

python和c++学习性价比分析
python和c++学习性价比分析

Python易于学习,广泛应用于Web开发、数据科学和人工智能等领域,但性能较低。C语言性能高,适用于对性能要求较高的场景,如游戏开发和系统编程,但学习曲线陡峭,错误处理复杂。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

447

5

c语言和c++一样吗
c语言和c++一样吗

c语言和c++是两种不同的编程语言,虽然有相似之处,但存在显著差异。c语言专注于过程式编程和系统级开发,以简洁、高效著称。c++作为c语言的超集,引入了面向对象编程,增强了代码组织和管理能力,但学习曲线也更陡峭。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

327

5

c语言和c++先学哪个好
c语言和c++先学哪个好

初学者选择学习c语言还是c++语言,需要根据个人学习目标、背景以及编程兴趣和预期应用方向来决定。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

406

5

c语言和c++的区别和联系
c语言和c++的区别和联系

c语言和c++是计算机科学领域应用广泛的编程语言。虽然它们有着相似的基础,但它们在语言类型、语法功能和内存管理方面存在着显著差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

580

5

c++软件中文更改教程
c++软件中文更改教程

对于 ide,可通过打开设置,找到语言设置,选择中文,并保存更改。对于非 ide 应用程序,可查找设置或选项,选择语言设置,更改为中文,并保存更改。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.21

1409

9

python和java和c++学习性价比分析
python和java和c++学习性价比分析

Python以其易学性、丰富的库和活跃的社区而著称,适合数据科学、人工智能和Web开发。Java以其跨平台性、企业级应用开发和Android应用开发而闻名。C++以其底层控制能力、高效性能和游戏开发而著称。选择哪种语言取决于个人兴趣、职业方向和特定需求。想了解更多python和java和c++的相关内容,可以阅读本专题下面的文章。

2024.03.22

1217

7

c++和c语言学习顺序推荐
c++和c语言学习顺序推荐

对于初学者,建议先学习C语言,掌握编程基础后再转入C++,便于理解面向对象编程概念。有编程经验者可直接学习C++,快速接触高级编程技术。想了解更多c++和c语言的相关内容,可以阅读本专题下面的文章。

2024.03.25

1325

9

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习