xref: /minix3/external/bsd/llvm/dist/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===--- UndefinedArraySubscriptChecker.h ----------------------*- C++ -*--===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This defines UndefinedArraySubscriptChecker, a builtin check in ExprEngine
11f4a2713aSLionel Sambuc // that performs checks for undefined array subscripts.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc 
15f4a2713aSLionel Sambuc #include "ClangSACheckers.h"
16f4a2713aSLionel Sambuc #include "clang/AST/DeclCXX.h"
17f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
18f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/Checker.h"
19f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/CheckerManager.h"
20f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
21f4a2713aSLionel Sambuc 
22f4a2713aSLionel Sambuc using namespace clang;
23f4a2713aSLionel Sambuc using namespace ento;
24f4a2713aSLionel Sambuc 
25f4a2713aSLionel Sambuc namespace {
26f4a2713aSLionel Sambuc class UndefinedArraySubscriptChecker
27f4a2713aSLionel Sambuc   : public Checker< check::PreStmt<ArraySubscriptExpr> > {
28*0a6a1f1dSLionel Sambuc   mutable std::unique_ptr<BugType> BT;
29f4a2713aSLionel Sambuc 
30f4a2713aSLionel Sambuc public:
31f4a2713aSLionel Sambuc   void checkPreStmt(const ArraySubscriptExpr *A, CheckerContext &C) const;
32f4a2713aSLionel Sambuc };
33f4a2713aSLionel Sambuc } // end anonymous namespace
34f4a2713aSLionel Sambuc 
35f4a2713aSLionel Sambuc void
checkPreStmt(const ArraySubscriptExpr * A,CheckerContext & C) const36f4a2713aSLionel Sambuc UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A,
37f4a2713aSLionel Sambuc                                              CheckerContext &C) const {
38f4a2713aSLionel Sambuc   const Expr *Index = A->getIdx();
39f4a2713aSLionel Sambuc   if (!C.getSVal(Index).isUndef())
40f4a2713aSLionel Sambuc     return;
41f4a2713aSLionel Sambuc 
42f4a2713aSLionel Sambuc   // Sema generates anonymous array variables for copying array struct fields.
43f4a2713aSLionel Sambuc   // Don't warn if we're in an implicitly-generated constructor.
44f4a2713aSLionel Sambuc   const Decl *D = C.getLocationContext()->getDecl();
45f4a2713aSLionel Sambuc   if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D))
46f4a2713aSLionel Sambuc     if (Ctor->isDefaulted())
47f4a2713aSLionel Sambuc       return;
48f4a2713aSLionel Sambuc 
49f4a2713aSLionel Sambuc   ExplodedNode *N = C.generateSink();
50f4a2713aSLionel Sambuc   if (!N)
51f4a2713aSLionel Sambuc     return;
52f4a2713aSLionel Sambuc   if (!BT)
53*0a6a1f1dSLionel Sambuc     BT.reset(new BuiltinBug(this, "Array subscript is undefined"));
54f4a2713aSLionel Sambuc 
55f4a2713aSLionel Sambuc   // Generate a report for this bug.
56f4a2713aSLionel Sambuc   BugReport *R = new BugReport(*BT, BT->getName(), N);
57f4a2713aSLionel Sambuc   R->addRange(A->getIdx()->getSourceRange());
58f4a2713aSLionel Sambuc   bugreporter::trackNullOrUndefValue(N, A->getIdx(), *R);
59f4a2713aSLionel Sambuc   C.emitReport(R);
60f4a2713aSLionel Sambuc }
61f4a2713aSLionel Sambuc 
registerUndefinedArraySubscriptChecker(CheckerManager & mgr)62f4a2713aSLionel Sambuc void ento::registerUndefinedArraySubscriptChecker(CheckerManager &mgr) {
63f4a2713aSLionel Sambuc   mgr.registerChecker<UndefinedArraySubscriptChecker>();
64f4a2713aSLionel Sambuc }
65