UndefinedAssignmentChecker.cpp revision 218887
142629Sobrien//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==// 238494Sobrien// 338494Sobrien// The LLVM Compiler Infrastructure 438494Sobrien// 542629Sobrien// This file is distributed under the University of Illinois Open Source 638494Sobrien// License. See LICENSE.TXT for details. 742629Sobrien// 838494Sobrien//===----------------------------------------------------------------------===// 938494Sobrien// 1038494Sobrien// This defines UndefinedAssginmentChecker, a builtin check in ExprEngine that 1138494Sobrien// checks for assigning undefined values. 1238494Sobrien// 1338494Sobrien//===----------------------------------------------------------------------===// 1438494Sobrien 1538494Sobrien#include "InternalChecks.h" 1638494Sobrien#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 1738494Sobrien#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" 1838494Sobrien 1938494Sobrienusing namespace clang; 2038494Sobrienusing namespace ento; 2138494Sobrien 2238494Sobriennamespace { 2338494Sobrienclass UndefinedAssignmentChecker 2438494Sobrien : public CheckerVisitor<UndefinedAssignmentChecker> { 2538494Sobrien BugType *BT; 2638494Sobrienpublic: 2738494Sobrien UndefinedAssignmentChecker() : BT(0) {} 2838494Sobrien static void *getTag(); 2938494Sobrien virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE, 3038494Sobrien SVal location, SVal val); 3138494Sobrien}; 3238494Sobrien} 3338494Sobrien 3438494Sobrienvoid ento::RegisterUndefinedAssignmentChecker(ExprEngine &Eng){ 3538494Sobrien Eng.registerCheck(new UndefinedAssignmentChecker()); 3638494Sobrien} 3738494Sobrien 3838494Sobrienvoid *UndefinedAssignmentChecker::getTag() { 3938494Sobrien static int x = 0; 4038494Sobrien return &x; 4138494Sobrien} 4238494Sobrien 4338494Sobrienvoid UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C, 4438494Sobrien const Stmt *StoreE, 4538494Sobrien SVal location, 4638494Sobrien SVal val) { 4738494Sobrien if (!val.isUndef()) 4838494Sobrien return; 4938494Sobrien 5038494Sobrien ExplodedNode *N = C.generateSink(); 5138494Sobrien 5238494Sobrien if (!N) 5338494Sobrien return; 5438494Sobrien 5538494Sobrien const char *str = "Assigned value is garbage or undefined"; 5638494Sobrien 5738494Sobrien if (!BT) 5838494Sobrien BT = new BuiltinBug(str); 5938494Sobrien 6038494Sobrien // Generate a report for this bug. 6138494Sobrien const Expr *ex = 0; 62119679Smbr 6338494Sobrien while (StoreE) { 6438494Sobrien if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) { 6538494Sobrien if (B->isCompoundAssignmentOp()) { 6638494Sobrien const GRState *state = C.getState(); 6738494Sobrien if (state->getSVal(B->getLHS()).isUndef()) { 6838494Sobrien str = "The left expression of the compound assignment is an " 6938494Sobrien "uninitialized value. The computed value will also be garbage"; 7038494Sobrien ex = B->getLHS(); 7138494Sobrien break; 7238494Sobrien } 7338494Sobrien } 7438494Sobrien 75119679Smbr ex = B->getRHS(); 7682794Sobrien break; 7782794Sobrien } 7838494Sobrien 7982794Sobrien if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) { 8038494Sobrien const VarDecl* VD = dyn_cast<VarDecl>(DS->getSingleDecl()); 8138494Sobrien ex = VD->getInit(); 8238494Sobrien } 8382794Sobrien 84119679Smbr break; 8582794Sobrien } 86119679Smbr 87119679Smbr EnhancedBugReport *R = new EnhancedBugReport(*BT, str, N); 8838494Sobrien if (ex) { 8938494Sobrien R->addRange(ex->getSourceRange()); 9038494Sobrien R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, ex); 9138494Sobrien } 9238494Sobrien C.EmitReport(R); 9338494Sobrien} 9438494Sobrien 9538494Sobrien