xref: /src/contrib/llvm-project/clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp (revision a7dea1671b87c07d2d266f836bfa8b58efc7c134)
122989816SDimitry Andric #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
222989816SDimitry Andric #include "clang/StaticAnalyzer/Core/Checker.h"
322989816SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
422989816SDimitry Andric #include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
522989816SDimitry Andric 
622989816SDimitry Andric using namespace clang;
722989816SDimitry Andric using namespace ento;
822989816SDimitry Andric 
922989816SDimitry Andric namespace {
1022989816SDimitry Andric class MainCallChecker : public Checker<check::PreStmt<CallExpr>> {
1122989816SDimitry Andric   mutable std::unique_ptr<BugType> BT;
1222989816SDimitry Andric 
1322989816SDimitry Andric public:
1422989816SDimitry Andric   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
1522989816SDimitry Andric };
1622989816SDimitry Andric } // end anonymous namespace
1722989816SDimitry Andric 
checkPreStmt(const CallExpr * CE,CheckerContext & C) const1822989816SDimitry Andric void MainCallChecker::checkPreStmt(const CallExpr *CE,
1922989816SDimitry Andric                                    CheckerContext &C) const {
2022989816SDimitry Andric   const Expr *Callee = CE->getCallee();
2122989816SDimitry Andric   const FunctionDecl *FD = C.getSVal(Callee).getAsFunctionDecl();
2222989816SDimitry Andric 
2322989816SDimitry Andric   if (!FD)
2422989816SDimitry Andric     return;
2522989816SDimitry Andric 
2622989816SDimitry Andric   // Get the name of the callee.
2722989816SDimitry Andric   IdentifierInfo *II = FD->getIdentifier();
2822989816SDimitry Andric   if (!II) // if no identifier, not a simple C function
2922989816SDimitry Andric     return;
3022989816SDimitry Andric 
3122989816SDimitry Andric   if (II->isStr("main")) {
3222989816SDimitry Andric     ExplodedNode *N = C.generateErrorNode();
3322989816SDimitry Andric     if (!N)
3422989816SDimitry Andric       return;
3522989816SDimitry Andric 
3622989816SDimitry Andric     if (!BT)
3722989816SDimitry Andric       BT.reset(new BugType(this, "call to main", "example analyzer plugin"));
3822989816SDimitry Andric 
39519fc96cSDimitry Andric     auto report =
40519fc96cSDimitry Andric         std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
4122989816SDimitry Andric     report->addRange(Callee->getSourceRange());
4222989816SDimitry Andric     C.emitReport(std::move(report));
4322989816SDimitry Andric   }
4422989816SDimitry Andric }
4522989816SDimitry Andric 
4622989816SDimitry Andric // Register plugin!
clang_registerCheckers(CheckerRegistry & registry)4722989816SDimitry Andric extern "C" void clang_registerCheckers(CheckerRegistry &registry) {
4822989816SDimitry Andric   registry.addChecker<MainCallChecker>(
4922989816SDimitry Andric       "example.MainCallChecker", "Disallows calls to functions called main",
5022989816SDimitry Andric       "");
5122989816SDimitry Andric }
5222989816SDimitry Andric 
5322989816SDimitry Andric extern "C" const char clang_analyzerAPIVersionString[] =
5422989816SDimitry Andric     CLANG_ANALYZER_API_VERSION_STRING;
55