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   if (!S || !N)
292     return 0;
293 
294   ProgramStateManager &StateMgr = N->getState()->getStateManager();
295 
296   // Walk through nodes until we get one that matches the statement
297   // exactly.
298   while (N) {
299     const ProgramPoint &pp = N->getLocation();
300     if (const PostStmt *ps = dyn_cast<PostStmt>(&pp)) {
301       if (ps->getStmt() == S)
302         break;
303     }
304     N = N->getFirstPred();
305   }
306 
307   if (!N)
308     return 0;
309 
310   ProgramStateRef state = N->getState();
311 
312   // Walk through lvalue-to-rvalue conversions.
313   if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S)) {
314     if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
315       const VarRegion *R =
316         StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
317 
318       // What did we load?
319       SVal V = state->getSVal(loc::MemRegionVal(R));
320 
321       if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)
322           || V.isUndef()) {
323         return new FindLastStoreBRVisitor(V, R);
324       }
325     }
326   }
327 
328   SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext());
329 
330   // Uncomment this to find cases where we aren't properly getting the
331   // base value that was dereferenced.
332   // assert(!V.isUnknownOrUndef());
333 
334   // Is it a symbolic value?
335   if (loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&V)) {
336     const SubRegion *R = cast<SubRegion>(L->getRegion());
337     while (R && !isa<SymbolicRegion>(R)) {
338       R = dyn_cast<SubRegion>(R->getSuperRegion());
339     }
340 
341     if (R) {
342       assert(isa<SymbolicRegion>(R));
343       return new TrackConstraintBRVisitor(loc::MemRegionVal(R), false);
344     }
345   }
346 
347   return 0;
348 }
349 
350 BugReporterVisitor *
351 FindLastStoreBRVisitor::createVisitorObject(const ExplodedNode *N,
352                                             const MemRegion *R) {
353   assert(R && "The memory region is null.");
354 
355   ProgramStateRef state = N->getState();
356   SVal V = state->getSVal(R);
357   if (V.isUnknown())
358     return 0;
359 
360   return new FindLastStoreBRVisitor(V, R);
361 }
362 
363 
364 PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
365                                                      const ExplodedNode *PrevN,
366                                                      BugReporterContext &BRC,
367                                                      BugReport &BR) {
368   const PostStmt *P = N->getLocationAs<PostStmt>();
369   if (!P)
370     return 0;
371   const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>();
372   if (!ME)
373     return 0;
374   const Expr *Receiver = ME->getInstanceReceiver();
375   if (!Receiver)
376     return 0;
377   ProgramStateRef state = N->getState();
378   const SVal &V = state->getSVal(Receiver, N->getLocationContext());
379   const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
380   if (!DV)
381     return 0;
382   state = state->assume(*DV, true);
383   if (state)
384     return 0;
385 
386   // The receiver was nil, and hence the method was skipped.
387   // Register a BugReporterVisitor to issue a message telling us how
388   // the receiver was null.
389   BR.addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Receiver));
390   // Issue a message saying that the method was skipped.
391   PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
392                                      N->getLocationContext());
393   return new PathDiagnosticEventPiece(L, "No method actually called "
394       "because the receiver is nil");
395 }
396 
397 // Registers every VarDecl inside a Stmt with a last store visitor.
398 void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
399                                                        const Stmt *S) {
400   const ExplodedNode *N = BR.getErrorNode();
401   std::deque<const Stmt *> WorkList;
402   WorkList.push_back(S);
403 
404   while (!WorkList.empty()) {
405     const Stmt *Head = WorkList.front();
406     WorkList.pop_front();
407 
408     ProgramStateRef state = N->getState();
409     ProgramStateManager &StateMgr = state->getStateManager();
410 
411     if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
412       if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
413         const VarRegion *R =
414         StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
415 
416         // What did we load?
417         SVal V = state->getSVal(S, N->getLocationContext());
418 
419         if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) {
420           // Register a new visitor with the BugReport.
421           BR.addVisitor(new FindLastStoreBRVisitor(V, R));
422         }
423       }
424     }
425 
426     for (Stmt::const_child_iterator I = Head->child_begin();
427         I != Head->child_end(); ++I)
428       WorkList.push_back(*I);
429   }
430 }
431 
432 //===----------------------------------------------------------------------===//
433 // Visitor that tries to report interesting diagnostics from conditions.
434 //===----------------------------------------------------------------------===//
435 PathDiagnosticPiece *ConditionBRVisitor::VisitNode(const ExplodedNode *N,
436                                                    const ExplodedNode *Prev,
437                                                    BugReporterContext &BRC,
438                                                    BugReport &BR) {
439 
440   const ProgramPoint &progPoint = N->getLocation();
441 
442   ProgramStateRef CurrentState = N->getState();
443   ProgramStateRef PrevState = Prev->getState();
444 
445   // Compare the GDMs of the state, because that is where constraints
446   // are managed.  Note that ensure that we only look at nodes that
447   // were generated by the analyzer engine proper, not checkers.
448   if (CurrentState->getGDM().getRoot() ==
449       PrevState->getGDM().getRoot())
450     return 0;
451 
452   // If an assumption was made on a branch, it should be caught
453   // here by looking at the state transition.
454   if (const BlockEdge *BE = dyn_cast<BlockEdge>(&progPoint)) {
455     const CFGBlock *srcBlk = BE->getSrc();
456     if (const Stmt *term = srcBlk->getTerminator())
457       return VisitTerminator(term, N, srcBlk, BE->getDst(), BRC);
458     return 0;
459   }
460 
461   if (const PostStmt *PS = dyn_cast<PostStmt>(&progPoint)) {
462     // FIXME: Assuming that BugReporter is a GRBugReporter is a layering
463     // violation.
464     const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
465       cast<GRBugReporter>(BRC.getBugReporter()).
466         getEngine().getEagerlyAssumeTags();
467 
468     const ProgramPointTag *tag = PS->getTag();
469     if (tag == tags.first)
470       return VisitTrueTest(cast<Expr>(PS->getStmt()), true,
471                            BRC, N->getLocationContext());
472     if (tag == tags.second)
473       return VisitTrueTest(cast<Expr>(PS->getStmt()), false,
474                            BRC, N->getLocationContext());
475 
476     return 0;
477   }
478 
479   return 0;
480 }
481 
482 PathDiagnosticPiece *
483 ConditionBRVisitor::VisitTerminator(const Stmt *Term,
484                                     const ExplodedNode *N,
485                                     const CFGBlock *srcBlk,
486                                     const CFGBlock *dstBlk,
487                                     BugReporterContext &BRC) {
488   const Expr *Cond = 0;
489 
490   switch (Term->getStmtClass()) {
491   default:
492     return 0;
493   case Stmt::IfStmtClass:
494     Cond = cast<IfStmt>(Term)->getCond();
495     break;
496   case Stmt::ConditionalOperatorClass:
497     Cond = cast<ConditionalOperator>(Term)->getCond();
498     break;
499   }
500 
501   assert(Cond);
502   assert(srcBlk->succ_size() == 2);
503   const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk;
504   return VisitTrueTest(Cond->IgnoreParenNoopCasts(BRC.getASTContext()),
505                        tookTrue, BRC, N->getLocationContext());
506 }
507 
508 PathDiagnosticPiece *
509 ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
510                                   bool tookTrue,
511                                   BugReporterContext &BRC,
512                                   const LocationContext *LC) {
513 
514   const Expr *Ex = Cond;
515 
516   while (true) {
517     Ex = Ex->IgnoreParens();
518     switch (Ex->getStmtClass()) {
519       default:
520         return 0;
521       case Stmt::BinaryOperatorClass:
522         return VisitTrueTest(Cond, cast<BinaryOperator>(Ex), tookTrue, BRC, LC);
523       case Stmt::DeclRefExprClass:
524         return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC, LC);
525       case Stmt::UnaryOperatorClass: {
526         const UnaryOperator *UO = cast<UnaryOperator>(Ex);
527         if (UO->getOpcode() == UO_LNot) {
528           tookTrue = !tookTrue;
529           Ex = UO->getSubExpr()->IgnoreParenNoopCasts(BRC.getASTContext());
530           continue;
531         }
532         return 0;
533       }
534     }
535   }
536 }
537 
538 bool ConditionBRVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out,
539                                       BugReporterContext &BRC) {
540   const Expr *OriginalExpr = Ex;
541   Ex = Ex->IgnoreParenCasts();
542 
543   if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
544     const bool quotes = isa<VarDecl>(DR->getDecl());
545     if (quotes)
546       Out << '\'';
547     Out << DR->getDecl()->getDeclName().getAsString();
548     if (quotes)
549       Out << '\'';
550     return quotes;
551   }
552 
553   if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) {
554     QualType OriginalTy = OriginalExpr->getType();
555     if (OriginalTy->isPointerType()) {
556       if (IL->getValue() == 0) {
557         Out << "null";
558         return false;
559       }
560     }
561     else if (OriginalTy->isObjCObjectPointerType()) {
562       if (IL->getValue() == 0) {
563         Out << "nil";
564         return false;
565       }
566     }
567 
568     Out << IL->getValue();
569     return false;
570   }
571 
572   return false;
573 }
574 
575 PathDiagnosticPiece *
576 ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
577                                   const BinaryOperator *BExpr,
578                                   const bool tookTrue,
579                                   BugReporterContext &BRC,
580                                   const LocationContext *LC) {
581 
582   bool shouldInvert = false;
583 
584   SmallString<128> LhsString, RhsString;
585   {
586     llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
587     const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC);
588     const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC);
589 
590     shouldInvert = !isVarLHS && isVarRHS;
591   }
592 
593   BinaryOperator::Opcode Op = BExpr->getOpcode();
594 
595   if (BinaryOperator::isAssignmentOp(Op)) {
596     // For assignment operators, all that we care about is that the LHS
597     // evaluates to "true" or "false".
598     return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue,
599                                   BRC, LC);
600   }
601 
602   // For non-assignment operations, we require that we can understand
603   // both the LHS and RHS.
604   if (LhsString.empty() || RhsString.empty())
605     return 0;
606 
607   // Should we invert the strings if the LHS is not a variable name?
608   SmallString<256> buf;
609   llvm::raw_svector_ostream Out(buf);
610   Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is ";
611 
612   // Do we need to invert the opcode?
613   if (shouldInvert)
614     switch (Op) {
615       default: break;
616       case BO_LT: Op = BO_GT; break;
617       case BO_GT: Op = BO_LT; break;
618       case BO_LE: Op = BO_GE; break;
619       case BO_GE: Op = BO_LE; break;
620     }
621 
622   if (!tookTrue)
623     switch (Op) {
624       case BO_EQ: Op = BO_NE; break;
625       case BO_NE: Op = BO_EQ; break;
626       case BO_LT: Op = BO_GE; break;
627       case BO_GT: Op = BO_LE; break;
628       case BO_LE: Op = BO_GT; break;
629       case BO_GE: Op = BO_LT; break;
630       default:
631         return 0;
632     }
633 
634   switch (Op) {
635     case BO_EQ:
636       Out << "equal to ";
637       break;
638     case BO_NE:
639       Out << "not equal to ";
640       break;
641     default:
642       Out << BinaryOperator::getOpcodeStr(Op) << ' ';
643       break;
644   }
645 
646   Out << (shouldInvert ? LhsString : RhsString);
647 
648   PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LC);
649   return new PathDiagnosticEventPiece(Loc, Out.str());
650 }
651 
652 PathDiagnosticPiece *
653 ConditionBRVisitor::VisitConditionVariable(StringRef LhsString,
654                                            const Expr *CondVarExpr,
655                                            const bool tookTrue,
656                                            BugReporterContext &BRC,
657                                            const LocationContext *LC) {
658   SmallString<256> buf;
659   llvm::raw_svector_ostream Out(buf);
660   Out << "Assuming " << LhsString << " is ";
661 
662   QualType Ty = CondVarExpr->getType();
663 
664   if (Ty->isPointerType())
665     Out << (tookTrue ? "not null" : "null");
666   else if (Ty->isObjCObjectPointerType())
667     Out << (tookTrue ? "not nil" : "nil");
668   else if (Ty->isBooleanType())
669     Out << (tookTrue ? "true" : "false");
670   else if (Ty->isIntegerType())
671     Out << (tookTrue ? "non-zero" : "zero");
672   else
673     return 0;
674 
675   PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LC);
676   return new PathDiagnosticEventPiece(Loc, Out.str());
677 }
678 
679 PathDiagnosticPiece *
680 ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
681                                   const DeclRefExpr *DR,
682                                   const bool tookTrue,
683                                   BugReporterContext &BRC,
684                                   const LocationContext *LC) {
685 
686   const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
687   if (!VD)
688     return 0;
689 
690   SmallString<256> Buf;
691   llvm::raw_svector_ostream Out(Buf);
692 
693   Out << "Assuming '";
694   VD->getDeclName().printName(Out);
695   Out << "' is ";
696 
697   QualType VDTy = VD->getType();
698 
699   if (VDTy->isPointerType())
700     Out << (tookTrue ? "non-null" : "null");
701   else if (VDTy->isObjCObjectPointerType())
702     Out << (tookTrue ? "non-nil" : "nil");
703   else if (VDTy->isScalarType())
704     Out << (tookTrue ? "not equal to 0" : "0");
705   else
706     return 0;
707 
708   PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LC);
709   return new PathDiagnosticEventPiece(Loc, Out.str());
710 }
711 
712 static PathDiagnosticLocation getLastStmtLoc(const ExplodedNode *N,
713                                              const SourceManager &SM) {
714   while (N) {
715     ProgramPoint PP = N->getLocation();
716     if (const StmtPoint *SP = dyn_cast<StmtPoint>(&PP))
717       return PathDiagnosticLocation(SP->getStmt(), SM, PP.getLocationContext());
718     if (N->pred_empty())
719       break;
720     N = *N->pred_begin();
721   }
722   return PathDiagnosticLocation();
723 }
724 
725 PathDiagnosticPiece *
726 CallEnterExitBRVisitor::VisitNode(const ExplodedNode *N,
727                                   const ExplodedNode *PrevN,
728                                   BugReporterContext &BRC,
729                                   BugReport &BR) {
730   ProgramPoint PP = N->getLocation();
731   SmallString<256> buf;
732   llvm::raw_svector_ostream Out(buf);
733   PathDiagnosticLocation pos;
734 
735   if (const CallEnter *CEnter = dyn_cast<CallEnter>(&PP)) {
736     const Decl *callee = CEnter->getCalleeContext()->getDecl();
737     pos = PathDiagnosticLocation(CEnter->getCallExpr(), BRC.getSourceManager(),
738                                  PP.getLocationContext());
739     if (isa<BlockDecl>(callee))
740       Out << "Entering call to block";
741     else if (const NamedDecl *ND = dyn_cast<NamedDecl>(callee))
742       Out << "Entering call to '" << *ND << "'";
743     StringRef msg = Out.str();
744     if (msg.empty())
745       return 0;
746     return new PathDiagnosticCallEnterPiece(pos, msg);
747   }
748   else if (const CallExit *CExit = dyn_cast<CallExit>(&PP)) {
749     const Decl *caller = CExit->getLocationContext()->getParent()->getDecl();
750     pos = getLastStmtLoc(PrevN, BRC.getSourceManager());
751     if (const NamedDecl *ND = dyn_cast<NamedDecl>(caller))
752       Out << "Returning to '" << *ND << "'";
753     else
754       Out << "Returning to caller";
755     return new PathDiagnosticCallExitPiece(pos, Out.str());
756   }
757 
758   return 0;
759 }
760