BugReporterVisitors.cpp revision 3b9e8e40dab1295de4f14d9cf8d24c22422a42d2
1f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// BugReporterVisitors.cpp - Helpers for reporting bugs -----------*- C++ -*--//
2f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//
3f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//                     The LLVM Compiler Infrastructure
4f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//
5f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source
6f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// License. See LICENSE.TXT for details.
7f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//
8f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//===----------------------------------------------------------------------===//
9f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//
10f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//  This file defines a set of BugReporter "visitors" which can be used to
11f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//  enhance the diagnostics reported for a bug.
12f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//
13f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//===----------------------------------------------------------------------===//
14f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
15f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "clang/AST/Expr.h"
16f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "clang/AST/ExprObjC.h"
17f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
18f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
19f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
20f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
21f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
22f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
23f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)using namespace clang;
24f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)using namespace ento;
25f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
26f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//===----------------------------------------------------------------------===//
27f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Utility functions.
28f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//===----------------------------------------------------------------------===//
29f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
30f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const Stmt *bugreporter::GetDerefExpr(const ExplodedNode *N) {
31f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  // Pattern match for a few useful cases (do something smarter later):
32f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  //   a[0], p->f, *p
33f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
34f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
35f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  if (const UnaryOperator *U = dyn_cast<UnaryOperator>(S)) {
36f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U->getOpcode() == UO_Deref)
37f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      return U->getSubExpr()->IgnoreParenCasts();
38f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  }
39f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  else if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) {
40f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return ME->getBase()->IgnoreParenCasts();
41f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  }
42f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(S)) {
43f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return AE->getBase();
44f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  }
45f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
46f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  return NULL;
47f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
48f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
49f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) {
50f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
51f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S))
52f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return BE->getRHS();
53f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  return NULL;
54f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
55f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
56f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const Stmt *bugreporter::GetCalleeExpr(const ExplodedNode *N) {
57f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  // Callee is checked as a PreVisit to the CallExpr.
58f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
59f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  if (const CallExpr *CE = dyn_cast<CallExpr>(S))
60f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return CE->getCallee();
61f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  return NULL;
62f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
63f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
64f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) {
65f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
66f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S))
67f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return RS->getRetValue();
68f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  return NULL;
69f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
70f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
71f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//===----------------------------------------------------------------------===//
72f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Definitions for bug reporter visitors.
73f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//===----------------------------------------------------------------------===//
74f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
75f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)namespace {
76f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)class FindLastStoreBRVisitor : public BugReporterVisitor {
77f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  const MemRegion *R;
78f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  SVal V;
79f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  bool satisfied;
80f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  const ExplodedNode *StoreSite;
81f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)public:
82f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  FindLastStoreBRVisitor(SVal v, const MemRegion *r)
83f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  : R(r), V(v), satisfied(false), StoreSite(0) {}
84f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
85f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  virtual void Profile(llvm::FoldingSetNodeID &ID) const {
86f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    static int tag = 0;
87f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ID.AddPointer(&tag);
88f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ID.AddPointer(R);
89f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ID.Add(V);
90f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  }
91f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
92f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
93f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                 const ExplodedNode *PrevN,
94f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                 BugReporterContext &BRC) {
95f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
96f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (satisfied)
97f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      return NULL;
98f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
99f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (!StoreSite) {
100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      const ExplodedNode *Node = N, *Last = NULL;
101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      for ( ; Node ; Last = Node, Node = Node->getFirstPred()) {
103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)          if (const PostStmt *P = Node->getLocationAs<PostStmt>())
106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (const DeclStmt *DS = P->getStmtAs<DeclStmt>())
107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              if (DS->getSingleDecl() == VR->getDecl()) {
108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                Last = Node;
109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              }
111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (Node->getState()->getSVal(R) != V)
114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)          break;
115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      }
116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      if (!Node || !Last) {
118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        satisfied = true;
119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      }
121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      StoreSite = Last;
123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (StoreSite != N)
126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      return NULL;
127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    satisfied = true;
129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    llvm::SmallString<256> sbuf;
130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    llvm::raw_svector_ostream os(sbuf);
131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (const PostStmt *PS = N->getLocationAs<PostStmt>()) {
133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) {
134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)          os << "Variable '" << VR->getDecl() << "' ";
137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        else
139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)          return NULL;
140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (isa<loc::ConcreteInt>(V)) {
142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)          bool b = false;
143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)          if (R->isBoundable()) {
144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              if (TR->getValueType()->isObjCObjectPointerType()) {
146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                os << "initialized to nil";
147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                b = true;
148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              }
149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)          }
151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)          if (!b)
153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            os << "initialized to a null pointer value";
154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        else if (isa<nonloc::ConcreteInt>(V)) {
156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)          os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue();
157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        else if (V.isUndef()) {
159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)          if (isa<VarRegion>(R)) {
160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (VD->getInit())
162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              os << "initialized to a garbage value";
163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            else
164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              os << "declared without an initial value";
165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)          }
166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      }
168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (os.str().empty()) {
171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      if (isa<loc::ConcreteInt>(V)) {
172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        bool b = false;
173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (R->isBoundable()) {
174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)          if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (TR->getValueType()->isObjCObjectPointerType()) {
176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              os << "nil object reference stored to ";
177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              b = true;
178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)          }
180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (!b)
183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)          os << "Null pointer value stored to ";
184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      }
185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      else if (V.isUndef()) {
186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        os << "Uninitialized value stored to ";
187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      }
188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      else if (isa<nonloc::ConcreteInt>(V)) {
189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        os << "The value " << cast<nonloc::ConcreteInt>(V).getValue()
190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)           << " is assigned to ";
191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      }
192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      else
193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        os << '\'' << VR->getDecl() << '\'';
197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      }
198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      else
199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // FIXME: Refactor this into BugReporterContext.
203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const Stmt *S = 0;
204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ProgramPoint P = N->getLocation();
205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      const CFGBlock *BSrc = BE->getSrc();
208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      S = BSrc->getTerminatorCondition();
209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      S = PS->getStmt();
212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (!S)
215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      return NULL;
216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // Construct a new PathDiagnosticPiece.
218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    PathDiagnosticLocation L(S, BRC.getSourceManager());
219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return new PathDiagnosticEventPiece(L, os.str());
220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  }
221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)};
222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void registerFindLastStore(BugReporterContext &BRC, const MemRegion *R,
225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                  SVal V) {
226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  BRC.addVisitor(new FindLastStoreBRVisitor(V, R));
227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)class TrackConstraintBRVisitor : public BugReporterVisitor {
230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  DefinedSVal Constraint;
231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  const bool Assumption;
232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  bool isSatisfied;
233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)public:
234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption)
235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  : Constraint(constraint), Assumption(assumption), isSatisfied(false) {}
236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  void Profile(llvm::FoldingSetNodeID &ID) const {
238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    static int tag = 0;
239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ID.AddPointer(&tag);
240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ID.AddBoolean(Assumption);
241f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ID.Add(Constraint);
242f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  }
243f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
244f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
245f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                 const ExplodedNode *PrevN,
246f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                 BugReporterContext &BRC) {
247f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (isSatisfied)
248f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      return NULL;
249f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
250f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // Check if in the previous state it was feasible for this constraint
251f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // to *not* be true.
252f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (PrevN->getState()->assume(Constraint, !Assumption)) {
253f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
254f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      isSatisfied = true;
255f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
256f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      // As a sanity check, make sure that the negation of the constraint
257f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      // was infeasible in the current state.  If it is feasible, we somehow
258f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      // missed the transition point.
259f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      if (N->getState()->assume(Constraint, !Assumption))
260f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
261f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
262f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      // We found the transition point for the constraint.  We now need to
263f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      // pretty-print the constraint. (work-in-progress)
264f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      std::string sbuf;
265f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      llvm::raw_string_ostream os(sbuf);
266f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
267f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      if (isa<Loc>(Constraint)) {
268f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        os << "Assuming pointer value is ";
269f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        os << (Assumption ? "non-null" : "null");
270f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      }
271f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
272f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      if (os.str().empty())
273f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
274f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
275f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      // FIXME: Refactor this into BugReporterContext.
276f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      const Stmt *S = 0;
277f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      ProgramPoint P = N->getLocation();
278f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
279f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
280f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        const CFGBlock *BSrc = BE->getSrc();
281f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        S = BSrc->getTerminatorCondition();
282f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      }
283f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
284f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        S = PS->getStmt();
285f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      }
286f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
287f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      if (!S)
288f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
289f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
290f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      // Construct a new PathDiagnosticPiece.
291f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      PathDiagnosticLocation L(S, BRC.getSourceManager());
292f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      return new PathDiagnosticEventPiece(L, os.str());
293f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
294f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
295f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return NULL;
296f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  }
297f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)};
298f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} // end anonymous namespace
299f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
300f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void registerTrackConstraint(BugReporterContext &BRC,
301f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                    DefinedSVal Constraint,
302f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                    bool Assumption) {
303f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  BRC.addVisitor(new TrackConstraintBRVisitor(Constraint, Assumption));
304f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
305f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
306f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void bugreporter::registerTrackNullOrUndefValue(BugReporterContext &BRC,
307f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                                const void *data,
308f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                                const ExplodedNode *N) {
309f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
310f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  const Stmt *S = static_cast<const Stmt*>(data);
311f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
312f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  if (!S)
313f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return;
314f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
315f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  ProgramStateManager &StateMgr = BRC.getStateManager();
316f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
317f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  // Walk through nodes until we get one that matches the statement
318f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  // exactly.
319f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  while (N) {
320f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const ProgramPoint &pp = N->getLocation();
321f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (const PostStmt *ps = dyn_cast<PostStmt>(&pp)) {
322f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      if (ps->getStmt() == S)
323f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        break;
324f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
325f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    N = *N->pred_begin();
326f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  }
327f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
328f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  if (!N)
329f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return;
330f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
331f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  const ProgramState *state = N->getState();
332f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
333f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  // Walk through lvalue-to-rvalue conversions.
334f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S)) {
335f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
336f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      const VarRegion *R =
337f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
338f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
339f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      // What did we load?
340f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      SVal V = state->getSVal(loc::MemRegionVal(R));
341f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
342f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)
343f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)          || V.isUndef()) {
344f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ::registerFindLastStore(BRC, R, V);
345f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      }
346f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
347f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  }
348f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
349f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  SVal V = state->getSValAsScalarOrLoc(S);
350f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
351f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  // Uncomment this to find cases where we aren't properly getting the
352f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  // base value that was dereferenced.
353f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  // assert(!V.isUnknownOrUndef());
354f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
355f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  // Is it a symbolic value?
356f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  if (loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&V)) {
357f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const SubRegion *R = cast<SubRegion>(L->getRegion());
358f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while (R && !isa<SymbolicRegion>(R)) {
359f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      R = dyn_cast<SubRegion>(R->getSuperRegion());
360f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
361f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
362f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (R) {
363f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      assert(isa<SymbolicRegion>(R));
364f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      registerTrackConstraint(BRC, loc::MemRegionVal(R), false);
365f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
366f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  }
367f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
368f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
369f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void bugreporter::registerFindLastStore(BugReporterContext &BRC,
370f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                        const void *data,
371f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                        const ExplodedNode *N) {
372f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
373f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  const MemRegion *R = static_cast<const MemRegion*>(data);
374f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
375f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  if (!R)
376f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return;
377f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
378f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  const ProgramState *state = N->getState();
379f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  SVal V = state->getSVal(R);
380f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
381f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  if (V.isUnknown())
382f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return;
383f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
384f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  BRC.addVisitor(new FindLastStoreBRVisitor(V, R));
385f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
386f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
387f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
388f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)namespace {
389f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)class NilReceiverVisitor : public BugReporterVisitor {
390f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)public:
391f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  NilReceiverVisitor() {}
392f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
393f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  void Profile(llvm::FoldingSetNodeID &ID) const {
394f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    static int x = 0;
395f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ID.AddPointer(&x);
396f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  }
397f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
398f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
399f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                 const ExplodedNode *PrevN,
400f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                 BugReporterContext &BRC) {
401f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
402f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const PostStmt *P = N->getLocationAs<PostStmt>();
403f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (!P)
404f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      return 0;
405f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>();
406f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (!ME)
407f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      return 0;
408f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const Expr *Receiver = ME->getInstanceReceiver();
409f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (!Receiver)
410f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      return 0;
411f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const ProgramState *state = N->getState();
412f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const SVal &V = state->getSVal(Receiver);
413f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
414f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (!DV)
415f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      return 0;
416f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    state = state->assume(*DV, true);
417f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (state)
418f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      return 0;
419f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
420f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // The receiver was nil, and hence the method was skipped.
421f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // Register a BugReporterVisitor to issue a message telling us how
422f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // the receiver was null.
423f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    bugreporter::registerTrackNullOrUndefValue(BRC, Receiver, N);
424f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // Issue a message saying that the method was skipped.
425f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    PathDiagnosticLocation L(Receiver, BRC.getSourceManager());
426f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return new PathDiagnosticEventPiece(L, "No method actually called "
427f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                           "because the receiver is nil");
428f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  }
429f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)};
430f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} // end anonymous namespace
431f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
432f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void bugreporter::registerNilReceiverVisitor(BugReporterContext &BRC) {
433f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  BRC.addVisitor(new NilReceiverVisitor());
434f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
435f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
436f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Registers every VarDecl inside a Stmt with a last store vistor.
437f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void bugreporter::registerVarDeclsLastStore(BugReporterContext &BRC,
438f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                                   const void *stmt,
439f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                                   const ExplodedNode *N) {
440f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  const Stmt *S = static_cast<const Stmt *>(stmt);
441f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
442f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  std::deque<const Stmt *> WorkList;
443f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
444f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  WorkList.push_back(S);
445f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
446f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  while (!WorkList.empty()) {
447    const Stmt *Head = WorkList.front();
448    WorkList.pop_front();
449
450    ProgramStateManager &StateMgr = BRC.getStateManager();
451    const ProgramState *state = N->getState();
452
453    if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
454      if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
455        const VarRegion *R =
456        StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
457
458        // What did we load?
459        SVal V = state->getSVal(S);
460
461        if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) {
462          ::registerFindLastStore(BRC, R, V);
463        }
464      }
465    }
466
467    for (Stmt::const_child_iterator I = Head->child_begin();
468        I != Head->child_end(); ++I)
469      WorkList.push_back(*I);
470  }
471}
472
473//===----------------------------------------------------------------------===//
474// Visitor that tries to report interesting diagnostics from conditions.
475//===----------------------------------------------------------------------===//
476
477namespace {
478class ConditionVisitor : public BugReporterVisitor {
479public:
480  void Profile(llvm::FoldingSetNodeID &ID) const {
481    static int x = 0;
482    ID.AddPointer(&x);
483  }
484
485  virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
486                                         const ExplodedNode *Prev,
487                                         BugReporterContext &BRC);
488
489  PathDiagnosticPiece *VisitTerminator(const Stmt *Term,
490                                       const ProgramState *CurrentState,
491                                       const ProgramState *PrevState,
492                                       const CFGBlock *srcBlk,
493                                       const CFGBlock *dstBlk,
494                                       BugReporterContext &BRC);
495
496  PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
497                                     bool tookTrue,
498                                     BugReporterContext &BRC);
499
500  PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
501                                     const DeclRefExpr *DR,
502                                     const bool tookTrue,
503                                     BugReporterContext &BRC);
504
505  PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
506                                     const BinaryOperator *BExpr,
507                                     const bool tookTrue,
508                                     BugReporterContext &BRC);
509
510  bool patternMatch(const Expr *Ex,
511                    llvm::raw_ostream &Out,
512                    BugReporterContext &BRC);
513};
514}
515
516PathDiagnosticPiece *ConditionVisitor::VisitNode(const ExplodedNode *N,
517                                                 const ExplodedNode *Prev,
518                                                 BugReporterContext &BRC) {
519
520  const ProgramPoint &progPoint = N->getLocation();
521
522  const ProgramState *CurrentState = N->getState();
523  const ProgramState *PrevState = Prev->getState();
524
525  // Compare the GDMs of the state, because that is where constraints
526  // are managed.  Note that ensure that we only look at nodes that
527  // were generated by the analyzer engine proper, not checkers.
528  if (CurrentState->getGDM().getRoot() ==
529      PrevState->getGDM().getRoot())
530    return 0;
531
532  // If an assumption was made on a branch, it should be caught
533  // here by looking at the state transition.
534  if (const BlockEdge *BE = dyn_cast<BlockEdge>(&progPoint)) {
535    const CFGBlock *srcBlk = BE->getSrc();
536    if (const Stmt *term = srcBlk->getTerminator())
537      return VisitTerminator(term, CurrentState, PrevState,
538                             srcBlk, BE->getDst(), BRC);
539    return 0;
540  }
541
542  if (const PostStmt *PS = dyn_cast<PostStmt>(&progPoint)) {
543    // FIXME: Assuming that BugReporter is a GRBugReporter is a layering
544    // violation.
545    const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
546      cast<GRBugReporter>(BRC.getBugReporter()).
547        getEngine().getEagerlyAssumeTags();
548
549    const ProgramPointTag *tag = PS->getTag();
550    if (tag == tags.first)
551      return VisitTrueTest(cast<Expr>(PS->getStmt()), true, BRC);
552    if (tag == tags.second)
553      return VisitTrueTest(cast<Expr>(PS->getStmt()), false, BRC);
554
555    return 0;
556  }
557
558  return 0;
559}
560
561PathDiagnosticPiece *
562ConditionVisitor::VisitTerminator(const Stmt *Term,
563                                  const ProgramState *CurrentState,
564                                  const ProgramState *PrevState,
565                                  const CFGBlock *srcBlk,
566                                  const CFGBlock *dstBlk,
567                                  BugReporterContext &BRC) {
568
569  const Expr *Cond = 0;
570
571  switch (Term->getStmtClass()) {
572  default:
573    return 0;
574  case Stmt::IfStmtClass:
575    Cond = cast<IfStmt>(Term)->getCond();
576    break;
577  case Stmt::ConditionalOperatorClass:
578    Cond = cast<ConditionalOperator>(Term)->getCond();
579    break;
580  }
581
582  assert(Cond);
583  assert(srcBlk->succ_size() == 2);
584  const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk;
585  return VisitTrueTest(Cond->IgnoreParenNoopCasts(BRC.getASTContext()),
586                       tookTrue, BRC);
587}
588
589PathDiagnosticPiece *
590ConditionVisitor::VisitTrueTest(const Expr *Cond,
591                                bool tookTrue,
592                                BugReporterContext &BRC) {
593
594  const Expr *Ex = Cond;
595
596  while (true) {
597    Ex = Ex->IgnoreParens();
598    switch (Ex->getStmtClass()) {
599      default:
600        return 0;
601      case Stmt::BinaryOperatorClass:
602        return VisitTrueTest(Cond, cast<BinaryOperator>(Cond), tookTrue, BRC);
603      case Stmt::DeclRefExprClass:
604        return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC);
605      case Stmt::UnaryOperatorClass: {
606        const UnaryOperator *UO = cast<UnaryOperator>(Ex);
607        if (UO->getOpcode() == UO_LNot) {
608          tookTrue = !tookTrue;
609          Ex = UO->getSubExpr()->IgnoreParenNoopCasts(BRC.getASTContext());
610          continue;
611        }
612        return 0;
613      }
614    }
615  }
616}
617
618bool ConditionVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out,
619                                    BugReporterContext &BRC) {
620  const Expr *OriginalExpr = Ex;
621  Ex = Ex->IgnoreParenCasts();
622
623  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
624    const bool quotes = isa<VarDecl>(DR->getDecl());
625    if (quotes)
626      Out << '\'';
627    Out << DR->getDecl()->getDeclName().getAsString();
628    if (quotes)
629      Out << '\'';
630    return quotes;
631  }
632
633  if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) {
634    QualType OriginalTy = OriginalExpr->getType();
635    if (OriginalTy->isPointerType()) {
636      if (IL->getValue() == 0) {
637        Out << "null";
638        return false;
639      }
640    }
641    else if (OriginalTy->isObjCObjectPointerType()) {
642      if (IL->getValue() == 0) {
643        Out << "nil";
644        return false;
645      }
646    }
647
648    Out << IL->getValue();
649    return false;
650  }
651
652  return false;
653}
654
655PathDiagnosticPiece *
656ConditionVisitor::VisitTrueTest(const Expr *Cond,
657                                const BinaryOperator *BExpr,
658                                const bool tookTrue,
659                                BugReporterContext &BRC) {
660
661  bool shouldInvert = false;
662
663  llvm::SmallString<128> LhsString, RhsString;
664  {
665    llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
666    const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC);
667    const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC);
668
669    shouldInvert = !isVarLHS && isVarRHS;
670  }
671
672  if (LhsString.empty() || RhsString.empty())
673    return 0;
674
675  // Should we invert the strings if the LHS is not a variable name?
676
677  llvm::SmallString<256> buf;
678  llvm::raw_svector_ostream Out(buf);
679  Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is ";
680
681  // Do we need to invert the opcode?
682  BinaryOperator::Opcode Op = BExpr->getOpcode();
683
684  if (shouldInvert)
685    switch (Op) {
686      default: break;
687      case BO_LT: Op = BO_GT; break;
688      case BO_GT: Op = BO_LT; break;
689      case BO_LE: Op = BO_GE; break;
690      case BO_GE: Op = BO_LE; break;
691    }
692
693  if (!tookTrue)
694    switch (Op) {
695      case BO_EQ: Op = BO_NE; break;
696      case BO_NE: Op = BO_EQ; break;
697      case BO_LT: Op = BO_GE; break;
698      case BO_GT: Op = BO_LE; break;
699      case BO_LE: Op = BO_GT; break;
700      case BO_GE: Op = BO_LT; break;
701      default:
702        return 0;
703    }
704
705  switch (BExpr->getOpcode()) {
706    case BO_EQ:
707      Out << "equal to ";
708      break;
709    case BO_NE:
710      Out << "not equal to ";
711      break;
712    default:
713      Out << BinaryOperator::getOpcodeStr(Op) << ' ';
714      break;
715  }
716
717  Out << (shouldInvert ? LhsString : RhsString);
718
719  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager());
720  return new PathDiagnosticEventPiece(Loc, Out.str());
721}
722
723PathDiagnosticPiece *
724ConditionVisitor::VisitTrueTest(const Expr *Cond,
725                                const DeclRefExpr *DR,
726                                const bool tookTrue,
727                                BugReporterContext &BRC) {
728
729  const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
730  if (!VD)
731    return 0;
732
733  llvm::SmallString<256> Buf;
734  llvm::raw_svector_ostream Out(Buf);
735
736  Out << "Assuming '";
737  VD->getDeclName().printName(Out);
738  Out << "' is ";
739
740  QualType VDTy = VD->getType();
741
742  if (VDTy->isPointerType())
743    Out << (tookTrue ? "non-null" : "null");
744  else if (VDTy->isObjCObjectPointerType())
745    Out << (tookTrue ? "non-nil" : "nil");
746  else if (VDTy->isScalarType())
747    Out << (tookTrue ? "not equal to 0" : "0");
748  else
749    return 0;
750
751  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager());
752  return new PathDiagnosticEventPiece(Loc, Out.str());
753}
754
755void bugreporter::registerConditionVisitor(BugReporterContext &BRC) {
756  BRC.addVisitor(new ConditionVisitor());
757}
758
759