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