1d99bd55aSTed Kremenek //===--- UndefinedArraySubscriptChecker.h ----------------------*- C++ -*--===// 2d99bd55aSTed Kremenek // 3d99bd55aSTed Kremenek // The LLVM Compiler Infrastructure 4d99bd55aSTed Kremenek // 5d99bd55aSTed Kremenek // This file is distributed under the University of Illinois Open Source 6d99bd55aSTed Kremenek // License. See LICENSE.TXT for details. 7d99bd55aSTed Kremenek // 8d99bd55aSTed Kremenek //===----------------------------------------------------------------------===// 9d99bd55aSTed Kremenek // 10d99bd55aSTed Kremenek // This defines UndefinedArraySubscriptChecker, a builtin check in ExprEngine 11d99bd55aSTed Kremenek // that performs checks for undefined array subscripts. 12d99bd55aSTed Kremenek // 13d99bd55aSTed Kremenek //===----------------------------------------------------------------------===// 14d99bd55aSTed Kremenek 15da6c7568SArgyrios Kyrtzidis #include "ClangSACheckers.h" 162ab0ac53SReid Kleckner #include "clang/AST/DeclCXX.h" 173a02247dSChandler Carruth #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 186a5674ffSArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/Checker.h" 19da6c7568SArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/CheckerManager.h" 20da6c7568SArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 21d99bd55aSTed Kremenek 22d99bd55aSTed Kremenek using namespace clang; 23d99bd55aSTed Kremenek using namespace ento; 24d99bd55aSTed Kremenek 25d99bd55aSTed Kremenek namespace { 26d99bd55aSTed Kremenek class UndefinedArraySubscriptChecker 276a5674ffSArgyrios Kyrtzidis : public Checker< check::PreStmt<ArraySubscriptExpr> > { 28b8984329SAhmed Charles mutable std::unique_ptr<BugType> BT; 29da6c7568SArgyrios Kyrtzidis 30d99bd55aSTed Kremenek public: 31da6c7568SArgyrios Kyrtzidis void checkPreStmt(const ArraySubscriptExpr *A, CheckerContext &C) const; 32d99bd55aSTed Kremenek }; 33d99bd55aSTed Kremenek } // end anonymous namespace 34d99bd55aSTed Kremenek 35d99bd55aSTed Kremenek void 36da6c7568SArgyrios Kyrtzidis UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A, 37da6c7568SArgyrios Kyrtzidis CheckerContext &C) const { 38bc74eb1cSJordan Rose const Expr *Index = A->getIdx(); 39bc74eb1cSJordan Rose if (!C.getSVal(Index).isUndef()) 40bc74eb1cSJordan Rose return; 41bc74eb1cSJordan Rose 42bc74eb1cSJordan Rose // Sema generates anonymous array variables for copying array struct fields. 43bc74eb1cSJordan Rose // Don't warn if we're in an implicitly-generated constructor. 44bc74eb1cSJordan Rose const Decl *D = C.getLocationContext()->getDecl(); 45bc74eb1cSJordan Rose if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) 4654533f73SJordan Rose if (Ctor->isDefaulted()) 47bc74eb1cSJordan Rose return; 48bc74eb1cSJordan Rose 49e39bd407SDevin Coughlin ExplodedNode *N = C.generateErrorNode(); 50bc74eb1cSJordan Rose if (!N) 51bc74eb1cSJordan Rose return; 52d99bd55aSTed Kremenek if (!BT) 534aca9b1cSAlexander Kornienko BT.reset(new BuiltinBug(this, "Array subscript is undefined")); 54d99bd55aSTed Kremenek 55d99bd55aSTed Kremenek // Generate a report for this bug. 568d3a7a56SAaron Ballman auto R = llvm::make_unique<BugReport>(*BT, BT->getName(), N); 57d99bd55aSTed Kremenek R->addRange(A->getIdx()->getSourceRange()); 58*b2cf0063SGeorge Karpenkov bugreporter::trackExpressionValue(N, A->getIdx(), *R); 598d3a7a56SAaron Ballman C.emitReport(std::move(R)); 60d99bd55aSTed Kremenek } 61da6c7568SArgyrios Kyrtzidis 62da6c7568SArgyrios Kyrtzidis void ento::registerUndefinedArraySubscriptChecker(CheckerManager &mgr) { 63da6c7568SArgyrios Kyrtzidis mgr.registerChecker<UndefinedArraySubscriptChecker>(); 64da6c7568SArgyrios Kyrtzidis } 65