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 6 using namespace clang; 7 using namespace ento; 8 9 namespace { 10 class MainCallChecker : public Checker < check::PreStmt<CallExpr> > { 11 mutable std::unique_ptr<BugType> BT; 12 13 public: 14 void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; 15 }; 16 } // end anonymous namespace 17 18 void 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.generateErrorNode(); 34 if (!N) 35 return; 36 37 if (!BT) 38 BT.reset(new BugType(this, "call to main", "example analyzer plugin")); 39 40 std::unique_ptr<BugReport> report = 41 llvm::make_unique<BugReport>(*BT, BT->getName(), N); 42 report->addRange(Callee->getSourceRange()); 43 C.emitReport(std::move(report)); 44 } 45 } 46 47 // Register plugin! 48 extern "C" 49 void clang_registerCheckers (CheckerRegistry ®istry) { 50 registry.addChecker<MainCallChecker>("example.MainCallChecker", "Disallows calls to functions called main"); 51 } 52 53 extern "C" 54 const char clang_analyzerAPIVersionString[] = CLANG_ANALYZER_API_VERSION_STRING; 55