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