Home | History | Annotate | Download | only in Core
      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 
    785