clang API Documentation
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