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