xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp (revision 7330f729ccf0bd976a06f95fad452fe774fc7fd1)
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 &registry) {
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