#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 ProgramStateRef state = C.getState(); const LocationContext *LC = C.getLocationContext(); const Expr *Callee = CE->getCallee(); const FunctionDecl *FD = state->getSVal(Callee, LC).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;