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