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> > { 28e2778999SDylan Noblesmith mutable OwningPtr<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)) 46*54533f73SJordan Rose if (Ctor->isDefaulted()) 47bc74eb1cSJordan Rose return; 48bc74eb1cSJordan Rose 49bc74eb1cSJordan Rose ExplodedNode *N = C.generateSink(); 50bc74eb1cSJordan Rose if (!N) 51bc74eb1cSJordan Rose return; 52d99bd55aSTed Kremenek if (!BT) 53da6c7568SArgyrios Kyrtzidis BT.reset(new BuiltinBug("Array subscript is undefined")); 54d99bd55aSTed Kremenek 55d99bd55aSTed Kremenek // Generate a report for this bug. 563a6bdf8fSAnna Zaks BugReport *R = new BugReport(*BT, BT->getName(), N); 57d99bd55aSTed Kremenek R->addRange(A->getIdx()->getSourceRange()); 58a0f7d35aSJordan Rose bugreporter::trackNullOrUndefValue(N, A->getIdx(), *R); 59e10d5a76SJordan Rose C.emitReport(R); 60d99bd55aSTed Kremenek } 61da6c7568SArgyrios Kyrtzidis 62da6c7568SArgyrios Kyrtzidis void ento::registerUndefinedArraySubscriptChecker(CheckerManager &mgr) { 63da6c7568SArgyrios Kyrtzidis mgr.registerChecker<UndefinedArraySubscriptChecker>(); 64da6c7568SArgyrios Kyrtzidis } 65