UndefinedArraySubscriptChecker.cpp revision 360784
1//===--- UndefinedArraySubscriptChecker.h ----------------------*- C++ -*--===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This defines UndefinedArraySubscriptChecker, a builtin check in ExprEngine
10// that performs checks for undefined array subscripts.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
15#include "clang/AST/DeclCXX.h"
16#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
17#include "clang/StaticAnalyzer/Core/Checker.h"
18#include "clang/StaticAnalyzer/Core/CheckerManager.h"
19#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
20
21using namespace clang;
22using namespace ento;
23
24namespace {
25class UndefinedArraySubscriptChecker
26  : public Checker< check::PreStmt<ArraySubscriptExpr> > {
27  mutable std::unique_ptr<BugType> BT;
28
29public:
30  void checkPreStmt(const ArraySubscriptExpr *A, CheckerContext &C) const;
31};
32} // end anonymous namespace
33
34void
35UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A,
36                                             CheckerContext &C) const {
37  const Expr *Index = A->getIdx();
38  if (!C.getSVal(Index).isUndef())
39    return;
40
41  // Sema generates anonymous array variables for copying array struct fields.
42  // Don't warn if we're in an implicitly-generated constructor.
43  const Decl *D = C.getLocationContext()->getDecl();
44  if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D))
45    if (Ctor->isDefaulted())
46      return;
47
48  ExplodedNode *N = C.generateErrorNode();
49  if (!N)
50    return;
51  if (!BT)
52    BT.reset(new BuiltinBug(this, "Array subscript is undefined"));
53
54  // Generate a report for this bug.
55  auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
56  R->addRange(A->getIdx()->getSourceRange());
57  bugreporter::trackExpressionValue(N, A->getIdx(), *R);
58  C.emitReport(std::move(R));
59}
60
61void ento::registerUndefinedArraySubscriptChecker(CheckerManager &mgr) {
62  mgr.registerChecker<UndefinedArraySubscriptChecker>();
63}
64
65bool ento::shouldRegisterUndefinedArraySubscriptChecker(const LangOptions &LO) {
66  return true;
67}
68