UndefinedAssignmentChecker.cpp revision 239462
1275072Semaste//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==// 2275072Semaste// 3275072Semaste// The LLVM Compiler Infrastructure 4275072Semaste// 5275072Semaste// This file is distributed under the University of Illinois Open Source 6275072Semaste// License. See LICENSE.TXT for details. 7275072Semaste// 8275072Semaste//===----------------------------------------------------------------------===// 9275072Semaste// 10275072Semaste// This defines UndefinedAssignmentChecker, a builtin check in ExprEngine that 11275072Semaste// checks for assigning undefined values. 12275072Semaste// 13275072Semaste//===----------------------------------------------------------------------===// 14296417Sdim 15296417Sdim#include "ClangSACheckers.h" 16275072Semaste#include "clang/StaticAnalyzer/Core/Checker.h" 17275072Semaste#include "clang/StaticAnalyzer/Core/CheckerManager.h" 18280031Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 19280031Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 20280031Sdim 21280031Sdimusing namespace clang; 22280031Sdimusing namespace ento; 23275072Semaste 24296417Sdimnamespace { 25280031Sdimclass UndefinedAssignmentChecker 26280031Sdim : public Checker<check::Bind> { 27280031Sdim mutable OwningPtr<BugType> BT; 28296417Sdim 29296417Sdimpublic: 30296417Sdim void checkBind(SVal location, SVal val, const Stmt *S, 31296417Sdim CheckerContext &C) const; 32296417Sdim}; 33296417Sdim} 34296417Sdim 35275072Semastevoid UndefinedAssignmentChecker::checkBind(SVal location, SVal val, 36275072Semaste const Stmt *StoreE, 37275072Semaste CheckerContext &C) const { 38275072Semaste if (!val.isUndef()) 39280031Sdim return; 40280031Sdim 41280031Sdim ExplodedNode *N = C.generateSink(); 42280031Sdim 43280031Sdim if (!N) 44275072Semaste return; 45296417Sdim 46275072Semaste const char *str = "Assigned value is garbage or undefined"; 47275072Semaste 48275072Semaste if (!BT) 49275072Semaste BT.reset(new BuiltinBug(str)); 50280031Sdim 51280031Sdim // Generate a report for this bug. 52280031Sdim const Expr *ex = 0; 53280031Sdim 54280031Sdim while (StoreE) { 55275072Semaste if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) { 56280031Sdim if (B->isCompoundAssignmentOp()) { 57296417Sdim ProgramStateRef state = C.getState(); 58275072Semaste if (state->getSVal(B->getLHS(), C.getLocationContext()).isUndef()) { 59280031Sdim str = "The left expression of the compound assignment is an " 60275072Semaste "uninitialized value. The computed value will also be garbage"; 61280031Sdim ex = B->getLHS(); 62275072Semaste break; 63280031Sdim } 64280031Sdim } 65280031Sdim 66280031Sdim ex = B->getRHS(); 67280031Sdim break; 68280031Sdim } 69275072Semaste 70280031Sdim if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) { 71296417Sdim const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl()); 72275072Semaste ex = VD->getInit(); 73280031Sdim } 74275072Semaste 75275072Semaste break; 76275072Semaste } 77280031Sdim 78280031Sdim BugReport *R = new BugReport(*BT, str, N); 79280031Sdim if (ex) { 80280031Sdim R->addRange(ex->getSourceRange()); 81288943Sdim bugreporter::addTrackNullOrUndefValueVisitor(N, ex, R); 82280031Sdim } 83275072Semaste R->disablePathPruning(); 84280031Sdim C.EmitReport(R); 85296417Sdim} 86280031Sdim 87280031Sdimvoid ento::registerUndefinedAssignmentChecker(CheckerManager &mgr) { 88275072Semaste mgr.registerChecker<UndefinedAssignmentChecker>(); 89275072Semaste} 90275072Semaste