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