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 &registry) {
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