clang API Documentation

BugReporterVisitors.cpp
Go to the documentation of this file.
00001 // BugReporterVisitors.cpp - Helpers for reporting bugs -----------*- C++ -*--//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file defines a set of BugReporter "visitors" which can be used to
00011 //  enhance the diagnostics reported for a bug.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
00015 
00016 #include "clang/AST/Expr.h"
00017 #include "clang/AST/ExprObjC.h"
00018 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
00019 #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
00020 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
00021 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
00022 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
00023 #include "llvm/ADT/SmallString.h"
00024 
00025 using namespace clang;
00026 using namespace ento;
00027 
00028 //===----------------------------------------------------------------------===//
00029 // Utility functions.
00030 //===----------------------------------------------------------------------===//
00031 
00032 const Stmt *bugreporter::GetDerefExpr(const ExplodedNode *N) {
00033   // Pattern match for a few useful cases (do something smarter later):
00034   //   a[0], p->f, *p
00035   const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
00036 
00037   while (true) {
00038     if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
00039       assert(B->isAssignmentOp());
00040       S = B->getLHS()->IgnoreParenCasts();
00041       continue;
00042     }
00043     else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(S)) {
00044       if (U->getOpcode() == UO_Deref)
00045         return U->getSubExpr()->IgnoreParenCasts();
00046     }
00047     else if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) {
00048       return ME->getBase()->IgnoreParenCasts();
00049     }
00050     else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(S)) {
00051       return AE->getBase();
00052     }
00053     break;
00054   }
00055 
00056   return NULL;
00057 }
00058 
00059 const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) {
00060   const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
00061   if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S))
00062     return BE->getRHS();
00063   return NULL;
00064 }
00065 
00066 const Stmt *bugreporter::GetCalleeExpr(const ExplodedNode *N) {
00067   // Callee is checked as a PreVisit to the CallExpr.
00068   const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
00069   if (const CallExpr *CE = dyn_cast<CallExpr>(S))
00070     return CE->getCallee();
00071   return NULL;
00072 }
00073 
00074 const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) {
00075   const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
00076   if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S))
00077     return RS->getRetValue();
00078   return NULL;
00079 }
00080 
00081 //===----------------------------------------------------------------------===//
00082 // Definitions for bug reporter visitors.
00083 //===----------------------------------------------------------------------===//
00084 
00085 PathDiagnosticPiece*
00086 BugReporterVisitor::getEndPath(BugReporterContext &BRC,
00087                                const ExplodedNode *EndPathNode,
00088                                BugReport &BR) {
00089   return 0;
00090 }
00091 
00092 PathDiagnosticPiece*
00093 BugReporterVisitor::getDefaultEndPath(BugReporterContext &BRC,
00094                                       const ExplodedNode *EndPathNode,
00095                                       BugReport &BR) {
00096   PathDiagnosticLocation L =
00097     PathDiagnosticLocation::createEndOfPath(EndPathNode,BRC.getSourceManager());
00098 
00099   BugReport::ranges_iterator Beg, End;
00100   llvm::tie(Beg, End) = BR.getRanges();
00101 
00102   // Only add the statement itself as a range if we didn't specify any
00103   // special ranges for this report.
00104   PathDiagnosticPiece *P = new PathDiagnosticEventPiece(L,
00105       BR.getDescription(),
00106       Beg == End);
00107   for (; Beg != End; ++Beg)
00108     P->addRange(*Beg);
00109 
00110   return P;
00111 }
00112 
00113 
00114 void FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const {
00115   static int tag = 0;
00116   ID.AddPointer(&tag);
00117   ID.AddPointer(R);
00118   ID.Add(V);
00119 }
00120 
00121 PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *N,
00122                                                      const ExplodedNode *PrevN,
00123                                                      BugReporterContext &BRC,
00124                                                      BugReport &BR) {
00125 
00126   if (satisfied)
00127     return NULL;
00128 
00129   if (!StoreSite) {
00130     const ExplodedNode *Node = N, *Last = NULL;
00131 
00132     for ( ; Node ; Node = Node->getFirstPred()) {
00133 
00134       if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
00135         if (const PostStmt *P = Node->getLocationAs<PostStmt>())
00136           if (const DeclStmt *DS = P->getStmtAs<DeclStmt>())
00137             if (DS->getSingleDecl() == VR->getDecl()) {
00138               // Record the last seen initialization point.
00139               Last = Node;
00140               break;
00141             }
00142       }
00143 
00144       // Does the region still bind to value V?  If not, we are done
00145       // looking for store sites.
00146       if (Node->getState()->getSVal(R) != V)
00147         break;
00148     }
00149 
00150     if (!Node || !Last) {
00151       satisfied = true;
00152       return NULL;
00153     }
00154 
00155     StoreSite = Last;
00156   }
00157 
00158   if (StoreSite != N)
00159     return NULL;
00160 
00161   satisfied = true;
00162   SmallString<256> sbuf;
00163   llvm::raw_svector_ostream os(sbuf);
00164 
00165   if (const PostStmt *PS = N->getLocationAs<PostStmt>()) {
00166     if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) {
00167 
00168       if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
00169         os << "Variable '" << *VR->getDecl() << "' ";
00170       }
00171       else
00172         return NULL;
00173 
00174       if (isa<loc::ConcreteInt>(V)) {
00175         bool b = false;
00176         if (R->isBoundable()) {
00177           if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
00178             if (TR->getValueType()->isObjCObjectPointerType()) {
00179               os << "initialized to nil";
00180               b = true;
00181             }
00182           }
00183         }
00184 
00185         if (!b)
00186           os << "initialized to a null pointer value";
00187       }
00188       else if (isa<nonloc::ConcreteInt>(V)) {
00189         os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue();
00190       }
00191       else if (V.isUndef()) {
00192         if (isa<VarRegion>(R)) {
00193           const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
00194           if (VD->getInit())
00195             os << "initialized to a garbage value";
00196           else
00197             os << "declared without an initial value";
00198         }
00199       }
00200     }
00201   }
00202 
00203   if (os.str().empty()) {
00204     if (isa<loc::ConcreteInt>(V)) {
00205       bool b = false;
00206       if (R->isBoundable()) {
00207         if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
00208           if (TR->getValueType()->isObjCObjectPointerType()) {
00209             os << "nil object reference stored to ";
00210             b = true;
00211           }
00212         }
00213       }
00214 
00215       if (!b)
00216         os << "Null pointer value stored to ";
00217     }
00218     else if (V.isUndef()) {
00219       os << "Uninitialized value stored to ";
00220     }
00221     else if (isa<nonloc::ConcreteInt>(V)) {
00222       os << "The value " << cast<nonloc::ConcreteInt>(V).getValue()
00223                << " is assigned to ";
00224     }
00225     else
00226       return NULL;
00227 
00228     if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
00229       os << '\'' << *VR->getDecl() << '\'';
00230     }
00231     else
00232       return NULL;
00233   }
00234 
00235   // Construct a new PathDiagnosticPiece.
00236   ProgramPoint P = N->getLocation();
00237   PathDiagnosticLocation L =
00238     PathDiagnosticLocation::create(P, BRC.getSourceManager());
00239   if (!L.isValid())
00240     return NULL;
00241   return new PathDiagnosticEventPiece(L, os.str());
00242 }
00243 
00244 void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
00245   static int tag = 0;
00246   ID.AddPointer(&tag);
00247   ID.AddBoolean(Assumption);
00248   ID.Add(Constraint);
00249 }
00250 
00251 PathDiagnosticPiece *
00252 TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
00253                                     const ExplodedNode *PrevN,
00254                                     BugReporterContext &BRC,
00255                                     BugReport &BR) {
00256   if (isSatisfied)
00257     return NULL;
00258 
00259   // Check if in the previous state it was feasible for this constraint
00260   // to *not* be true.
00261   if (PrevN->getState()->assume(Constraint, !Assumption)) {
00262 
00263     isSatisfied = true;
00264 
00265     // As a sanity check, make sure that the negation of the constraint
00266     // was infeasible in the current state.  If it is feasible, we somehow
00267     // missed the transition point.
00268     if (N->getState()->assume(Constraint, !Assumption))
00269       return NULL;
00270 
00271     // We found the transition point for the constraint.  We now need to
00272     // pretty-print the constraint. (work-in-progress)
00273     std::string sbuf;
00274     llvm::raw_string_ostream os(sbuf);
00275 
00276     if (isa<Loc>(Constraint)) {
00277       os << "Assuming pointer value is ";
00278       os << (Assumption ? "non-null" : "null");
00279     }
00280 
00281     if (os.str().empty())
00282       return NULL;
00283 
00284     // Construct a new PathDiagnosticPiece.
00285     ProgramPoint P = N->getLocation();
00286     PathDiagnosticLocation L =
00287       PathDiagnosticLocation::create(P, BRC.getSourceManager());
00288     if (!L.isValid())
00289       return NULL;
00290     return new PathDiagnosticEventPiece(L, os.str());
00291   }
00292 
00293   return NULL;
00294 }
00295 
00296 BugReporterVisitor *
00297 bugreporter::getTrackNullOrUndefValueVisitor(const ExplodedNode *N,
00298                                              const Stmt *S,
00299                                              BugReport *report) {
00300   if (!S || !N)
00301     return 0;
00302 
00303   ProgramStateManager &StateMgr = N->getState()->getStateManager();
00304 
00305   // Walk through nodes until we get one that matches the statement
00306   // exactly.
00307   while (N) {
00308     const ProgramPoint &pp = N->getLocation();
00309     if (const PostStmt *ps = dyn_cast<PostStmt>(&pp)) {
00310       if (ps->getStmt() == S)
00311         break;
00312     }
00313     N = N->getFirstPred();
00314   }
00315 
00316   if (!N)
00317     return 0;
00318   
00319   ProgramStateRef state = N->getState();
00320 
00321   // Walk through lvalue-to-rvalue conversions.
00322   const Expr *Ex = dyn_cast<Expr>(S);
00323   if (Ex) {
00324     Ex = Ex->IgnoreParenLValueCasts();
00325     if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
00326       if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
00327         const VarRegion *R =
00328           StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
00329 
00330         // What did we load?
00331         SVal V = state->getRawSVal(loc::MemRegionVal(R));
00332         report->markInteresting(R);
00333         report->markInteresting(V);
00334         return new FindLastStoreBRVisitor(V, R);
00335       }
00336     }
00337   }
00338 
00339   SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext());
00340 
00341   // Uncomment this to find cases where we aren't properly getting the
00342   // base value that was dereferenced.
00343   // assert(!V.isUnknownOrUndef());
00344 
00345   // Is it a symbolic value?
00346   if (loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&V)) {
00347     const SubRegion *R = cast<SubRegion>(L->getRegion());
00348     while (R && !isa<SymbolicRegion>(R)) {
00349       R = dyn_cast<SubRegion>(R->getSuperRegion());
00350     }
00351 
00352     if (R) {
00353       report->markInteresting(R);
00354       return new TrackConstraintBRVisitor(loc::MemRegionVal(R), false);
00355     }
00356   }
00357 
00358   return 0;
00359 }
00360 
00361 BugReporterVisitor *
00362 FindLastStoreBRVisitor::createVisitorObject(const ExplodedNode *N,
00363                                             const MemRegion *R) {
00364   assert(R && "The memory region is null.");
00365 
00366   ProgramStateRef state = N->getState();
00367   SVal V = state->getSVal(R);
00368   if (V.isUnknown())
00369     return 0;
00370 
00371   return new FindLastStoreBRVisitor(V, R);
00372 }
00373 
00374 
00375 PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
00376                                                      const ExplodedNode *PrevN,
00377                                                      BugReporterContext &BRC,
00378                                                      BugReport &BR) {
00379   const PostStmt *P = N->getLocationAs<PostStmt>();
00380   if (!P)
00381     return 0;
00382   const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>();
00383   if (!ME)
00384     return 0;
00385   const Expr *Receiver = ME->getInstanceReceiver();
00386   if (!Receiver)
00387     return 0;
00388   ProgramStateRef state = N->getState();
00389   const SVal &V = state->getSVal(Receiver, N->getLocationContext());
00390   const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
00391   if (!DV)
00392     return 0;
00393   state = state->assume(*DV, true);
00394   if (state)
00395     return 0;
00396 
00397   // The receiver was nil, and hence the method was skipped.
00398   // Register a BugReporterVisitor to issue a message telling us how
00399   // the receiver was null.
00400   BR.addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Receiver, &BR));
00401   // Issue a message saying that the method was skipped.
00402   PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
00403                                      N->getLocationContext());
00404   return new PathDiagnosticEventPiece(L, "No method is called "
00405       "because the receiver is nil");
00406 }
00407 
00408 // Registers every VarDecl inside a Stmt with a last store visitor.
00409 void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
00410                                                        const Stmt *S) {
00411   const ExplodedNode *N = BR.getErrorNode();
00412   std::deque<const Stmt *> WorkList;
00413   WorkList.push_back(S);
00414 
00415   while (!WorkList.empty()) {
00416     const Stmt *Head = WorkList.front();
00417     WorkList.pop_front();
00418 
00419     ProgramStateRef state = N->getState();
00420     ProgramStateManager &StateMgr = state->getStateManager();
00421 
00422     if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
00423       if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
00424         const VarRegion *R =
00425         StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
00426 
00427         // What did we load?
00428         SVal V = state->getSVal(S, N->getLocationContext());
00429 
00430         if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) {
00431           // Register a new visitor with the BugReport.
00432           BR.addVisitor(new FindLastStoreBRVisitor(V, R));
00433         }
00434       }
00435     }
00436 
00437     for (Stmt::const_child_iterator I = Head->child_begin();
00438         I != Head->child_end(); ++I)
00439       WorkList.push_back(*I);
00440   }
00441 }
00442 
00443 //===----------------------------------------------------------------------===//
00444 // Visitor that tries to report interesting diagnostics from conditions.
00445 //===----------------------------------------------------------------------===//
00446 PathDiagnosticPiece *ConditionBRVisitor::VisitNode(const ExplodedNode *N,
00447                                                    const ExplodedNode *Prev,
00448                                                    BugReporterContext &BRC,
00449                                                    BugReport &BR) {
00450   PathDiagnosticPiece *piece = VisitNodeImpl(N, Prev, BRC, BR);
00451   if (PathDiagnosticEventPiece *ev =
00452       dyn_cast_or_null<PathDiagnosticEventPiece>(piece))
00453     ev->setPrunable(true, /* override */ false);
00454   return piece;
00455 }
00456 
00457 PathDiagnosticPiece *ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
00458                                                        const ExplodedNode *Prev,
00459                                                        BugReporterContext &BRC,
00460                                                        BugReport &BR) {
00461   
00462   const ProgramPoint &progPoint = N->getLocation();
00463 
00464   ProgramStateRef CurrentState = N->getState();
00465   ProgramStateRef PrevState = Prev->getState();
00466   
00467   // Compare the GDMs of the state, because that is where constraints
00468   // are managed.  Note that ensure that we only look at nodes that
00469   // were generated by the analyzer engine proper, not checkers.
00470   if (CurrentState->getGDM().getRoot() ==
00471       PrevState->getGDM().getRoot())
00472     return 0;
00473   
00474   // If an assumption was made on a branch, it should be caught
00475   // here by looking at the state transition.
00476   if (const BlockEdge *BE = dyn_cast<BlockEdge>(&progPoint)) {
00477     const CFGBlock *srcBlk = BE->getSrc();    
00478     if (const Stmt *term = srcBlk->getTerminator())
00479       return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC);
00480     return 0;
00481   }
00482   
00483   if (const PostStmt *PS = dyn_cast<PostStmt>(&progPoint)) {
00484     // FIXME: Assuming that BugReporter is a GRBugReporter is a layering
00485     // violation.
00486     const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =      
00487       cast<GRBugReporter>(BRC.getBugReporter()).
00488         getEngine().getEagerlyAssumeTags();
00489 
00490     const ProgramPointTag *tag = PS->getTag();
00491     if (tag == tags.first)
00492       return VisitTrueTest(cast<Expr>(PS->getStmt()), true,
00493                            BRC, BR, N);
00494     if (tag == tags.second)
00495       return VisitTrueTest(cast<Expr>(PS->getStmt()), false,
00496                            BRC, BR, N);
00497                            
00498     return 0;
00499   }
00500     
00501   return 0;
00502 }
00503 
00504 PathDiagnosticPiece *
00505 ConditionBRVisitor::VisitTerminator(const Stmt *Term,
00506                                     const ExplodedNode *N,
00507                                     const CFGBlock *srcBlk,
00508                                     const CFGBlock *dstBlk,
00509                                     BugReport &R,
00510                                     BugReporterContext &BRC) {
00511   const Expr *Cond = 0;
00512   
00513   switch (Term->getStmtClass()) {
00514   default:
00515     return 0;
00516   case Stmt::IfStmtClass:
00517     Cond = cast<IfStmt>(Term)->getCond();
00518     break;
00519   case Stmt::ConditionalOperatorClass:
00520     Cond = cast<ConditionalOperator>(Term)->getCond();
00521     break;
00522   }      
00523 
00524   assert(Cond);
00525   assert(srcBlk->succ_size() == 2);
00526   const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk;
00527   return VisitTrueTest(Cond->IgnoreParenNoopCasts(BRC.getASTContext()),
00528                        tookTrue, BRC, R, N);
00529 }
00530 
00531 PathDiagnosticPiece *
00532 ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
00533                                   bool tookTrue,
00534                                   BugReporterContext &BRC,
00535                                   BugReport &R,
00536                                   const ExplodedNode *N) {
00537   
00538   const Expr *Ex = Cond;
00539   
00540   while (true) {
00541     Ex = Ex->IgnoreParens();
00542     switch (Ex->getStmtClass()) {
00543       default:
00544         return 0;
00545       case Stmt::BinaryOperatorClass:
00546         return VisitTrueTest(Cond, cast<BinaryOperator>(Ex), tookTrue, BRC,
00547                              R, N);
00548       case Stmt::DeclRefExprClass:
00549         return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC,
00550                              R, N);
00551       case Stmt::UnaryOperatorClass: {
00552         const UnaryOperator *UO = cast<UnaryOperator>(Ex);
00553         if (UO->getOpcode() == UO_LNot) {
00554           tookTrue = !tookTrue;
00555           Ex = UO->getSubExpr()->IgnoreParenNoopCasts(BRC.getASTContext());
00556           continue;
00557         }
00558         return 0;
00559       }
00560     }
00561   }
00562 }
00563 
00564 bool ConditionBRVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out,
00565                                       BugReporterContext &BRC,
00566                                       BugReport &report,
00567                                       const ExplodedNode *N,
00568                                       llvm::Optional<bool> &prunable) {
00569   const Expr *OriginalExpr = Ex;
00570   Ex = Ex->IgnoreParenCasts();
00571 
00572   if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
00573     const bool quotes = isa<VarDecl>(DR->getDecl());
00574     if (quotes) {
00575       Out << '\'';
00576       const LocationContext *LCtx = N->getLocationContext();
00577       const ProgramState *state = N->getState().getPtr();
00578       if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
00579                                                 LCtx).getAsRegion()) {
00580         if (report.isInteresting(R))
00581           prunable = false;
00582         else {
00583           const ProgramState *state = N->getState().getPtr();
00584           SVal V = state->getSVal(R);
00585           if (report.isInteresting(V))
00586             prunable = false;
00587         }
00588       }
00589     }
00590     Out << DR->getDecl()->getDeclName().getAsString();
00591     if (quotes)
00592       Out << '\'';
00593     return quotes;
00594   }
00595   
00596   if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) {
00597     QualType OriginalTy = OriginalExpr->getType();
00598     if (OriginalTy->isPointerType()) {
00599       if (IL->getValue() == 0) {
00600         Out << "null";
00601         return false;
00602       }
00603     }
00604     else if (OriginalTy->isObjCObjectPointerType()) {
00605       if (IL->getValue() == 0) {
00606         Out << "nil";
00607         return false;
00608       }
00609     }
00610     
00611     Out << IL->getValue();
00612     return false;
00613   }
00614   
00615   return false;
00616 }
00617 
00618 PathDiagnosticPiece *
00619 ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
00620                                   const BinaryOperator *BExpr,
00621                                   const bool tookTrue,
00622                                   BugReporterContext &BRC,
00623                                   BugReport &R,
00624                                   const ExplodedNode *N) {
00625   
00626   bool shouldInvert = false;
00627   llvm::Optional<bool> shouldPrune;
00628   
00629   SmallString<128> LhsString, RhsString;
00630   {
00631     llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
00632     const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC, R, N,
00633                                        shouldPrune);
00634     const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC, R, N,
00635                                        shouldPrune);
00636     
00637     shouldInvert = !isVarLHS && isVarRHS;    
00638   }
00639   
00640   BinaryOperator::Opcode Op = BExpr->getOpcode();
00641 
00642   if (BinaryOperator::isAssignmentOp(Op)) {
00643     // For assignment operators, all that we care about is that the LHS
00644     // evaluates to "true" or "false".
00645     return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue,
00646                                   BRC, R, N);
00647   }
00648 
00649   // For non-assignment operations, we require that we can understand
00650   // both the LHS and RHS.
00651   if (LhsString.empty() || RhsString.empty())
00652     return 0;
00653   
00654   // Should we invert the strings if the LHS is not a variable name?
00655   SmallString<256> buf;
00656   llvm::raw_svector_ostream Out(buf);
00657   Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is ";
00658 
00659   // Do we need to invert the opcode?
00660   if (shouldInvert)
00661     switch (Op) {
00662       default: break;
00663       case BO_LT: Op = BO_GT; break;
00664       case BO_GT: Op = BO_LT; break;
00665       case BO_LE: Op = BO_GE; break;
00666       case BO_GE: Op = BO_LE; break;
00667     }
00668 
00669   if (!tookTrue)
00670     switch (Op) {
00671       case BO_EQ: Op = BO_NE; break;
00672       case BO_NE: Op = BO_EQ; break;
00673       case BO_LT: Op = BO_GE; break;
00674       case BO_GT: Op = BO_LE; break;
00675       case BO_LE: Op = BO_GT; break;
00676       case BO_GE: Op = BO_LT; break;
00677       default:
00678         return 0;
00679     }
00680   
00681   switch (Op) {
00682     case BO_EQ:
00683       Out << "equal to ";
00684       break;
00685     case BO_NE:
00686       Out << "not equal to ";
00687       break;
00688     default:
00689       Out << BinaryOperator::getOpcodeStr(Op) << ' ';
00690       break;
00691   }
00692   
00693   Out << (shouldInvert ? LhsString : RhsString);
00694   const LocationContext *LCtx = N->getLocationContext();
00695   PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
00696   PathDiagnosticEventPiece *event =
00697     new PathDiagnosticEventPiece(Loc, Out.str());
00698   if (shouldPrune.hasValue())
00699     event->setPrunable(shouldPrune.getValue());
00700   return event;
00701 }
00702 
00703 PathDiagnosticPiece *
00704 ConditionBRVisitor::VisitConditionVariable(StringRef LhsString,
00705                                            const Expr *CondVarExpr,
00706                                            const bool tookTrue,
00707                                            BugReporterContext &BRC,
00708                                            BugReport &report,
00709                                            const ExplodedNode *N) {
00710   SmallString<256> buf;
00711   llvm::raw_svector_ostream Out(buf);
00712   Out << "Assuming " << LhsString << " is ";
00713   
00714   QualType Ty = CondVarExpr->getType();
00715 
00716   if (Ty->isPointerType())
00717     Out << (tookTrue ? "not null" : "null");
00718   else if (Ty->isObjCObjectPointerType())
00719     Out << (tookTrue ? "not nil" : "nil");
00720   else if (Ty->isBooleanType())
00721     Out << (tookTrue ? "true" : "false");
00722   else if (Ty->isIntegerType())
00723     Out << (tookTrue ? "non-zero" : "zero");
00724   else
00725     return 0;
00726 
00727   const LocationContext *LCtx = N->getLocationContext();
00728   PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
00729   PathDiagnosticEventPiece *event =
00730     new PathDiagnosticEventPiece(Loc, Out.str());
00731 
00732   if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
00733     if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
00734       const ProgramState *state = N->getState().getPtr();
00735       if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
00736         if (report.isInteresting(R))
00737           event->setPrunable(false);
00738       }
00739     }
00740   }
00741   
00742   return event;
00743 }
00744   
00745 PathDiagnosticPiece *
00746 ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
00747                                   const DeclRefExpr *DR,
00748                                   const bool tookTrue,
00749                                   BugReporterContext &BRC,
00750                                   BugReport &report,
00751                                   const ExplodedNode *N) {
00752 
00753   const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
00754   if (!VD)
00755     return 0;
00756   
00757   SmallString<256> Buf;
00758   llvm::raw_svector_ostream Out(Buf);
00759     
00760   Out << "Assuming '";
00761   VD->getDeclName().printName(Out);
00762   Out << "' is ";
00763     
00764   QualType VDTy = VD->getType();
00765   
00766   if (VDTy->isPointerType())
00767     Out << (tookTrue ? "non-null" : "null");
00768   else if (VDTy->isObjCObjectPointerType())
00769     Out << (tookTrue ? "non-nil" : "nil");
00770   else if (VDTy->isScalarType())
00771     Out << (tookTrue ? "not equal to 0" : "0");
00772   else
00773     return 0;
00774   
00775   const LocationContext *LCtx = N->getLocationContext();
00776   PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
00777   PathDiagnosticEventPiece *event =
00778     new PathDiagnosticEventPiece(Loc, Out.str());
00779   
00780   const ProgramState *state = N->getState().getPtr();
00781   if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
00782     if (report.isInteresting(R))
00783       event->setPrunable(false);
00784     else {
00785       SVal V = state->getSVal(R);
00786       if (report.isInteresting(V))
00787         event->setPrunable(false);
00788     }
00789   }
00790   return event;
00791 }
00792