UndefinedAssignmentChecker.cpp revision 243830
1169695Skan//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==//
2169695Skan//
3169695Skan//                     The LLVM Compiler Infrastructure
4169695Skan//
5169695Skan// This file is distributed under the University of Illinois Open Source
6169695Skan// License. See LICENSE.TXT for details.
7169695Skan//
8169695Skan//===----------------------------------------------------------------------===//
9169695Skan//
10169695Skan// This defines UndefinedAssignmentChecker, a builtin check in ExprEngine that
11169695Skan// checks for assigning undefined values.
12169695Skan//
13169695Skan//===----------------------------------------------------------------------===//
14169695Skan
15169695Skan#include "ClangSACheckers.h"
16169695Skan#include "clang/StaticAnalyzer/Core/Checker.h"
17169695Skan#include "clang/StaticAnalyzer/Core/CheckerManager.h"
18169695Skan#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
19169695Skan#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
20169695Skan
21169695Skanusing namespace clang;
22169695Skanusing namespace ento;
23169695Skan
24169695Skannamespace {
25169695Skanclass UndefinedAssignmentChecker
26169695Skan  : public Checker<check::Bind> {
27169695Skan  mutable OwningPtr<BugType> BT;
28169695Skan
29169695Skanpublic:
30169695Skan  void checkBind(SVal location, SVal val, const Stmt *S,
31169695Skan                 CheckerContext &C) const;
32169695Skan};
33169695Skan}
34169695Skan
35169695Skanvoid UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
36169695Skan                                           const Stmt *StoreE,
37169695Skan                                           CheckerContext &C) const {
38169695Skan  if (!val.isUndef())
39169695Skan    return;
40169695Skan
41169695Skan  ExplodedNode *N = C.generateSink();
42169695Skan
43169695Skan  if (!N)
44169695Skan    return;
45169695Skan
46169695Skan  const char *str = "Assigned value is garbage or undefined";
47169695Skan
48169695Skan  if (!BT)
49169695Skan    BT.reset(new BuiltinBug(str));
50169695Skan
51169695Skan  // Generate a report for this bug.
52169695Skan  const Expr *ex = 0;
53169695Skan
54169695Skan  while (StoreE) {
55169695Skan    if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
56169695Skan      if (B->isCompoundAssignmentOp()) {
57169695Skan        ProgramStateRef state = C.getState();
58169695Skan        if (state->getSVal(B->getLHS(), C.getLocationContext()).isUndef()) {
59169695Skan          str = "The left expression of the compound assignment is an "
60169695Skan                "uninitialized value. The computed value will also be garbage";
61169695Skan          ex = B->getLHS();
62169695Skan          break;
63169695Skan        }
64169695Skan      }
65169695Skan
66169695Skan      ex = B->getRHS();
67169695Skan      break;
68169695Skan    }
69169695Skan
70169695Skan    if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) {
71169695Skan      const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
72169695Skan      ex = VD->getInit();
73169695Skan    }
74169695Skan
75169695Skan    break;
76169695Skan  }
77169695Skan
78169695Skan  BugReport *R = new BugReport(*BT, str, N);
79169695Skan  if (ex) {
80169695Skan    R->addRange(ex->getSourceRange());
81169695Skan    bugreporter::trackNullOrUndefValue(N, ex, *R);
82169695Skan  }
83169695Skan  C.emitReport(R);
84169695Skan}
85169695Skan
86169695Skanvoid ento::registerUndefinedAssignmentChecker(CheckerManager &mgr) {
87169695Skan  mgr.registerChecker<UndefinedAssignmentChecker>();
88169695Skan}
89169695Skan