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