12754fe60SDimitry Andric //===--- UndefinedArraySubscriptChecker.h ----------------------*- C++ -*--===// 22754fe60SDimitry Andric // 32754fe60SDimitry Andric // The LLVM Compiler Infrastructure 42754fe60SDimitry Andric // 52754fe60SDimitry Andric // This file is distributed under the University of Illinois Open Source 62754fe60SDimitry Andric // License. See LICENSE.TXT for details. 72754fe60SDimitry Andric // 82754fe60SDimitry Andric //===----------------------------------------------------------------------===// 92754fe60SDimitry Andric // 102754fe60SDimitry Andric // This defines UndefinedArraySubscriptChecker, a builtin check in ExprEngine 112754fe60SDimitry Andric // that performs checks for undefined array subscripts. 122754fe60SDimitry Andric // 132754fe60SDimitry Andric //===----------------------------------------------------------------------===// 142754fe60SDimitry Andric 15*b5893f02SDimitry Andric #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" 16f785676fSDimitry Andric #include "clang/AST/DeclCXX.h" 17139f7f9bSDimitry Andric #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 183b0f4066SDimitry Andric #include "clang/StaticAnalyzer/Core/Checker.h" 193b0f4066SDimitry Andric #include "clang/StaticAnalyzer/Core/CheckerManager.h" 203b0f4066SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 212754fe60SDimitry Andric 222754fe60SDimitry Andric using namespace clang; 232754fe60SDimitry Andric using namespace ento; 242754fe60SDimitry Andric 252754fe60SDimitry Andric namespace { 262754fe60SDimitry Andric class UndefinedArraySubscriptChecker 273b0f4066SDimitry Andric : public Checker< check::PreStmt<ArraySubscriptExpr> > { 2859d1ed5bSDimitry Andric mutable std::unique_ptr<BugType> BT; 293b0f4066SDimitry Andric 302754fe60SDimitry Andric public: 313b0f4066SDimitry Andric void checkPreStmt(const ArraySubscriptExpr *A, CheckerContext &C) const; 322754fe60SDimitry Andric }; 332754fe60SDimitry Andric } // end anonymous namespace 342754fe60SDimitry Andric 352754fe60SDimitry Andric void checkPreStmt(const ArraySubscriptExpr * A,CheckerContext & C) const363b0f4066SDimitry AndricUndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A, 373b0f4066SDimitry Andric CheckerContext &C) const { 38139f7f9bSDimitry Andric const Expr *Index = A->getIdx(); 39139f7f9bSDimitry Andric if (!C.getSVal(Index).isUndef()) 40139f7f9bSDimitry Andric return; 41139f7f9bSDimitry Andric 42139f7f9bSDimitry Andric // Sema generates anonymous array variables for copying array struct fields. 43139f7f9bSDimitry Andric // Don't warn if we're in an implicitly-generated constructor. 44139f7f9bSDimitry Andric const Decl *D = C.getLocationContext()->getDecl(); 45139f7f9bSDimitry Andric if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) 46f785676fSDimitry Andric if (Ctor->isDefaulted()) 47139f7f9bSDimitry Andric return; 48139f7f9bSDimitry Andric 490623d748SDimitry Andric ExplodedNode *N = C.generateErrorNode(); 50139f7f9bSDimitry Andric if (!N) 51139f7f9bSDimitry Andric return; 522754fe60SDimitry Andric if (!BT) 5359d1ed5bSDimitry Andric BT.reset(new BuiltinBug(this, "Array subscript is undefined")); 542754fe60SDimitry Andric 552754fe60SDimitry Andric // Generate a report for this bug. 563dac3a9bSDimitry Andric auto R = llvm::make_unique<BugReport>(*BT, BT->getName(), N); 572754fe60SDimitry Andric R->addRange(A->getIdx()->getSourceRange()); 58*b5893f02SDimitry Andric bugreporter::trackExpressionValue(N, A->getIdx(), *R); 593dac3a9bSDimitry Andric C.emitReport(std::move(R)); 602754fe60SDimitry Andric } 613b0f4066SDimitry Andric registerUndefinedArraySubscriptChecker(CheckerManager & mgr)623b0f4066SDimitry Andricvoid ento::registerUndefinedArraySubscriptChecker(CheckerManager &mgr) { 633b0f4066SDimitry Andric mgr.registerChecker<UndefinedArraySubscriptChecker>(); 643b0f4066SDimitry Andric } 65