|  | #include "clang/StaticAnalyzer/Core/Checker.h" | 
|  | #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" | 
|  | #include "clang/StaticAnalyzer/Core/CheckerRegistry.h" | 
|  | #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" | 
|  |  | 
|  | using namespace clang; | 
|  | using namespace ento; | 
|  |  | 
|  | namespace { | 
|  | class MainCallChecker : public Checker < check::PreStmt<CallExpr> > { | 
|  | mutable std::unique_ptr<BugType> BT; | 
|  |  | 
|  | public: | 
|  | void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; | 
|  | }; | 
|  | } // end anonymous namespace | 
|  |  | 
|  | void MainCallChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const { | 
|  | const Expr *Callee = CE->getCallee(); | 
|  | const FunctionDecl *FD = C.getSVal(Callee).getAsFunctionDecl(); | 
|  |  | 
|  | if (!FD) | 
|  | return; | 
|  |  | 
|  | // Get the name of the callee. | 
|  | IdentifierInfo *II = FD->getIdentifier(); | 
|  | if (!II)   // if no identifier, not a simple C function | 
|  | return; | 
|  |  | 
|  | if (II->isStr("main")) { | 
|  | ExplodedNode *N = C.generateErrorNode(); | 
|  | if (!N) | 
|  | return; | 
|  |  | 
|  | if (!BT) | 
|  | BT.reset(new BugType(this, "call to main", "example analyzer plugin")); | 
|  |  | 
|  | std::unique_ptr<BugReport> report = | 
|  | llvm::make_unique<BugReport>(*BT, BT->getName(), N); | 
|  | report->addRange(Callee->getSourceRange()); | 
|  | C.emitReport(std::move(report)); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Register plugin! | 
|  | extern "C" | 
|  | void clang_registerCheckers (CheckerRegistry ®istry) { | 
|  | registry.addChecker<MainCallChecker>("example.MainCallChecker", "Disallows calls to functions called main"); | 
|  | } | 
|  |  | 
|  | extern "C" | 
|  | const char clang_analyzerAPIVersionString[] = CLANG_ANALYZER_API_VERSION_STRING; |