1218887Sdim//===--- UndefinedArraySubscriptChecker.h ----------------------*- C++ -*--===// 2218887Sdim// 3218887Sdim// The LLVM Compiler Infrastructure 4218887Sdim// 5218887Sdim// This file is distributed under the University of Illinois Open Source 6218887Sdim// License. See LICENSE.TXT for details. 7218887Sdim// 8218887Sdim//===----------------------------------------------------------------------===// 9218887Sdim// 10218887Sdim// This defines UndefinedArraySubscriptChecker, a builtin check in ExprEngine 11218887Sdim// that performs checks for undefined array subscripts. 12218887Sdim// 13218887Sdim//===----------------------------------------------------------------------===// 14218887Sdim 15221345Sdim#include "ClangSACheckers.h" 16263509Sdim#include "clang/AST/DeclCXX.h" 17252723Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 18221345Sdim#include "clang/StaticAnalyzer/Core/Checker.h" 19221345Sdim#include "clang/StaticAnalyzer/Core/CheckerManager.h" 20221345Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 21218887Sdim 22218887Sdimusing namespace clang; 23218887Sdimusing namespace ento; 24218887Sdim 25218887Sdimnamespace { 26218887Sdimclass UndefinedArraySubscriptChecker 27221345Sdim : public Checker< check::PreStmt<ArraySubscriptExpr> > { 28235633Sdim mutable OwningPtr<BugType> BT; 29221345Sdim 30218887Sdimpublic: 31221345Sdim void checkPreStmt(const ArraySubscriptExpr *A, CheckerContext &C) const; 32218887Sdim}; 33218887Sdim} // end anonymous namespace 34218887Sdim 35218887Sdimvoid 36221345SdimUndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A, 37221345Sdim CheckerContext &C) const { 38252723Sdim const Expr *Index = A->getIdx(); 39252723Sdim if (!C.getSVal(Index).isUndef()) 40252723Sdim return; 41218887Sdim 42252723Sdim // Sema generates anonymous array variables for copying array struct fields. 43252723Sdim // Don't warn if we're in an implicitly-generated constructor. 44252723Sdim const Decl *D = C.getLocationContext()->getDecl(); 45252723Sdim if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) 46263509Sdim if (Ctor->isDefaulted()) 47252723Sdim return; 48252723Sdim 49252723Sdim ExplodedNode *N = C.generateSink(); 50252723Sdim if (!N) 51252723Sdim return; 52252723Sdim if (!BT) 53252723Sdim BT.reset(new BuiltinBug("Array subscript is undefined")); 54252723Sdim 55252723Sdim // Generate a report for this bug. 56252723Sdim BugReport *R = new BugReport(*BT, BT->getName(), N); 57252723Sdim R->addRange(A->getIdx()->getSourceRange()); 58252723Sdim bugreporter::trackNullOrUndefValue(N, A->getIdx(), *R); 59252723Sdim C.emitReport(R); 60218887Sdim} 61221345Sdim 62221345Sdimvoid ento::registerUndefinedArraySubscriptChecker(CheckerManager &mgr) { 63221345Sdim mgr.registerChecker<UndefinedArraySubscriptChecker>(); 64221345Sdim} 65