1d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu//===--- UndefinedArraySubscriptChecker.h ----------------------*- C++ -*--===//
2d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu//
3d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu//                     The LLVM Compiler Infrastructure
4d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu//
5d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu// This file is distributed under the University of Illinois Open Source
6d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu// License. See LICENSE.TXT for details.
7d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu//
8d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu//===----------------------------------------------------------------------===//
9d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu//
10d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis// This defines UndefinedArraySubscriptChecker, a builtin check in ExprEngine
11d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu// that performs checks for undefined array subscripts.
12d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu//
13d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu//===----------------------------------------------------------------------===//
14d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu
15eb290caacc49587e4d3c992ba742d1916cab5350Argyrios Kyrtzidis#include "ClangSACheckers.h"
16cff15128c6c089bd6fae841b80680e6f5afbf0bfReid Kleckner#include "clang/AST/DeclCXX.h"
1755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
18ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h"
19eb290caacc49587e4d3c992ba742d1916cab5350Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
20eb290caacc49587e4d3c992ba742d1916cab5350Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
21d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu
22d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xuusing namespace clang;
239ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
24d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu
25d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xunamespace {
26ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass UndefinedArraySubscriptChecker
27ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis  : public Checker< check::PreStmt<ArraySubscriptExpr> > {
28651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  mutable std::unique_ptr<BugType> BT;
29eb290caacc49587e4d3c992ba742d1916cab5350Argyrios Kyrtzidis
30d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xupublic:
31eb290caacc49587e4d3c992ba742d1916cab5350Argyrios Kyrtzidis  void checkPreStmt(const ArraySubscriptExpr *A, CheckerContext &C) const;
32d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu};
33d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu} // end anonymous namespace
34d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu
35a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainarvoid
36eb290caacc49587e4d3c992ba742d1916cab5350Argyrios KyrtzidisUndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A,
37eb290caacc49587e4d3c992ba742d1916cab5350Argyrios Kyrtzidis                                             CheckerContext &C) const {
38ecee1651c100342366a9417c85c6e50399039930Jordan Rose  const Expr *Index = A->getIdx();
39ecee1651c100342366a9417c85c6e50399039930Jordan Rose  if (!C.getSVal(Index).isUndef())
40ecee1651c100342366a9417c85c6e50399039930Jordan Rose    return;
41ecee1651c100342366a9417c85c6e50399039930Jordan Rose
42ecee1651c100342366a9417c85c6e50399039930Jordan Rose  // Sema generates anonymous array variables for copying array struct fields.
43ecee1651c100342366a9417c85c6e50399039930Jordan Rose  // Don't warn if we're in an implicitly-generated constructor.
44ecee1651c100342366a9417c85c6e50399039930Jordan Rose  const Decl *D = C.getLocationContext()->getDecl();
45ecee1651c100342366a9417c85c6e50399039930Jordan Rose  if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D))
46a7b879723d3989d85b9492fd8218e7d745367fe3Jordan Rose    if (Ctor->isDefaulted())
47ecee1651c100342366a9417c85c6e50399039930Jordan Rose      return;
48ecee1651c100342366a9417c85c6e50399039930Jordan Rose
49a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ExplodedNode *N = C.generateErrorNode();
50ecee1651c100342366a9417c85c6e50399039930Jordan Rose  if (!N)
51ecee1651c100342366a9417c85c6e50399039930Jordan Rose    return;
52ecee1651c100342366a9417c85c6e50399039930Jordan Rose  if (!BT)
53651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    BT.reset(new BuiltinBug(this, "Array subscript is undefined"));
54ecee1651c100342366a9417c85c6e50399039930Jordan Rose
55ecee1651c100342366a9417c85c6e50399039930Jordan Rose  // Generate a report for this bug.
56a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  auto R = llvm::make_unique<BugReport>(*BT, BT->getName(), N);
57ecee1651c100342366a9417c85c6e50399039930Jordan Rose  R->addRange(A->getIdx()->getSourceRange());
58ecee1651c100342366a9417c85c6e50399039930Jordan Rose  bugreporter::trackNullOrUndefValue(N, A->getIdx(), *R);
59a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  C.emitReport(std::move(R));
60d694485f9d6e3ea7b458df8241dfffd38f62aca8Zhongxing Xu}
61eb290caacc49587e4d3c992ba742d1916cab5350Argyrios Kyrtzidis
62eb290caacc49587e4d3c992ba742d1916cab5350Argyrios Kyrtzidisvoid ento::registerUndefinedArraySubscriptChecker(CheckerManager &mgr) {
63eb290caacc49587e4d3c992ba742d1916cab5350Argyrios Kyrtzidis  mgr.registerChecker<UndefinedArraySubscriptChecker>();
64eb290caacc49587e4d3c992ba742d1916cab5350Argyrios Kyrtzidis}
65