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