BugReporterVisitors.cpp revision f7ccbad5d9949e7ddd1cbef43d482553b811e026
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 25using namespace clang; 26using namespace ento; 27 28//===----------------------------------------------------------------------===// 29// Utility functions. 30//===----------------------------------------------------------------------===// 31 32const 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 51const 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 58const 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 66const 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 77PathDiagnosticPiece* 78BugReporterVisitor::getEndPath(BugReporterContext &BRC, 79 const ExplodedNode *EndPathNode, 80 BugReport &BR) { 81 return 0; 82} 83 84PathDiagnosticPiece* 85BugReporterVisitor::getDefaultEndPath(BugReporterContext &BRC, 86 const ExplodedNode *EndPathNode, 87 BugReport &BR) { 88 const ProgramPoint &PP = EndPathNode->getLocation(); 89 PathDiagnosticLocation L; 90 91 if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&PP)) { 92 const CFGBlock *block = BE->getBlock(); 93 if (block->getBlockID() == 0) { 94 L = PathDiagnosticLocation::createDeclEnd(PP.getLocationContext(), 95 BRC.getSourceManager()); 96 } 97 } 98 99 if (!L.isValid()) { 100 const Stmt *S = BR.getStmt(); 101 102 if (!S) 103 return NULL; 104 105 L = PathDiagnosticLocation(S, BRC.getSourceManager(), 106 PP.getLocationContext()); 107 } 108 109 BugReport::ranges_iterator Beg, End; 110 llvm::tie(Beg, End) = BR.getRanges(); 111 112 // Only add the statement itself as a range if we didn't specify any 113 // special ranges for this report. 114 PathDiagnosticPiece *P = new PathDiagnosticEventPiece(L, 115 BR.getDescription(), 116 Beg == End); 117 for (; Beg != End; ++Beg) 118 P->addRange(*Beg); 119 120 return P; 121} 122 123 124void FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const { 125 static int tag = 0; 126 ID.AddPointer(&tag); 127 ID.AddPointer(R); 128 ID.Add(V); 129} 130 131PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *N, 132 const ExplodedNode *PrevN, 133 BugReporterContext &BRC, 134 BugReport &BR) { 135 136 if (satisfied) 137 return NULL; 138 139 if (!StoreSite) { 140 const ExplodedNode *Node = N, *Last = NULL; 141 142 for ( ; Node ; Node = Node->getFirstPred()) { 143 144 if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 145 if (const PostStmt *P = Node->getLocationAs<PostStmt>()) 146 if (const DeclStmt *DS = P->getStmtAs<DeclStmt>()) 147 if (DS->getSingleDecl() == VR->getDecl()) { 148 // Record the last seen initialization point. 149 Last = Node; 150 break; 151 } 152 } 153 154 // Does the region still bind to value V? If not, we are done 155 // looking for store sites. 156 if (Node->getState()->getSVal(R) != V) 157 break; 158 } 159 160 if (!Node || !Last) { 161 satisfied = true; 162 return NULL; 163 } 164 165 StoreSite = Last; 166 } 167 168 if (StoreSite != N) 169 return NULL; 170 171 satisfied = true; 172 SmallString<256> sbuf; 173 llvm::raw_svector_ostream os(sbuf); 174 175 if (const PostStmt *PS = N->getLocationAs<PostStmt>()) { 176 if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) { 177 178 if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 179 os << "Variable '" << *VR->getDecl() << "' "; 180 } 181 else 182 return NULL; 183 184 if (isa<loc::ConcreteInt>(V)) { 185 bool b = false; 186 if (R->isBoundable()) { 187 if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 188 if (TR->getValueType()->isObjCObjectPointerType()) { 189 os << "initialized to nil"; 190 b = true; 191 } 192 } 193 } 194 195 if (!b) 196 os << "initialized to a null pointer value"; 197 } 198 else if (isa<nonloc::ConcreteInt>(V)) { 199 os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue(); 200 } 201 else if (V.isUndef()) { 202 if (isa<VarRegion>(R)) { 203 const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); 204 if (VD->getInit()) 205 os << "initialized to a garbage value"; 206 else 207 os << "declared without an initial value"; 208 } 209 } 210 } 211 } 212 213 if (os.str().empty()) { 214 if (isa<loc::ConcreteInt>(V)) { 215 bool b = false; 216 if (R->isBoundable()) { 217 if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 218 if (TR->getValueType()->isObjCObjectPointerType()) { 219 os << "nil object reference stored to "; 220 b = true; 221 } 222 } 223 } 224 225 if (!b) 226 os << "Null pointer value stored to "; 227 } 228 else if (V.isUndef()) { 229 os << "Uninitialized value stored to "; 230 } 231 else if (isa<nonloc::ConcreteInt>(V)) { 232 os << "The value " << cast<nonloc::ConcreteInt>(V).getValue() 233 << " is assigned to "; 234 } 235 else 236 return NULL; 237 238 if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 239 os << '\'' << *VR->getDecl() << '\''; 240 } 241 else 242 return NULL; 243 } 244 245 // Construct a new PathDiagnosticPiece. 246 ProgramPoint P = N->getLocation(); 247 PathDiagnosticLocation L = 248 PathDiagnosticLocation::create(P, BRC.getSourceManager()); 249 if (!L.isValid()) 250 return NULL; 251 return new PathDiagnosticEventPiece(L, os.str()); 252} 253 254void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const { 255 static int tag = 0; 256 ID.AddPointer(&tag); 257 ID.AddBoolean(Assumption); 258 ID.Add(Constraint); 259} 260 261PathDiagnosticPiece * 262TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N, 263 const ExplodedNode *PrevN, 264 BugReporterContext &BRC, 265 BugReport &BR) { 266 if (isSatisfied) 267 return NULL; 268 269 // Check if in the previous state it was feasible for this constraint 270 // to *not* be true. 271 if (PrevN->getState()->assume(Constraint, !Assumption)) { 272 273 isSatisfied = true; 274 275 // As a sanity check, make sure that the negation of the constraint 276 // was infeasible in the current state. If it is feasible, we somehow 277 // missed the transition point. 278 if (N->getState()->assume(Constraint, !Assumption)) 279 return NULL; 280 281 // We found the transition point for the constraint. We now need to 282 // pretty-print the constraint. (work-in-progress) 283 std::string sbuf; 284 llvm::raw_string_ostream os(sbuf); 285 286 if (isa<Loc>(Constraint)) { 287 os << "Assuming pointer value is "; 288 os << (Assumption ? "non-null" : "null"); 289 } 290 291 if (os.str().empty()) 292 return NULL; 293 294 // Construct a new PathDiagnosticPiece. 295 ProgramPoint P = N->getLocation(); 296 PathDiagnosticLocation L = 297 PathDiagnosticLocation::create(P, BRC.getSourceManager()); 298 if (!L.isValid()) 299 return NULL; 300 return new PathDiagnosticEventPiece(L, os.str()); 301 } 302 303 return NULL; 304} 305 306BugReporterVisitor * 307bugreporter::getTrackNullOrUndefValueVisitor(const ExplodedNode *N, 308 const Stmt *S) { 309 if (!S || !N) 310 return 0; 311 312 ProgramStateManager &StateMgr = N->getState()->getStateManager(); 313 314 // Walk through nodes until we get one that matches the statement 315 // exactly. 316 while (N) { 317 const ProgramPoint &pp = N->getLocation(); 318 if (const PostStmt *ps = dyn_cast<PostStmt>(&pp)) { 319 if (ps->getStmt() == S) 320 break; 321 } 322 N = N->getFirstPred(); 323 } 324 325 if (!N) 326 return 0; 327 328 ProgramStateRef state = N->getState(); 329 330 // Walk through lvalue-to-rvalue conversions. 331 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S)) { 332 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 333 const VarRegion *R = 334 StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext()); 335 336 // What did we load? 337 SVal V = state->getSVal(loc::MemRegionVal(R)); 338 339 if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V) 340 || V.isUndef()) { 341 return new FindLastStoreBRVisitor(V, R); 342 } 343 } 344 } 345 346 SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext()); 347 348 // Uncomment this to find cases where we aren't properly getting the 349 // base value that was dereferenced. 350 // assert(!V.isUnknownOrUndef()); 351 352 // Is it a symbolic value? 353 if (loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&V)) { 354 const SubRegion *R = cast<SubRegion>(L->getRegion()); 355 while (R && !isa<SymbolicRegion>(R)) { 356 R = dyn_cast<SubRegion>(R->getSuperRegion()); 357 } 358 359 if (R) { 360 assert(isa<SymbolicRegion>(R)); 361 return new TrackConstraintBRVisitor(loc::MemRegionVal(R), false); 362 } 363 } 364 365 return 0; 366} 367 368BugReporterVisitor * 369FindLastStoreBRVisitor::createVisitorObject(const ExplodedNode *N, 370 const MemRegion *R) { 371 assert(R && "The memory region is null."); 372 373 ProgramStateRef state = N->getState(); 374 SVal V = state->getSVal(R); 375 if (V.isUnknown()) 376 return 0; 377 378 return new FindLastStoreBRVisitor(V, R); 379} 380 381 382PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N, 383 const ExplodedNode *PrevN, 384 BugReporterContext &BRC, 385 BugReport &BR) { 386 const PostStmt *P = N->getLocationAs<PostStmt>(); 387 if (!P) 388 return 0; 389 const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>(); 390 if (!ME) 391 return 0; 392 const Expr *Receiver = ME->getInstanceReceiver(); 393 if (!Receiver) 394 return 0; 395 ProgramStateRef state = N->getState(); 396 const SVal &V = state->getSVal(Receiver, N->getLocationContext()); 397 const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V); 398 if (!DV) 399 return 0; 400 state = state->assume(*DV, true); 401 if (state) 402 return 0; 403 404 // The receiver was nil, and hence the method was skipped. 405 // Register a BugReporterVisitor to issue a message telling us how 406 // the receiver was null. 407 BR.addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Receiver)); 408 // Issue a message saying that the method was skipped. 409 PathDiagnosticLocation L(Receiver, BRC.getSourceManager(), 410 N->getLocationContext()); 411 return new PathDiagnosticEventPiece(L, "No method actually called " 412 "because the receiver is nil"); 413} 414 415// Registers every VarDecl inside a Stmt with a last store visitor. 416void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR, 417 const Stmt *S) { 418 const ExplodedNode *N = BR.getErrorNode(); 419 std::deque<const Stmt *> WorkList; 420 WorkList.push_back(S); 421 422 while (!WorkList.empty()) { 423 const Stmt *Head = WorkList.front(); 424 WorkList.pop_front(); 425 426 ProgramStateRef state = N->getState(); 427 ProgramStateManager &StateMgr = state->getStateManager(); 428 429 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) { 430 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 431 const VarRegion *R = 432 StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext()); 433 434 // What did we load? 435 SVal V = state->getSVal(S, N->getLocationContext()); 436 437 if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) { 438 // Register a new visitor with the BugReport. 439 BR.addVisitor(new FindLastStoreBRVisitor(V, R)); 440 } 441 } 442 } 443 444 for (Stmt::const_child_iterator I = Head->child_begin(); 445 I != Head->child_end(); ++I) 446 WorkList.push_back(*I); 447 } 448} 449 450//===----------------------------------------------------------------------===// 451// Visitor that tries to report interesting diagnostics from conditions. 452//===----------------------------------------------------------------------===// 453PathDiagnosticPiece *ConditionBRVisitor::VisitNode(const ExplodedNode *N, 454 const ExplodedNode *Prev, 455 BugReporterContext &BRC, 456 BugReport &BR) { 457 458 const ProgramPoint &progPoint = N->getLocation(); 459 460 ProgramStateRef CurrentState = N->getState(); 461 ProgramStateRef PrevState = Prev->getState(); 462 463 // Compare the GDMs of the state, because that is where constraints 464 // are managed. Note that ensure that we only look at nodes that 465 // were generated by the analyzer engine proper, not checkers. 466 if (CurrentState->getGDM().getRoot() == 467 PrevState->getGDM().getRoot()) 468 return 0; 469 470 // If an assumption was made on a branch, it should be caught 471 // here by looking at the state transition. 472 if (const BlockEdge *BE = dyn_cast<BlockEdge>(&progPoint)) { 473 const CFGBlock *srcBlk = BE->getSrc(); 474 if (const Stmt *term = srcBlk->getTerminator()) 475 return VisitTerminator(term, N, srcBlk, BE->getDst(), BRC); 476 return 0; 477 } 478 479 if (const PostStmt *PS = dyn_cast<PostStmt>(&progPoint)) { 480 // FIXME: Assuming that BugReporter is a GRBugReporter is a layering 481 // violation. 482 const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags = 483 cast<GRBugReporter>(BRC.getBugReporter()). 484 getEngine().getEagerlyAssumeTags(); 485 486 const ProgramPointTag *tag = PS->getTag(); 487 if (tag == tags.first) 488 return VisitTrueTest(cast<Expr>(PS->getStmt()), true, 489 BRC, N->getLocationContext()); 490 if (tag == tags.second) 491 return VisitTrueTest(cast<Expr>(PS->getStmt()), false, 492 BRC, N->getLocationContext()); 493 494 return 0; 495 } 496 497 return 0; 498} 499 500PathDiagnosticPiece * 501ConditionBRVisitor::VisitTerminator(const Stmt *Term, 502 const ExplodedNode *N, 503 const CFGBlock *srcBlk, 504 const CFGBlock *dstBlk, 505 BugReporterContext &BRC) { 506 const Expr *Cond = 0; 507 508 switch (Term->getStmtClass()) { 509 default: 510 return 0; 511 case Stmt::IfStmtClass: 512 Cond = cast<IfStmt>(Term)->getCond(); 513 break; 514 case Stmt::ConditionalOperatorClass: 515 Cond = cast<ConditionalOperator>(Term)->getCond(); 516 break; 517 } 518 519 assert(Cond); 520 assert(srcBlk->succ_size() == 2); 521 const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk; 522 return VisitTrueTest(Cond->IgnoreParenNoopCasts(BRC.getASTContext()), 523 tookTrue, BRC, N->getLocationContext()); 524} 525 526PathDiagnosticPiece * 527ConditionBRVisitor::VisitTrueTest(const Expr *Cond, 528 bool tookTrue, 529 BugReporterContext &BRC, 530 const LocationContext *LC) { 531 532 const Expr *Ex = Cond; 533 534 while (true) { 535 Ex = Ex->IgnoreParens(); 536 switch (Ex->getStmtClass()) { 537 default: 538 return 0; 539 case Stmt::BinaryOperatorClass: 540 return VisitTrueTest(Cond, cast<BinaryOperator>(Ex), tookTrue, BRC, LC); 541 case Stmt::DeclRefExprClass: 542 return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC, LC); 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 556bool ConditionBRVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out, 557 BugReporterContext &BRC) { 558 const Expr *OriginalExpr = Ex; 559 Ex = Ex->IgnoreParenCasts(); 560 561 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) { 562 const bool quotes = isa<VarDecl>(DR->getDecl()); 563 if (quotes) 564 Out << '\''; 565 Out << DR->getDecl()->getDeclName().getAsString(); 566 if (quotes) 567 Out << '\''; 568 return quotes; 569 } 570 571 if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) { 572 QualType OriginalTy = OriginalExpr->getType(); 573 if (OriginalTy->isPointerType()) { 574 if (IL->getValue() == 0) { 575 Out << "null"; 576 return false; 577 } 578 } 579 else if (OriginalTy->isObjCObjectPointerType()) { 580 if (IL->getValue() == 0) { 581 Out << "nil"; 582 return false; 583 } 584 } 585 586 Out << IL->getValue(); 587 return false; 588 } 589 590 return false; 591} 592 593PathDiagnosticPiece * 594ConditionBRVisitor::VisitTrueTest(const Expr *Cond, 595 const BinaryOperator *BExpr, 596 const bool tookTrue, 597 BugReporterContext &BRC, 598 const LocationContext *LC) { 599 600 bool shouldInvert = false; 601 602 SmallString<128> LhsString, RhsString; 603 { 604 llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString); 605 const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC); 606 const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC); 607 608 shouldInvert = !isVarLHS && isVarRHS; 609 } 610 611 BinaryOperator::Opcode Op = BExpr->getOpcode(); 612 613 if (BinaryOperator::isAssignmentOp(Op)) { 614 // For assignment operators, all that we care about is that the LHS 615 // evaluates to "true" or "false". 616 return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue, 617 BRC, LC); 618 } 619 620 // For non-assignment operations, we require that we can understand 621 // both the LHS and RHS. 622 if (LhsString.empty() || RhsString.empty()) 623 return 0; 624 625 // Should we invert the strings if the LHS is not a variable name? 626 SmallString<256> buf; 627 llvm::raw_svector_ostream Out(buf); 628 Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is "; 629 630 // Do we need to invert the opcode? 631 if (shouldInvert) 632 switch (Op) { 633 default: break; 634 case BO_LT: Op = BO_GT; break; 635 case BO_GT: Op = BO_LT; break; 636 case BO_LE: Op = BO_GE; break; 637 case BO_GE: Op = BO_LE; break; 638 } 639 640 if (!tookTrue) 641 switch (Op) { 642 case BO_EQ: Op = BO_NE; break; 643 case BO_NE: Op = BO_EQ; break; 644 case BO_LT: Op = BO_GE; break; 645 case BO_GT: Op = BO_LE; break; 646 case BO_LE: Op = BO_GT; break; 647 case BO_GE: Op = BO_LT; break; 648 default: 649 return 0; 650 } 651 652 switch (Op) { 653 case BO_EQ: 654 Out << "equal to "; 655 break; 656 case BO_NE: 657 Out << "not equal to "; 658 break; 659 default: 660 Out << BinaryOperator::getOpcodeStr(Op) << ' '; 661 break; 662 } 663 664 Out << (shouldInvert ? LhsString : RhsString); 665 666 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LC); 667 return new PathDiagnosticEventPiece(Loc, Out.str()); 668} 669 670PathDiagnosticPiece * 671ConditionBRVisitor::VisitConditionVariable(StringRef LhsString, 672 const Expr *CondVarExpr, 673 const bool tookTrue, 674 BugReporterContext &BRC, 675 const LocationContext *LC) { 676 SmallString<256> buf; 677 llvm::raw_svector_ostream Out(buf); 678 Out << "Assuming " << LhsString << " is "; 679 680 QualType Ty = CondVarExpr->getType(); 681 682 if (Ty->isPointerType()) 683 Out << (tookTrue ? "not null" : "null"); 684 else if (Ty->isObjCObjectPointerType()) 685 Out << (tookTrue ? "not nil" : "nil"); 686 else if (Ty->isBooleanType()) 687 Out << (tookTrue ? "true" : "false"); 688 else if (Ty->isIntegerType()) 689 Out << (tookTrue ? "non-zero" : "zero"); 690 else 691 return 0; 692 693 PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LC); 694 return new PathDiagnosticEventPiece(Loc, Out.str()); 695} 696 697PathDiagnosticPiece * 698ConditionBRVisitor::VisitTrueTest(const Expr *Cond, 699 const DeclRefExpr *DR, 700 const bool tookTrue, 701 BugReporterContext &BRC, 702 const LocationContext *LC) { 703 704 const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); 705 if (!VD) 706 return 0; 707 708 SmallString<256> Buf; 709 llvm::raw_svector_ostream Out(Buf); 710 711 Out << "Assuming '"; 712 VD->getDeclName().printName(Out); 713 Out << "' is "; 714 715 QualType VDTy = VD->getType(); 716 717 if (VDTy->isPointerType()) 718 Out << (tookTrue ? "non-null" : "null"); 719 else if (VDTy->isObjCObjectPointerType()) 720 Out << (tookTrue ? "non-nil" : "nil"); 721 else if (VDTy->isScalarType()) 722 Out << (tookTrue ? "not equal to 0" : "0"); 723 else 724 return 0; 725 726 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LC); 727 return new PathDiagnosticEventPiece(Loc, Out.str()); 728} 729