xref: /src/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp (revision 647cbc5de815c5651677bf8582797f716ec7b48d) !
1b3d5a323SRoman Divacky //===--- UndefinedArraySubscriptChecker.h ----------------------*- C++ -*--===//
2b3d5a323SRoman Divacky //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b3d5a323SRoman Divacky //
7b3d5a323SRoman Divacky //===----------------------------------------------------------------------===//
8b3d5a323SRoman Divacky //
9bca07a45SDimitry Andric // This defines UndefinedArraySubscriptChecker, a builtin check in ExprEngine
10b3d5a323SRoman Divacky // that performs checks for undefined array subscripts.
11b3d5a323SRoman Divacky //
12b3d5a323SRoman Divacky //===----------------------------------------------------------------------===//
13b3d5a323SRoman Divacky 
14676fbe81SDimitry Andric #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
15bfef3995SDimitry Andric #include "clang/AST/DeclCXX.h"
16809500fcSDimitry Andric #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
1701af97d3SDimitry Andric #include "clang/StaticAnalyzer/Core/Checker.h"
1801af97d3SDimitry Andric #include "clang/StaticAnalyzer/Core/CheckerManager.h"
1901af97d3SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
20b3d5a323SRoman Divacky 
21b3d5a323SRoman Divacky using namespace clang;
22bca07a45SDimitry Andric using namespace ento;
23b3d5a323SRoman Divacky 
24b3d5a323SRoman Divacky namespace {
251569ce68SRoman Divacky class UndefinedArraySubscriptChecker
2601af97d3SDimitry Andric   : public Checker< check::PreStmt<ArraySubscriptExpr> > {
2777dbea07SDimitry Andric   const BugType BT{this, "Array subscript is undefined"};
2801af97d3SDimitry Andric 
29b3d5a323SRoman Divacky public:
3001af97d3SDimitry Andric   void checkPreStmt(const ArraySubscriptExpr *A, CheckerContext &C) const;
31b3d5a323SRoman Divacky };
32b3d5a323SRoman Divacky } // end anonymous namespace
33b3d5a323SRoman Divacky 
34b3d5a323SRoman Divacky void
checkPreStmt(const ArraySubscriptExpr * A,CheckerContext & C) const3501af97d3SDimitry Andric UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A,
3601af97d3SDimitry Andric                                              CheckerContext &C) const {
37809500fcSDimitry Andric   const Expr *Index = A->getIdx();
38809500fcSDimitry Andric   if (!C.getSVal(Index).isUndef())
39809500fcSDimitry Andric     return;
40809500fcSDimitry Andric 
41809500fcSDimitry Andric   // Sema generates anonymous array variables for copying array struct fields.
42809500fcSDimitry Andric   // Don't warn if we're in an implicitly-generated constructor.
43809500fcSDimitry Andric   const Decl *D = C.getLocationContext()->getDecl();
44809500fcSDimitry Andric   if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D))
45bfef3995SDimitry Andric     if (Ctor->isDefaulted())
46809500fcSDimitry Andric       return;
47809500fcSDimitry Andric 
4845b53394SDimitry Andric   ExplodedNode *N = C.generateErrorNode();
49809500fcSDimitry Andric   if (!N)
50809500fcSDimitry Andric     return;
51b3d5a323SRoman Divacky   // Generate a report for this bug.
5277dbea07SDimitry Andric   auto R = std::make_unique<PathSensitiveBugReport>(BT, BT.getDescription(), N);
53b3d5a323SRoman Divacky   R->addRange(A->getIdx()->getSourceRange());
54676fbe81SDimitry Andric   bugreporter::trackExpressionValue(N, A->getIdx(), *R);
55c192b3dcSDimitry Andric   C.emitReport(std::move(R));
56b3d5a323SRoman Divacky }
5701af97d3SDimitry Andric 
registerUndefinedArraySubscriptChecker(CheckerManager & mgr)5801af97d3SDimitry Andric void ento::registerUndefinedArraySubscriptChecker(CheckerManager &mgr) {
5901af97d3SDimitry Andric   mgr.registerChecker<UndefinedArraySubscriptChecker>();
6001af97d3SDimitry Andric }
6122989816SDimitry Andric 
shouldRegisterUndefinedArraySubscriptChecker(const CheckerManager & mgr)62cfca06d7SDimitry Andric bool ento::shouldRegisterUndefinedArraySubscriptChecker(const CheckerManager &mgr) {
6322989816SDimitry Andric   return true;
6422989816SDimitry Andric }
65