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 SambucUndefinedArraySubscriptChecker::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 Sambucvoid ento::registerUndefinedArraySubscriptChecker(CheckerManager &mgr) { 63f4a2713aSLionel Sambuc mgr.registerChecker<UndefinedArraySubscriptChecker>(); 64f4a2713aSLionel Sambuc } 65