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