1d99bd55aSTed Kremenek //===--- UndefinedArraySubscriptChecker.h ----------------------*- C++ -*--===// 2d99bd55aSTed Kremenek // 3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6d99bd55aSTed Kremenek // 7d99bd55aSTed Kremenek //===----------------------------------------------------------------------===// 8d99bd55aSTed Kremenek // 9d99bd55aSTed Kremenek // This defines UndefinedArraySubscriptChecker, a builtin check in ExprEngine 10d99bd55aSTed Kremenek // that performs checks for undefined array subscripts. 11d99bd55aSTed Kremenek // 12d99bd55aSTed Kremenek //===----------------------------------------------------------------------===// 13d99bd55aSTed Kremenek 1476a21502SKristof Umann #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" 152ab0ac53SReid Kleckner #include "clang/AST/DeclCXX.h" 163a02247dSChandler Carruth #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 176a5674ffSArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/Checker.h" 18da6c7568SArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/CheckerManager.h" 19da6c7568SArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 20d99bd55aSTed Kremenek 21d99bd55aSTed Kremenek using namespace clang; 22d99bd55aSTed Kremenek using namespace ento; 23d99bd55aSTed Kremenek 24d99bd55aSTed Kremenek namespace { 25d99bd55aSTed Kremenek class UndefinedArraySubscriptChecker 266a5674ffSArgyrios Kyrtzidis : public Checker< check::PreStmt<ArraySubscriptExpr> > { 27b8984329SAhmed Charles mutable std::unique_ptr<BugType> BT; 28da6c7568SArgyrios Kyrtzidis 29d99bd55aSTed Kremenek public: 30da6c7568SArgyrios Kyrtzidis void checkPreStmt(const ArraySubscriptExpr *A, CheckerContext &C) const; 31d99bd55aSTed Kremenek }; 32d99bd55aSTed Kremenek } // end anonymous namespace 33d99bd55aSTed Kremenek 34d99bd55aSTed Kremenek void 35da6c7568SArgyrios Kyrtzidis UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A, 36da6c7568SArgyrios Kyrtzidis CheckerContext &C) const { 37bc74eb1cSJordan Rose const Expr *Index = A->getIdx(); 38bc74eb1cSJordan Rose if (!C.getSVal(Index).isUndef()) 39bc74eb1cSJordan Rose return; 40bc74eb1cSJordan Rose 41bc74eb1cSJordan Rose // Sema generates anonymous array variables for copying array struct fields. 42bc74eb1cSJordan Rose // Don't warn if we're in an implicitly-generated constructor. 43bc74eb1cSJordan Rose const Decl *D = C.getLocationContext()->getDecl(); 44bc74eb1cSJordan Rose if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) 4554533f73SJordan Rose if (Ctor->isDefaulted()) 46bc74eb1cSJordan Rose return; 47bc74eb1cSJordan Rose 48e39bd407SDevin Coughlin ExplodedNode *N = C.generateErrorNode(); 49bc74eb1cSJordan Rose if (!N) 50bc74eb1cSJordan Rose return; 51d99bd55aSTed Kremenek if (!BT) 524aca9b1cSAlexander Kornienko BT.reset(new BuiltinBug(this, "Array subscript is undefined")); 53d99bd55aSTed Kremenek 54d99bd55aSTed Kremenek // Generate a report for this bug. 558d3a7a56SAaron Ballman auto R = llvm::make_unique<BugReport>(*BT, BT->getName(), N); 56d99bd55aSTed Kremenek R->addRange(A->getIdx()->getSourceRange()); 57b2cf0063SGeorge Karpenkov bugreporter::trackExpressionValue(N, A->getIdx(), *R); 588d3a7a56SAaron Ballman C.emitReport(std::move(R)); 59d99bd55aSTed Kremenek } 60da6c7568SArgyrios Kyrtzidis 61da6c7568SArgyrios Kyrtzidis void ento::registerUndefinedArraySubscriptChecker(CheckerManager &mgr) { 62da6c7568SArgyrios Kyrtzidis mgr.registerChecker<UndefinedArraySubscriptChecker>(); 63da6c7568SArgyrios Kyrtzidis } 64