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"
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> > {
27e2778999SDylan Noblesmith   mutable OwningPtr<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 {
37*bc74eb1cSJordan Rose   const Expr *Index = A->getIdx();
38*bc74eb1cSJordan Rose   if (!C.getSVal(Index).isUndef())
39*bc74eb1cSJordan Rose     return;
40*bc74eb1cSJordan Rose 
41*bc74eb1cSJordan Rose   // Sema generates anonymous array variables for copying array struct fields.
42*bc74eb1cSJordan Rose   // Don't warn if we're in an implicitly-generated constructor.
43*bc74eb1cSJordan Rose   const Decl *D = C.getLocationContext()->getDecl();
44*bc74eb1cSJordan Rose   if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D))
45*bc74eb1cSJordan Rose     if (Ctor->isImplicitlyDefined())
46*bc74eb1cSJordan Rose       return;
47*bc74eb1cSJordan Rose 
48*bc74eb1cSJordan Rose   ExplodedNode *N = C.generateSink();
49*bc74eb1cSJordan Rose   if (!N)
50*bc74eb1cSJordan Rose     return;
51d99bd55aSTed Kremenek   if (!BT)
52da6c7568SArgyrios Kyrtzidis     BT.reset(new BuiltinBug("Array subscript is undefined"));
53d99bd55aSTed Kremenek 
54d99bd55aSTed Kremenek   // Generate a report for this bug.
553a6bdf8fSAnna Zaks   BugReport *R = new BugReport(*BT, BT->getName(), N);
56d99bd55aSTed Kremenek   R->addRange(A->getIdx()->getSourceRange());
57a0f7d35aSJordan Rose   bugreporter::trackNullOrUndefValue(N, A->getIdx(), *R);
58e10d5a76SJordan Rose   C.emitReport(R);
59d99bd55aSTed Kremenek }
60da6c7568SArgyrios Kyrtzidis 
61da6c7568SArgyrios Kyrtzidis void ento::registerUndefinedArraySubscriptChecker(CheckerManager &mgr) {
62da6c7568SArgyrios Kyrtzidis   mgr.registerChecker<UndefinedArraySubscriptChecker>();
63da6c7568SArgyrios Kyrtzidis }
64