BugReporterVisitors.cpp revision a1f81bb0e55749a1414b1b5124bb83b9052ff2ac
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// BugReporterVisitors.cpp - Helpers for reporting bugs -----------*- C++ -*--//
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//                     The LLVM Compiler Infrastructure
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// This file is distributed under the University of Illinois Open Source
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// License. See LICENSE.TXT for details.
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===//
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//  This file defines a set of BugReporter "visitors" which can be used to
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//  enhance the diagnostics reported for a bug.
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch//===----------------------------------------------------------------------===//
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "clang/AST/Expr.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/AST/ExprObjC.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "llvm/ADT/SmallString.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using namespace clang;
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using namespace ento;
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===//
30c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Utility functions.
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===//
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const Stmt *bugreporter::GetDerefExpr(const ExplodedNode *N) {
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Pattern match for a few useful cases (do something smarter later):
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //   a[0], p->f, *p
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const PostStmt *Loc = N->getLocationAs<PostStmt>();
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!Loc)
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return 0;
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const Expr *S = dyn_cast<Expr>(Loc->getStmt());
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!S)
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return 0;
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  S = S->IgnoreParenCasts();
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  while (true) {
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
47a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      assert(B->isAssignmentOp());
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      S = B->getLHS()->IgnoreParenCasts();
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      continue;
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
51a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(S)) {
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (U->getOpcode() == UO_Deref)
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return U->getSubExpr()->IgnoreParenCasts();
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    else if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) {
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return ME->getBase()->IgnoreParenCasts();
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(S)) {
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return AE->getBase();
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    break;
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return NULL;
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
66
67const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) {
68  const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
69  if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S))
70    return BE->getRHS();
71  return NULL;
72}
73
74const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) {
75  const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
76  if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S))
77    return RS->getRetValue();
78  return NULL;
79}
80
81//===----------------------------------------------------------------------===//
82// Definitions for bug reporter visitors.
83//===----------------------------------------------------------------------===//
84
85PathDiagnosticPiece*
86BugReporterVisitor::getEndPath(BugReporterContext &BRC,
87                               const ExplodedNode *EndPathNode,
88                               BugReport &BR) {
89  return 0;
90}
91
92PathDiagnosticPiece*
93BugReporterVisitor::getDefaultEndPath(BugReporterContext &BRC,
94                                      const ExplodedNode *EndPathNode,
95                                      BugReport &BR) {
96  PathDiagnosticLocation L =
97    PathDiagnosticLocation::createEndOfPath(EndPathNode,BRC.getSourceManager());
98
99  BugReport::ranges_iterator Beg, End;
100  llvm::tie(Beg, End) = BR.getRanges();
101
102  // Only add the statement itself as a range if we didn't specify any
103  // special ranges for this report.
104  PathDiagnosticPiece *P = new PathDiagnosticEventPiece(L,
105      BR.getDescription(),
106      Beg == End);
107  for (; Beg != End; ++Beg)
108    P->addRange(*Beg);
109
110  return P;
111}
112
113
114namespace {
115/// Emits an extra note at the return statement of an interesting stack frame.
116///
117/// The returned value is marked as an interesting value, and if it's null,
118/// adds a visitor to track where it became null.
119///
120/// This visitor is intended to be used when another visitor discovers that an
121/// interesting value comes from an inlined function call.
122class ReturnVisitor : public BugReporterVisitorImpl<ReturnVisitor> {
123  const StackFrameContext *StackFrame;
124  bool Satisfied;
125public:
126  ReturnVisitor(const StackFrameContext *Frame)
127    : StackFrame(Frame), Satisfied(false) {}
128
129  virtual void Profile(llvm::FoldingSetNodeID &ID) const {
130    static int Tag = 0;
131    ID.AddPointer(&Tag);
132    ID.AddPointer(StackFrame);
133  }
134
135  /// Adds a ReturnVisitor if the given statement represents a call that was
136  /// inlined.
137  ///
138  /// This will search back through the ExplodedGraph, starting from the given
139  /// node, looking for when the given statement was processed. If it turns out
140  /// the statement is a call that was inlined, we add the visitor to the
141  /// bug report, so it can print a note later.
142  static void addVisitorIfNecessary(const ExplodedNode *Node, const Stmt *S,
143                                    BugReport &BR) {
144    if (!CallEvent::isCallStmt(S))
145      return;
146
147    // First, find when we processed the statement.
148    do {
149      if (const CallExitEnd *CEE = Node->getLocationAs<CallExitEnd>())
150        if (CEE->getCalleeContext()->getCallSite() == S)
151          break;
152      if (const StmtPoint *SP = Node->getLocationAs<StmtPoint>())
153        if (SP->getStmt() == S)
154          break;
155
156      Node = Node->getFirstPred();
157    } while (Node);
158
159    // Next, step over any post-statement checks.
160    while (Node && isa<PostStmt>(Node->getLocation()))
161      Node = Node->getFirstPred();
162
163    // Finally, see if we inlined the call.
164    if (Node)
165      if (const CallExitEnd *CEE = Node->getLocationAs<CallExitEnd>())
166        if (CEE->getCalleeContext()->getCallSite() == S)
167          BR.addVisitor(new ReturnVisitor(CEE->getCalleeContext()));
168
169  }
170
171  PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
172                                 const ExplodedNode *PrevN,
173                                 BugReporterContext &BRC,
174                                 BugReport &BR) {
175    if (Satisfied)
176      return 0;
177
178    // Only print a message at the interesting return statement.
179    if (N->getLocationContext() != StackFrame)
180      return 0;
181
182    const StmtPoint *SP = N->getLocationAs<StmtPoint>();
183    if (!SP)
184      return 0;
185
186    const ReturnStmt *Ret = dyn_cast<ReturnStmt>(SP->getStmt());
187    if (!Ret)
188      return 0;
189
190    // Okay, we're at the right return statement, but do we have the return
191    // value available?
192    ProgramStateRef State = N->getState();
193    SVal V = State->getSVal(Ret, StackFrame);
194    if (V.isUnknownOrUndef())
195      return 0;
196
197    // Don't print any more notes after this one.
198    Satisfied = true;
199
200    // Build an appropriate message based on the return value.
201    SmallString<64> Msg;
202    llvm::raw_svector_ostream Out(Msg);
203
204    const Expr *RetE = Ret->getRetValue();
205    assert(RetE && "Tracking a return value for a void function");
206    RetE = RetE->IgnoreParenCasts();
207
208    // See if we know that the return value is 0.
209    ProgramStateRef StNonZero, StZero;
210    llvm::tie(StNonZero, StZero) = State->assume(cast<DefinedSVal>(V));
211    if (StZero && !StNonZero) {
212      // If we're returning 0, we should track where that 0 came from.
213      bugreporter::trackNullOrUndefValue(N, RetE, BR);
214
215      if (isa<Loc>(V)) {
216        if (RetE->getType()->isObjCObjectPointerType())
217          Out << "Returning nil";
218        else
219          Out << "Returning null pointer";
220      } else {
221        Out << "Returning zero";
222      }
223    } else {
224      // FIXME: We can probably do better than this.
225      BR.markInteresting(V);
226      Out << "Value returned here";
227    }
228
229    // FIXME: We should have a more generalized location printing mechanism.
230    if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(RetE))
231      if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(DR->getDecl()))
232        Out << " (loaded from '" << *DD << "')";
233
234    PathDiagnosticLocation L(Ret, BRC.getSourceManager(), StackFrame);
235    return new PathDiagnosticEventPiece(L, Out.str());
236  }
237};
238} // end anonymous namespace
239
240
241void FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const {
242  static int tag = 0;
243  ID.AddPointer(&tag);
244  ID.AddPointer(R);
245  ID.Add(V);
246}
247
248PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
249                                                       const ExplodedNode *Pred,
250                                                       BugReporterContext &BRC,
251                                                       BugReport &BR) {
252
253  if (satisfied)
254    return NULL;
255
256  const ExplodedNode *StoreSite = 0;
257  const Expr *InitE = 0;
258
259  // First see if we reached the declaration of the region.
260  if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
261    if (const PostStmt *P = Pred->getLocationAs<PostStmt>()) {
262      if (const DeclStmt *DS = P->getStmtAs<DeclStmt>()) {
263        if (DS->getSingleDecl() == VR->getDecl()) {
264          StoreSite = Pred;
265          InitE = VR->getDecl()->getInit();
266        }
267      }
268    }
269  }
270
271  // Otherwise, check that Succ has this binding and Pred does not, i.e. this is
272  // where the binding first occurred.
273  if (!StoreSite) {
274    if (Succ->getState()->getSVal(R) != V)
275      return NULL;
276    if (Pred->getState()->getSVal(R) == V)
277      return NULL;
278
279    StoreSite = Succ;
280
281    // If this is an assignment expression, we can track the value
282    // being assigned.
283    if (const PostStmt *P = Succ->getLocationAs<PostStmt>())
284      if (const BinaryOperator *BO = P->getStmtAs<BinaryOperator>())
285        if (BO->isAssignmentOp())
286          InitE = BO->getRHS();
287  }
288
289  if (!StoreSite)
290    return NULL;
291  satisfied = true;
292
293  // If the value that was stored came from an inlined call, make sure we
294  // step into the call.
295  if (InitE) {
296    InitE = InitE->IgnoreParenCasts();
297    ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE, BR);
298  }
299
300  // Okay, we've found the binding. Emit an appropriate message.
301  SmallString<256> sbuf;
302  llvm::raw_svector_ostream os(sbuf);
303
304  if (const PostStmt *PS = StoreSite->getLocationAs<PostStmt>()) {
305    if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) {
306
307      if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
308        os << "Variable '" << *VR->getDecl() << "' ";
309      }
310      else
311        return NULL;
312
313      if (isa<loc::ConcreteInt>(V)) {
314        bool b = false;
315        if (R->isBoundable()) {
316          if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
317            if (TR->getValueType()->isObjCObjectPointerType()) {
318              os << "initialized to nil";
319              b = true;
320            }
321          }
322        }
323
324        if (!b)
325          os << "initialized to a null pointer value";
326      }
327      else if (isa<nonloc::ConcreteInt>(V)) {
328        os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue();
329      }
330      else if (V.isUndef()) {
331        if (isa<VarRegion>(R)) {
332          const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
333          if (VD->getInit())
334            os << "initialized to a garbage value";
335          else
336            os << "declared without an initial value";
337        }
338      }
339      else {
340        os << "initialized here";
341      }
342    }
343  }
344
345  if (os.str().empty()) {
346    if (isa<loc::ConcreteInt>(V)) {
347      bool b = false;
348      if (R->isBoundable()) {
349        if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
350          if (TR->getValueType()->isObjCObjectPointerType()) {
351            os << "nil object reference stored to ";
352            b = true;
353          }
354        }
355      }
356
357      if (!b)
358        os << "Null pointer value stored to ";
359    }
360    else if (V.isUndef()) {
361      os << "Uninitialized value stored to ";
362    }
363    else if (isa<nonloc::ConcreteInt>(V)) {
364      os << "The value " << cast<nonloc::ConcreteInt>(V).getValue()
365               << " is assigned to ";
366    }
367    else
368      os << "Value assigned to ";
369
370    if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
371      os << '\'' << *VR->getDecl() << '\'';
372    }
373    else
374      return NULL;
375  }
376
377  // Construct a new PathDiagnosticPiece.
378  ProgramPoint P = StoreSite->getLocation();
379  PathDiagnosticLocation L =
380    PathDiagnosticLocation::create(P, BRC.getSourceManager());
381  if (!L.isValid())
382    return NULL;
383  return new PathDiagnosticEventPiece(L, os.str());
384}
385
386void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
387  static int tag = 0;
388  ID.AddPointer(&tag);
389  ID.AddBoolean(Assumption);
390  ID.Add(Constraint);
391}
392
393PathDiagnosticPiece *
394TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
395                                    const ExplodedNode *PrevN,
396                                    BugReporterContext &BRC,
397                                    BugReport &BR) {
398  if (isSatisfied)
399    return NULL;
400
401  // Check if in the previous state it was feasible for this constraint
402  // to *not* be true.
403  if (PrevN->getState()->assume(Constraint, !Assumption)) {
404
405    isSatisfied = true;
406
407    // As a sanity check, make sure that the negation of the constraint
408    // was infeasible in the current state.  If it is feasible, we somehow
409    // missed the transition point.
410    if (N->getState()->assume(Constraint, !Assumption))
411      return NULL;
412
413    // We found the transition point for the constraint.  We now need to
414    // pretty-print the constraint. (work-in-progress)
415    std::string sbuf;
416    llvm::raw_string_ostream os(sbuf);
417
418    if (isa<Loc>(Constraint)) {
419      os << "Assuming pointer value is ";
420      os << (Assumption ? "non-null" : "null");
421    }
422
423    if (os.str().empty())
424      return NULL;
425
426    // Construct a new PathDiagnosticPiece.
427    ProgramPoint P = N->getLocation();
428    PathDiagnosticLocation L =
429      PathDiagnosticLocation::create(P, BRC.getSourceManager());
430    if (!L.isValid())
431      return NULL;
432    return new PathDiagnosticEventPiece(L, os.str());
433  }
434
435  return NULL;
436}
437
438void bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S,
439                                        BugReport &report) {
440  if (!S || !N)
441    return;
442
443  ProgramStateManager &StateMgr = N->getState()->getStateManager();
444
445  // Walk through nodes until we get one that matches the statement exactly.
446  while (N) {
447    const ProgramPoint &pp = N->getLocation();
448    if (const PostStmt *ps = dyn_cast<PostStmt>(&pp)) {
449      if (ps->getStmt() == S)
450        break;
451    } else if (const CallExitEnd *CEE = dyn_cast<CallExitEnd>(&pp)) {
452      if (CEE->getCalleeContext()->getCallSite() == S)
453        break;
454    }
455    N = N->getFirstPred();
456  }
457
458  if (!N)
459    return;
460
461  ProgramStateRef state = N->getState();
462
463  // See if the expression we're interested refers to a variable.
464  // If so, we can track both its contents and constraints on its value.
465  if (const Expr *Ex = dyn_cast<Expr>(S)) {
466    // Strip off parens and casts. Note that this will never have issues with
467    // C++ user-defined implicit conversions, because those have a constructor
468    // or function call inside.
469    Ex = Ex->IgnoreParenCasts();
470    if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
471      // FIXME: Right now we only track VarDecls because it's non-trivial to
472      // get a MemRegion for any other DeclRefExprs. <rdar://problem/12114812>
473      if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
474        const VarRegion *R =
475          StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
476
477        // Mark both the variable region and its contents as interesting.
478        SVal V = state->getRawSVal(loc::MemRegionVal(R));
479        report.markInteresting(R);
480        report.markInteresting(V);
481
482        // If the contents are symbolic, find out when they became null.
483        if (V.getAsLocSymbol()) {
484          BugReporterVisitor *ConstraintTracker
485            = new TrackConstraintBRVisitor(cast<loc::MemRegionVal>(V), false);
486          report.addVisitor(ConstraintTracker);
487        }
488
489        report.addVisitor(new FindLastStoreBRVisitor(V, R));
490        return;
491      }
492    }
493  }
494
495  // If the expression does NOT refer to a variable, we can still track
496  // constraints on its contents.
497  SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext());
498
499  // Uncomment this to find cases where we aren't properly getting the
500  // base value that was dereferenced.
501  // assert(!V.isUnknownOrUndef());
502
503  // Is it a symbolic value?
504  if (loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&V)) {
505    const MemRegion *Base = L->getRegion()->getBaseRegion();
506    if (isa<SymbolicRegion>(Base)) {
507      report.markInteresting(Base);
508      report.addVisitor(new TrackConstraintBRVisitor(loc::MemRegionVal(Base),
509                                                      false));
510    }
511  } else {
512    // Otherwise, if the value came from an inlined function call,
513    // we should at least make sure that function isn't pruned in our output.
514    ReturnVisitor::addVisitorIfNecessary(N, S, report);
515  }
516}
517
518BugReporterVisitor *
519FindLastStoreBRVisitor::createVisitorObject(const ExplodedNode *N,
520                                            const MemRegion *R) {
521  assert(R && "The memory region is null.");
522
523  ProgramStateRef state = N->getState();
524  SVal V = state->getSVal(R);
525  if (V.isUnknown())
526    return 0;
527
528  return new FindLastStoreBRVisitor(V, R);
529}
530
531
532PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
533                                                     const ExplodedNode *PrevN,
534                                                     BugReporterContext &BRC,
535                                                     BugReport &BR) {
536  const PostStmt *P = N->getLocationAs<PostStmt>();
537  if (!P)
538    return 0;
539  const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>();
540  if (!ME)
541    return 0;
542  const Expr *Receiver = ME->getInstanceReceiver();
543  if (!Receiver)
544    return 0;
545  ProgramStateRef state = N->getState();
546  const SVal &V = state->getSVal(Receiver, N->getLocationContext());
547  const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
548  if (!DV)
549    return 0;
550  state = state->assume(*DV, true);
551  if (state)
552    return 0;
553
554  // The receiver was nil, and hence the method was skipped.
555  // Register a BugReporterVisitor to issue a message telling us how
556  // the receiver was null.
557  bugreporter::trackNullOrUndefValue(N, Receiver, BR);
558  // Issue a message saying that the method was skipped.
559  PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
560                                     N->getLocationContext());
561  return new PathDiagnosticEventPiece(L, "No method is called "
562      "because the receiver is nil");
563}
564
565// Registers every VarDecl inside a Stmt with a last store visitor.
566void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
567                                                       const Stmt *S) {
568  const ExplodedNode *N = BR.getErrorNode();
569  std::deque<const Stmt *> WorkList;
570  WorkList.push_back(S);
571
572  while (!WorkList.empty()) {
573    const Stmt *Head = WorkList.front();
574    WorkList.pop_front();
575
576    ProgramStateRef state = N->getState();
577    ProgramStateManager &StateMgr = state->getStateManager();
578
579    if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
580      if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
581        const VarRegion *R =
582        StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
583
584        // What did we load?
585        SVal V = state->getSVal(S, N->getLocationContext());
586
587        if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) {
588          // Register a new visitor with the BugReport.
589          BR.addVisitor(new FindLastStoreBRVisitor(V, R));
590        }
591      }
592    }
593
594    for (Stmt::const_child_iterator I = Head->child_begin();
595        I != Head->child_end(); ++I)
596      WorkList.push_back(*I);
597  }
598}
599
600//===----------------------------------------------------------------------===//
601// Visitor that tries to report interesting diagnostics from conditions.
602//===----------------------------------------------------------------------===//
603PathDiagnosticPiece *ConditionBRVisitor::VisitNode(const ExplodedNode *N,
604                                                   const ExplodedNode *Prev,
605                                                   BugReporterContext &BRC,
606                                                   BugReport &BR) {
607  PathDiagnosticPiece *piece = VisitNodeImpl(N, Prev, BRC, BR);
608  if (PathDiagnosticEventPiece *ev =
609      dyn_cast_or_null<PathDiagnosticEventPiece>(piece))
610    ev->setPrunable(true, /* override */ false);
611  return piece;
612}
613
614PathDiagnosticPiece *ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
615                                                       const ExplodedNode *Prev,
616                                                       BugReporterContext &BRC,
617                                                       BugReport &BR) {
618
619  const ProgramPoint &progPoint = N->getLocation();
620
621  ProgramStateRef CurrentState = N->getState();
622  ProgramStateRef PrevState = Prev->getState();
623
624  // Compare the GDMs of the state, because that is where constraints
625  // are managed.  Note that ensure that we only look at nodes that
626  // were generated by the analyzer engine proper, not checkers.
627  if (CurrentState->getGDM().getRoot() ==
628      PrevState->getGDM().getRoot())
629    return 0;
630
631  // If an assumption was made on a branch, it should be caught
632  // here by looking at the state transition.
633  if (const BlockEdge *BE = dyn_cast<BlockEdge>(&progPoint)) {
634    const CFGBlock *srcBlk = BE->getSrc();
635    if (const Stmt *term = srcBlk->getTerminator())
636      return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC);
637    return 0;
638  }
639
640  if (const PostStmt *PS = dyn_cast<PostStmt>(&progPoint)) {
641    // FIXME: Assuming that BugReporter is a GRBugReporter is a layering
642    // violation.
643    const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
644      cast<GRBugReporter>(BRC.getBugReporter()).
645        getEngine().getEagerlyAssumeTags();
646
647    const ProgramPointTag *tag = PS->getTag();
648    if (tag == tags.first)
649      return VisitTrueTest(cast<Expr>(PS->getStmt()), true,
650                           BRC, BR, N);
651    if (tag == tags.second)
652      return VisitTrueTest(cast<Expr>(PS->getStmt()), false,
653                           BRC, BR, N);
654
655    return 0;
656  }
657
658  return 0;
659}
660
661PathDiagnosticPiece *
662ConditionBRVisitor::VisitTerminator(const Stmt *Term,
663                                    const ExplodedNode *N,
664                                    const CFGBlock *srcBlk,
665                                    const CFGBlock *dstBlk,
666                                    BugReport &R,
667                                    BugReporterContext &BRC) {
668  const Expr *Cond = 0;
669
670  switch (Term->getStmtClass()) {
671  default:
672    return 0;
673  case Stmt::IfStmtClass:
674    Cond = cast<IfStmt>(Term)->getCond();
675    break;
676  case Stmt::ConditionalOperatorClass:
677    Cond = cast<ConditionalOperator>(Term)->getCond();
678    break;
679  }
680
681  assert(Cond);
682  assert(srcBlk->succ_size() == 2);
683  const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk;
684  return VisitTrueTest(Cond->IgnoreParenNoopCasts(BRC.getASTContext()),
685                       tookTrue, BRC, R, N);
686}
687
688PathDiagnosticPiece *
689ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
690                                  bool tookTrue,
691                                  BugReporterContext &BRC,
692                                  BugReport &R,
693                                  const ExplodedNode *N) {
694
695  const Expr *Ex = Cond;
696
697  while (true) {
698    Ex = Ex->IgnoreParens();
699    switch (Ex->getStmtClass()) {
700      default:
701        return 0;
702      case Stmt::BinaryOperatorClass:
703        return VisitTrueTest(Cond, cast<BinaryOperator>(Ex), tookTrue, BRC,
704                             R, N);
705      case Stmt::DeclRefExprClass:
706        return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC,
707                             R, N);
708      case Stmt::UnaryOperatorClass: {
709        const UnaryOperator *UO = cast<UnaryOperator>(Ex);
710        if (UO->getOpcode() == UO_LNot) {
711          tookTrue = !tookTrue;
712          Ex = UO->getSubExpr()->IgnoreParenNoopCasts(BRC.getASTContext());
713          continue;
714        }
715        return 0;
716      }
717    }
718  }
719}
720
721bool ConditionBRVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out,
722                                      BugReporterContext &BRC,
723                                      BugReport &report,
724                                      const ExplodedNode *N,
725                                      llvm::Optional<bool> &prunable) {
726  const Expr *OriginalExpr = Ex;
727  Ex = Ex->IgnoreParenCasts();
728
729  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
730    const bool quotes = isa<VarDecl>(DR->getDecl());
731    if (quotes) {
732      Out << '\'';
733      const LocationContext *LCtx = N->getLocationContext();
734      const ProgramState *state = N->getState().getPtr();
735      if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
736                                                LCtx).getAsRegion()) {
737        if (report.isInteresting(R))
738          prunable = false;
739        else {
740          const ProgramState *state = N->getState().getPtr();
741          SVal V = state->getSVal(R);
742          if (report.isInteresting(V))
743            prunable = false;
744        }
745      }
746    }
747    Out << DR->getDecl()->getDeclName().getAsString();
748    if (quotes)
749      Out << '\'';
750    return quotes;
751  }
752
753  if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) {
754    QualType OriginalTy = OriginalExpr->getType();
755    if (OriginalTy->isPointerType()) {
756      if (IL->getValue() == 0) {
757        Out << "null";
758        return false;
759      }
760    }
761    else if (OriginalTy->isObjCObjectPointerType()) {
762      if (IL->getValue() == 0) {
763        Out << "nil";
764        return false;
765      }
766    }
767
768    Out << IL->getValue();
769    return false;
770  }
771
772  return false;
773}
774
775PathDiagnosticPiece *
776ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
777                                  const BinaryOperator *BExpr,
778                                  const bool tookTrue,
779                                  BugReporterContext &BRC,
780                                  BugReport &R,
781                                  const ExplodedNode *N) {
782
783  bool shouldInvert = false;
784  llvm::Optional<bool> shouldPrune;
785
786  SmallString<128> LhsString, RhsString;
787  {
788    llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
789    const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC, R, N,
790                                       shouldPrune);
791    const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC, R, N,
792                                       shouldPrune);
793
794    shouldInvert = !isVarLHS && isVarRHS;
795  }
796
797  BinaryOperator::Opcode Op = BExpr->getOpcode();
798
799  if (BinaryOperator::isAssignmentOp(Op)) {
800    // For assignment operators, all that we care about is that the LHS
801    // evaluates to "true" or "false".
802    return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue,
803                                  BRC, R, N);
804  }
805
806  // For non-assignment operations, we require that we can understand
807  // both the LHS and RHS.
808  if (LhsString.empty() || RhsString.empty())
809    return 0;
810
811  // Should we invert the strings if the LHS is not a variable name?
812  SmallString<256> buf;
813  llvm::raw_svector_ostream Out(buf);
814  Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is ";
815
816  // Do we need to invert the opcode?
817  if (shouldInvert)
818    switch (Op) {
819      default: break;
820      case BO_LT: Op = BO_GT; break;
821      case BO_GT: Op = BO_LT; break;
822      case BO_LE: Op = BO_GE; break;
823      case BO_GE: Op = BO_LE; break;
824    }
825
826  if (!tookTrue)
827    switch (Op) {
828      case BO_EQ: Op = BO_NE; break;
829      case BO_NE: Op = BO_EQ; break;
830      case BO_LT: Op = BO_GE; break;
831      case BO_GT: Op = BO_LE; break;
832      case BO_LE: Op = BO_GT; break;
833      case BO_GE: Op = BO_LT; break;
834      default:
835        return 0;
836    }
837
838  switch (Op) {
839    case BO_EQ:
840      Out << "equal to ";
841      break;
842    case BO_NE:
843      Out << "not equal to ";
844      break;
845    default:
846      Out << BinaryOperator::getOpcodeStr(Op) << ' ';
847      break;
848  }
849
850  Out << (shouldInvert ? LhsString : RhsString);
851  const LocationContext *LCtx = N->getLocationContext();
852  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
853  PathDiagnosticEventPiece *event =
854    new PathDiagnosticEventPiece(Loc, Out.str());
855  if (shouldPrune.hasValue())
856    event->setPrunable(shouldPrune.getValue());
857  return event;
858}
859
860PathDiagnosticPiece *
861ConditionBRVisitor::VisitConditionVariable(StringRef LhsString,
862                                           const Expr *CondVarExpr,
863                                           const bool tookTrue,
864                                           BugReporterContext &BRC,
865                                           BugReport &report,
866                                           const ExplodedNode *N) {
867  // FIXME: If there's already a constraint tracker for this variable,
868  // we shouldn't emit anything here (c.f. the double note in
869  // test/Analysis/inlining/path-notes.c)
870  SmallString<256> buf;
871  llvm::raw_svector_ostream Out(buf);
872  Out << "Assuming " << LhsString << " is ";
873
874  QualType Ty = CondVarExpr->getType();
875
876  if (Ty->isPointerType())
877    Out << (tookTrue ? "not null" : "null");
878  else if (Ty->isObjCObjectPointerType())
879    Out << (tookTrue ? "not nil" : "nil");
880  else if (Ty->isBooleanType())
881    Out << (tookTrue ? "true" : "false");
882  else if (Ty->isIntegerType())
883    Out << (tookTrue ? "non-zero" : "zero");
884  else
885    return 0;
886
887  const LocationContext *LCtx = N->getLocationContext();
888  PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
889  PathDiagnosticEventPiece *event =
890    new PathDiagnosticEventPiece(Loc, Out.str());
891
892  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
893    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
894      const ProgramState *state = N->getState().getPtr();
895      if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
896        if (report.isInteresting(R))
897          event->setPrunable(false);
898      }
899    }
900  }
901
902  return event;
903}
904
905PathDiagnosticPiece *
906ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
907                                  const DeclRefExpr *DR,
908                                  const bool tookTrue,
909                                  BugReporterContext &BRC,
910                                  BugReport &report,
911                                  const ExplodedNode *N) {
912
913  const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
914  if (!VD)
915    return 0;
916
917  SmallString<256> Buf;
918  llvm::raw_svector_ostream Out(Buf);
919
920  Out << "Assuming '";
921  VD->getDeclName().printName(Out);
922  Out << "' is ";
923
924  QualType VDTy = VD->getType();
925
926  if (VDTy->isPointerType())
927    Out << (tookTrue ? "non-null" : "null");
928  else if (VDTy->isObjCObjectPointerType())
929    Out << (tookTrue ? "non-nil" : "nil");
930  else if (VDTy->isScalarType())
931    Out << (tookTrue ? "not equal to 0" : "0");
932  else
933    return 0;
934
935  const LocationContext *LCtx = N->getLocationContext();
936  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
937  PathDiagnosticEventPiece *event =
938    new PathDiagnosticEventPiece(Loc, Out.str());
939
940  const ProgramState *state = N->getState().getPtr();
941  if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
942    if (report.isInteresting(R))
943      event->setPrunable(false);
944    else {
945      SVal V = state->getSVal(R);
946      if (report.isInteresting(V))
947        event->setPrunable(false);
948    }
949  }
950  return event;
951}
952
953