Clang静态分析器自定义Checker注册及生效问题排查
问题描述
我知道这个问题已有旧答案,但这些答案已经过时,不符合当前代码库的情况。我已按照《Checker开发手册》的步骤开发Checker、完成引擎注册并测试。编译代码成功后,执行clang -cc1 -analyzer-checker-help时我的Checker未显示,且发现大量Checker都不可见。是否需要在命令行显式启用Checker?若不需要,我遗漏了什么步骤?执行clang --analyze test.cpp或clang -cc1 -analyze test.cpp时,我的Checker未触发警告,但其他Checker(包括在帮助中不可见的)可以正常触发。
相关代码
MainCallChecker.cpp
using namespace clang; using namespace ento; namespace { class MainCallChecker : public Checker<check::PreCall> { mutable std::unique_ptr<BugType> BT; public: void checkPreCall(const CallEvent &Call, CheckerContext &C) const; }; } void MainCallChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const { if(const IdentifierInfo *II = Call.getCalleeIdentifier()) { if(II->isStr("main")) { if(!BT) { BT.reset(new BugType(this, "Call to main", "Example checker")); ExplodedNode *N = C.generateErrorNode(); auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getCheckerName(), N); C.emitReport(std::move(R)); } } } } void ento::registerMainCallChecker(CheckerManager &mgr){ mgr.registerChecker<MainCallChecker>(); }
Checkers.td
def MainCallChecker : Checker<"MainCall">, HelpText<"MyChecker">, Documentation<NotDocumented>;
CMakeLists.txt
add_clang_library(clangStaticAnalyzerCheckers . . MainCallChecker.cpp . . )
test.cpp
typedef int (*main_t)(int, char **); int main(int argc, char** argv) { main_t foo = main; int exit_code = foo(argc, argv); return exit_code; }
解决方案
1. 修复Checker未在帮助中显示的问题
必须在Checkers.td中为Checker指定所属包,否则它不会被归类到任何可见组,导致-analyzer-checker-help无法列出。测试用Checker通常放在Alpha包下,修改如下:
def MainCallChecker : Checker<"Alpha.MainCall">, HelpText<"Detects calls to the main function">, Documentation<NotDocumented>;
TableGen会根据这个声明生成关联的注册代码,确保Checker能被识别并在帮助中显示。
2. 修复Checker未触发的问题
原代码仅检测直接通过标识符调用的main,但测试代码是通过函数指针调用,Call.getCalleeIdentifier()会返回nullptr,因此无法触发。需修改逻辑,通过函数声明判断是否为main:
void MainCallChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const { const FunctionDecl *FD = Call.getDeclaredFunction(); if (!FD) return; if (FD->isMain()) { if (!BT) { BT.reset(new BugType(this, "Call to main", "Example checker")); } ExplodedNode *N = C.generateErrorNode(); if (N) { auto R = std::make_unique<PathSensitiveBugReport>(*BT, "Direct or indirect call to main function", N); C.emitReport(std::move(R)); } } }
FD->isMain()是Clang提供的标准方法,可覆盖直接调用、函数指针调用等所有场景。- 增加
N非空判断,避免空指针异常。
3. 正确启用Checker
编译完成后,需显式指定启用你的Checker(因属于Alpha测试包):
# 常规模式 clang --analyze -Xclang -analyzer-checker=Alpha.MainCall test.cpp # cc1模式 clang -cc1 -analyze -analyzer-checker=Alpha.MainCall test.cpp
内容的提问来源于stack exchange,提问作者Gianni Crivello
相关产品推荐
相关产品推荐

