
用 LLVM/Clang LibTooling 编写 C++ 静态分析工具,核心是绕过编译器前端黑盒,直接在 AST 层做语义检查——不是靠正则或字符串匹配,而是真正理解代码结构、类型、作用域和控制流。
LibTooling 是 LLVM 的 C++ 库接口,必须从源码构建(或使用预编译的 libclang-dev + libc++-dev + llvm-dev 包),仅装 clang 命令行工具无法链接 libTooling。推荐方式:
llvm-dev、libclang-1x-dev(x ≥ 14)、libc++-dev,确保 llvm-config 和 clang++ 版本一致brew install llvm,然后用 $(brew --prefix llvm)/bin/clang++ 编译,链接时指定 -lclangTooling -lclangFrontend -lclangSerialization -lclangDriver -lclangAST -lclangParse -lclangSema -lclangLex -lclangBasic -lLLVM
llvm-config --libs tooling frontend ast parse sema 看是否输出对应库名别一上来就写 ASTConsumer;用 clang::ast_matchers + MatchFinder 是最稳妥的起点——它把 AST 遍历封装成声明式规则,避免手动递归、生命周期管理出错。
std::strcpy 的地方:callExpr(callee(functionDecl(hasName("strcpy"))))
MatchCallback,重写 run(const MatchResult &),用 Result.Nodes.getNodeAs<callexpr>("expr")</callexpr> 提取节点run() 中拿到的是 const 节点指针,不能改 AST;如需修改(如自动修复),得用 ASTRewriter + SourceManager 定位位置并生成新文本单纯匹配函数名没意义。真正静态分析要结合类型、值流、控制流:
立即学习“C++免费学习笔记(深入)”;
call->getArg(0)->getType().getCanonicalType().getAsString(),再用 isPointerType() 或 isConstQualified() 判断varDecl(hasInitializer(expr())) + getNodeAs<vardecl>("v")->getInit()->getSourceRange()</vardecl>
ASTUnit 缓存 + 符号表重建,复杂度陡增getQualifiedNameAsString() 对模板实例化返回空,要用 getQualifiedName().getAsString() + 检查 isAnonymousOrUnresolved()
让工具被团队用起来,关键在易用性和误报率控制:
CompilationDatabase::loadFromDirectory() 自动读取项目编译配置,不用手动传 -I/-Dclang::tooling::ClangTool 的 run() 接口配合文件时间戳跳过未改文件file:line:col: severity: message(如 main.cpp:42:5: warning: unsafe strcpy usage),VS Code/CLion 可自动高亮// NOLINT 或自定义注释(用 SourceManager 查当前行注释字符串),别硬编码跳过逻辑基本上就这些。不复杂但容易忽略细节:版本对齐、AST 生命周期、跨 TU 限制、语义查询边界。写一个能发现 std::vector::at() 未检查异常的检查器,200 行以内就能跑通;想覆盖 RAII 泄漏或虚函数调用歧义,就得深入 Sema 和 CFG(Control Flow Graph)了。
以上就是c++++如何使用LLVM/Clang LibTooling_c++编写自己的静态分析工具【高级】的详细内容,更多请关注php中文网其它相关文章!
c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号