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