xref: /freebsd-src/contrib/llvm-project/clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp (revision 5b27928474e6a4103d65b347544705c40c9618fd)
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 &registry) {
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