xref: /freebsd/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp (revision 59c8e88e72633afbc47a4ace0d2170d00d51f7dc)
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 
21 using namespace clang;
22 using namespace ento;
23 
24 namespace {
25 class UndefinedArraySubscriptChecker
26   : public Checker< check::PreStmt<ArraySubscriptExpr> > {
27   mutable std::unique_ptr<BugType> BT;
28 
29 public:
30   void checkPreStmt(const ArraySubscriptExpr *A, CheckerContext &C) const;
31 };
32 } // end anonymous namespace
33 
34 void
35 UndefinedArraySubscriptChecker::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 
61 void ento::registerUndefinedArraySubscriptChecker(CheckerManager &mgr) {
62   mgr.registerChecker<UndefinedArraySubscriptChecker>();
63 }
64 
65 bool ento::shouldRegisterUndefinedArraySubscriptChecker(const CheckerManager &mgr) {
66   return true;
67 }
68