xref: /openbsd-src/gnu/llvm/clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp (revision e5dd70708596ae51455a0ffa086a00c5b29f8583)
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 &registry) {
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