1 #include "clang/StaticAnalyzer/Core/Checker.h" 2 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 3 #include "clang/StaticAnalyzer/Core/CheckerRegistry.h" 4 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 5 6 using namespace clang; 7 using namespace ento; 8 9 namespace { 10 class MainCallChecker : public Checker < check::PreStmt<CallExpr> > { 11 mutable OwningPtr<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.generateSink(); 34 if (!N) 35 return; 36 37 if (!BT) 38 BT.reset(new BugType("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! 47 extern "C" 48 void clang_registerCheckers (CheckerRegistry ®istry) { 49 registry.addChecker<MainCallChecker>("example.MainCallChecker", "Disallows calls to functions called main"); 50 } 51 52 extern "C" 53 const char clang_analyzerAPIVersionString[] = CLANG_ANALYZER_API_VERSION_STRING; 54