UndefinedAssignmentChecker.cpp revision 226633
1218887Sdim//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==// 2218887Sdim// 3218887Sdim// The LLVM Compiler Infrastructure 4218887Sdim// 5218887Sdim// This file is distributed under the University of Illinois Open Source 6218887Sdim// License. See LICENSE.TXT for details. 7218887Sdim// 8218887Sdim//===----------------------------------------------------------------------===// 9218887Sdim// 10221345Sdim// This defines UndefinedAssignmentChecker, a builtin check in ExprEngine that 11218887Sdim// checks for assigning undefined values. 12218887Sdim// 13218887Sdim//===----------------------------------------------------------------------===// 14218887Sdim 15221345Sdim#include "ClangSACheckers.h" 16221345Sdim#include "clang/StaticAnalyzer/Core/Checker.h" 17221345Sdim#include "clang/StaticAnalyzer/Core/CheckerManager.h" 18221345Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 19218887Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 20218887Sdim 21218887Sdimusing namespace clang; 22218887Sdimusing namespace ento; 23218887Sdim 24218887Sdimnamespace { 25218887Sdimclass UndefinedAssignmentChecker 26221345Sdim : public Checker<check::Bind> { 27221345Sdim mutable llvm::OwningPtr<BugType> BT; 28221345Sdim 29218887Sdimpublic: 30226633Sdim void checkBind(SVal location, SVal val, const Stmt *S, 31226633Sdim CheckerContext &C) const; 32218887Sdim}; 33218887Sdim} 34218887Sdim 35221345Sdimvoid UndefinedAssignmentChecker::checkBind(SVal location, SVal val, 36226633Sdim const Stmt *StoreE, 37221345Sdim CheckerContext &C) const { 38218887Sdim if (!val.isUndef()) 39218887Sdim return; 40218887Sdim 41218887Sdim ExplodedNode *N = C.generateSink(); 42218887Sdim 43218887Sdim if (!N) 44218887Sdim return; 45218887Sdim 46218887Sdim const char *str = "Assigned value is garbage or undefined"; 47218887Sdim 48218887Sdim if (!BT) 49221345Sdim BT.reset(new BuiltinBug(str)); 50218887Sdim 51218887Sdim // Generate a report for this bug. 52218887Sdim const Expr *ex = 0; 53218887Sdim 54218887Sdim while (StoreE) { 55218887Sdim if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) { 56218887Sdim if (B->isCompoundAssignmentOp()) { 57226633Sdim const ProgramState *state = C.getState(); 58218887Sdim if (state->getSVal(B->getLHS()).isUndef()) { 59218887Sdim str = "The left expression of the compound assignment is an " 60218887Sdim "uninitialized value. The computed value will also be garbage"; 61218887Sdim ex = B->getLHS(); 62218887Sdim break; 63218887Sdim } 64218887Sdim } 65218887Sdim 66218887Sdim ex = B->getRHS(); 67218887Sdim break; 68218887Sdim } 69218887Sdim 70218887Sdim if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) { 71226633Sdim const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl()); 72218887Sdim ex = VD->getInit(); 73218887Sdim } 74218887Sdim 75218887Sdim break; 76218887Sdim } 77218887Sdim 78226633Sdim BugReport *R = new BugReport(*BT, str, N); 79218887Sdim if (ex) { 80218887Sdim R->addRange(ex->getSourceRange()); 81226633Sdim R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, ex)); 82218887Sdim } 83218887Sdim C.EmitReport(R); 84218887Sdim} 85218887Sdim 86221345Sdimvoid ento::registerUndefinedAssignmentChecker(CheckerManager &mgr) { 87221345Sdim mgr.registerChecker<UndefinedAssignmentChecker>(); 88221345Sdim} 89