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