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