1#include "clang/StaticAnalyzer/Core/Checker.h"
2#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
3#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
4#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
5
6using namespace clang;
7using namespace ento;
8
9namespace {
10class MainCallChecker : public Checker < check::PreStmt<CallExpr> > {
11  mutable std::unique_ptr<BugType> BT;
12
13public:
14  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
15};
16} // end anonymous namespace
17
18void MainCallChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
19  const ProgramStateRef state = C.getState();
20  const LocationContext *LC = C.getLocationContext();
21  const Expr *Callee = CE->getCallee();
22  const FunctionDecl *FD = state->getSVal(Callee, LC).getAsFunctionDecl();
23
24  if (!FD)
25    return;
26
27  // Get the name of the callee.
28  IdentifierInfo *II = FD->getIdentifier();
29  if (!II)   // if no identifier, not a simple C function
30    return;
31
32  if (II->isStr("main")) {
33    ExplodedNode *N = C.generateSink();
34    if (!N)
35      return;
36
37    if (!BT)
38      BT.reset(new BugType(this, "call to main", "example analyzer plugin"));
39
40    BugReport *report = new BugReport(*BT, BT->getName(), N);
41    report->addRange(Callee->getSourceRange());
42    C.emitReport(report);
43  }
44}
45
46// Register plugin!
47extern "C"
48void clang_registerCheckers (CheckerRegistry &registry) {
49  registry.addChecker<MainCallChecker>("example.MainCallChecker", "Disallows calls to functions called main");
50}
51
52extern "C"
53const char clang_analyzerAPIVersionString[] = CLANG_ANALYZER_API_VERSION_STRING;
54