10b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
20b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/Checker.h"
30b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
40b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
50b57cec5SDimitry Andric
60b57cec5SDimitry Andric using namespace clang;
70b57cec5SDimitry Andric using namespace ento;
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric namespace {
100b57cec5SDimitry Andric class MainCallChecker : public Checker<check::PreStmt<CallExpr>> {
110b57cec5SDimitry Andric mutable std::unique_ptr<BugType> BT;
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric public:
140b57cec5SDimitry Andric void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
150b57cec5SDimitry Andric };
160b57cec5SDimitry Andric } // end anonymous namespace
170b57cec5SDimitry Andric
checkPreStmt(const CallExpr * CE,CheckerContext & C) const180b57cec5SDimitry Andric void MainCallChecker::checkPreStmt(const CallExpr *CE,
190b57cec5SDimitry Andric CheckerContext &C) const {
200b57cec5SDimitry Andric const Expr *Callee = CE->getCallee();
210b57cec5SDimitry Andric const FunctionDecl *FD = C.getSVal(Callee).getAsFunctionDecl();
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric if (!FD)
240b57cec5SDimitry Andric return;
250b57cec5SDimitry Andric
260b57cec5SDimitry Andric // Get the name of the callee.
270b57cec5SDimitry Andric IdentifierInfo *II = FD->getIdentifier();
280b57cec5SDimitry Andric if (!II) // if no identifier, not a simple C function
290b57cec5SDimitry Andric return;
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric if (II->isStr("main")) {
320b57cec5SDimitry Andric ExplodedNode *N = C.generateErrorNode();
330b57cec5SDimitry Andric if (!N)
340b57cec5SDimitry Andric return;
350b57cec5SDimitry Andric
360b57cec5SDimitry Andric if (!BT)
370b57cec5SDimitry Andric BT.reset(new BugType(this, "call to main", "example analyzer plugin"));
380b57cec5SDimitry Andric
39*a7dea167SDimitry Andric auto report =
40*a7dea167SDimitry Andric std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
410b57cec5SDimitry Andric report->addRange(Callee->getSourceRange());
420b57cec5SDimitry Andric C.emitReport(std::move(report));
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric // Register plugin!
clang_registerCheckers(CheckerRegistry & registry)470b57cec5SDimitry Andric extern "C" void clang_registerCheckers(CheckerRegistry ®istry) {
480b57cec5SDimitry Andric registry.addChecker<MainCallChecker>(
490b57cec5SDimitry Andric "example.MainCallChecker", "Disallows calls to functions called main",
500b57cec5SDimitry Andric "");
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric extern "C" const char clang_analyzerAPIVersionString[] =
540b57cec5SDimitry Andric CLANG_ANALYZER_API_VERSION_STRING;
55