You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 06:26:27