How do I register my Clang Static Analyzer checker

I am fully aware that this question has previous answers. However, those answers are old and don’t seem to reflect what is happening in the current code base.

I have followed the steps in this guide for developing the checker, registering it with the engine, and testing it.

After some work, I was able to compile the code but when running clang -cc1 -analyzer-checker-help my checker is not visible. I Have noticed that a lot of the checkers aren’t visible.

Do I need to explicitly enable the checker on the command line? If not what have I missed?

When I run clang --analyze test.cpp of clang -cc1 -analyze test.cpp my checker does not raise a warning. But others do, even those “not visible” in the clang -cc1 -analyzer-checker-help command.

My code:

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>;

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;
        
}

Since the documentation is not always up to date. I always look at other checkers.
The SimpleStreamChecker is quite small and there is the “Building a Checker in 24 hours” talk explaining it.

After looking at your source, I noticed you are missing the following lines:

bool ento::shouldRegisterMainCallChecker(const CheckerManager &mgr) {
  return true;
}

see here fore more information.

When I ran it on you test file i got the following:

$ bin/scan-build -enable-checker alpha.unix.MainCall bin/clang -g ~/test.cpp
scan-build: Using '/home/mschroetter/project/llvm-project/build/bin/clang-15' for static analysis
/home/mschroetter/test.cpp:4:25: warning: alpha.unix.MainCall [alpha.unix.MainCall]
        int exit_code = foo(argc, argv);
                        ^~~~~~~~~~~~~~~
1 warning generated.
scan-build: Analysis run complete.
scan-build: 1 bug found.
scan-build: Run 'scan-view /tmp/scan-build-2022-11-29-231029-8632-1' to examine bug reports.

I also needed to enable the checker because I put it under alpha.unix in the checkers.td and those are always disabled by default.

1 Like

Thank you so much for the help! Everything is working now. We ought to update some of the documentation for writing checkers. It would make getting started a whole lot less painful.

Yeah we definitely need to update that :expressionless: Thanks @schrc3b6 for investigating it! :blush:

@giannicrivello, I noticed that you’re sending us patches. That guide actually lives in llvm-project as well (llvm-project/checker_dev_manual.html at main · llvm/llvm-project · GitHub) so when you find mistakes or omissions, you can fix them right away! And more importantly, your perspective as a newcomer is very valuable because a lot of the folks who know the answers, also forgot that they ever needed those answers. So please feel free to re-tailor the documentation to clarify things you personally found confusing!

1 Like

Thanks! Will do! @NoQ