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