BugReporter.cpp revision 8bef8238181a30e52dea380789a7e2d760eac532
1// BugReporter.cpp - Generate PathDiagnostics for 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 BugReporter, a utility class for generating 11// PathDiagnostics. 12// 13//===----------------------------------------------------------------------===// 14 15#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 16#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 17#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 18#include "clang/AST/ASTContext.h" 19#include "clang/Analysis/CFG.h" 20#include "clang/AST/Expr.h" 21#include "clang/AST/ParentMap.h" 22#include "clang/AST/StmtObjC.h" 23#include "clang/Basic/SourceManager.h" 24#include "clang/Analysis/ProgramPoint.h" 25#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 26#include "llvm/Support/raw_ostream.h" 27#include "llvm/ADT/DenseMap.h" 28#include "llvm/ADT/STLExtras.h" 29#include "llvm/ADT/OwningPtr.h" 30#include <queue> 31 32using namespace clang; 33using namespace ento; 34 35BugReporterVisitor::~BugReporterVisitor() {} 36 37void BugReporterContext::anchor() {} 38 39//===----------------------------------------------------------------------===// 40// Helper routines for walking the ExplodedGraph and fetching statements. 41//===----------------------------------------------------------------------===// 42 43static inline const Stmt *GetStmt(const ProgramPoint &P) { 44 if (const StmtPoint* SP = dyn_cast<StmtPoint>(&P)) 45 return SP->getStmt(); 46 else if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) 47 return BE->getSrc()->getTerminator(); 48 49 return 0; 50} 51 52static inline const ExplodedNode* 53GetPredecessorNode(const ExplodedNode *N) { 54 return N->pred_empty() ? NULL : *(N->pred_begin()); 55} 56 57static inline const ExplodedNode* 58GetSuccessorNode(const ExplodedNode *N) { 59 return N->succ_empty() ? NULL : *(N->succ_begin()); 60} 61 62static const Stmt *GetPreviousStmt(const ExplodedNode *N) { 63 for (N = GetPredecessorNode(N); N; N = GetPredecessorNode(N)) 64 if (const Stmt *S = GetStmt(N->getLocation())) 65 return S; 66 67 return 0; 68} 69 70static const Stmt *GetNextStmt(const ExplodedNode *N) { 71 for (N = GetSuccessorNode(N); N; N = GetSuccessorNode(N)) 72 if (const Stmt *S = GetStmt(N->getLocation())) { 73 // Check if the statement is '?' or '&&'/'||'. These are "merges", 74 // not actual statement points. 75 switch (S->getStmtClass()) { 76 case Stmt::ChooseExprClass: 77 case Stmt::BinaryConditionalOperatorClass: continue; 78 case Stmt::ConditionalOperatorClass: continue; 79 case Stmt::BinaryOperatorClass: { 80 BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode(); 81 if (Op == BO_LAnd || Op == BO_LOr) 82 continue; 83 break; 84 } 85 default: 86 break; 87 } 88 return S; 89 } 90 91 return 0; 92} 93 94static inline const Stmt* 95GetCurrentOrPreviousStmt(const ExplodedNode *N) { 96 if (const Stmt *S = GetStmt(N->getLocation())) 97 return S; 98 99 return GetPreviousStmt(N); 100} 101 102static inline const Stmt* 103GetCurrentOrNextStmt(const ExplodedNode *N) { 104 if (const Stmt *S = GetStmt(N->getLocation())) 105 return S; 106 107 return GetNextStmt(N); 108} 109 110//===----------------------------------------------------------------------===// 111// PathDiagnosticBuilder and its associated routines and helper objects. 112//===----------------------------------------------------------------------===// 113 114typedef llvm::DenseMap<const ExplodedNode*, 115const ExplodedNode*> NodeBackMap; 116 117namespace { 118class NodeMapClosure : public BugReport::NodeResolver { 119 NodeBackMap& M; 120public: 121 NodeMapClosure(NodeBackMap *m) : M(*m) {} 122 ~NodeMapClosure() {} 123 124 const ExplodedNode *getOriginalNode(const ExplodedNode *N) { 125 NodeBackMap::iterator I = M.find(N); 126 return I == M.end() ? 0 : I->second; 127 } 128}; 129 130class PathDiagnosticBuilder : public BugReporterContext { 131 BugReport *R; 132 PathDiagnosticConsumer *PDC; 133 llvm::OwningPtr<ParentMap> PM; 134 NodeMapClosure NMC; 135public: 136 PathDiagnosticBuilder(GRBugReporter &br, 137 BugReport *r, NodeBackMap *Backmap, 138 PathDiagnosticConsumer *pdc) 139 : BugReporterContext(br), 140 R(r), PDC(pdc), NMC(Backmap) {} 141 142 PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N); 143 144 PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os, 145 const ExplodedNode *N); 146 147 BugReport *getBugReport() { return R; } 148 149 Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); } 150 151 const LocationContext* getLocationContext() { 152 return R->getErrorNode()->getLocationContext(); 153 } 154 155 ParentMap& getParentMap() { return R->getErrorNode()->getParentMap(); } 156 157 const Stmt *getParent(const Stmt *S) { 158 return getParentMap().getParent(S); 159 } 160 161 virtual NodeMapClosure& getNodeResolver() { return NMC; } 162 163 PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S); 164 165 PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const { 166 return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive; 167 } 168 169 bool supportsLogicalOpControlFlow() const { 170 return PDC ? PDC->supportsLogicalOpControlFlow() : true; 171 } 172}; 173} // end anonymous namespace 174 175PathDiagnosticLocation 176PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) { 177 if (const Stmt *S = GetNextStmt(N)) 178 return PathDiagnosticLocation(S, getSourceManager(), getLocationContext()); 179 180 return PathDiagnosticLocation::createDeclEnd(N->getLocationContext(), 181 getSourceManager()); 182} 183 184PathDiagnosticLocation 185PathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os, 186 const ExplodedNode *N) { 187 188 // Slow, but probably doesn't matter. 189 if (os.str().empty()) 190 os << ' '; 191 192 const PathDiagnosticLocation &Loc = ExecutionContinues(N); 193 194 if (Loc.asStmt()) 195 os << "Execution continues on line " 196 << getSourceManager().getExpansionLineNumber(Loc.asLocation()) 197 << '.'; 198 else { 199 os << "Execution jumps to the end of the "; 200 const Decl *D = N->getLocationContext()->getDecl(); 201 if (isa<ObjCMethodDecl>(D)) 202 os << "method"; 203 else if (isa<FunctionDecl>(D)) 204 os << "function"; 205 else { 206 assert(isa<BlockDecl>(D)); 207 os << "anonymous block"; 208 } 209 os << '.'; 210 } 211 212 return Loc; 213} 214 215static bool IsNested(const Stmt *S, ParentMap &PM) { 216 if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S))) 217 return true; 218 219 const Stmt *Parent = PM.getParentIgnoreParens(S); 220 221 if (Parent) 222 switch (Parent->getStmtClass()) { 223 case Stmt::ForStmtClass: 224 case Stmt::DoStmtClass: 225 case Stmt::WhileStmtClass: 226 return true; 227 default: 228 break; 229 } 230 231 return false; 232} 233 234PathDiagnosticLocation 235PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { 236 assert(S && "Null Stmt *passed to getEnclosingStmtLocation"); 237 ParentMap &P = getParentMap(); 238 SourceManager &SMgr = getSourceManager(); 239 const LocationContext *LC = getLocationContext(); 240 241 while (IsNested(S, P)) { 242 const Stmt *Parent = P.getParentIgnoreParens(S); 243 244 if (!Parent) 245 break; 246 247 switch (Parent->getStmtClass()) { 248 case Stmt::BinaryOperatorClass: { 249 const BinaryOperator *B = cast<BinaryOperator>(Parent); 250 if (B->isLogicalOp()) 251 return PathDiagnosticLocation(S, SMgr, LC); 252 break; 253 } 254 case Stmt::CompoundStmtClass: 255 case Stmt::StmtExprClass: 256 return PathDiagnosticLocation(S, SMgr, LC); 257 case Stmt::ChooseExprClass: 258 // Similar to '?' if we are referring to condition, just have the edge 259 // point to the entire choose expression. 260 if (cast<ChooseExpr>(Parent)->getCond() == S) 261 return PathDiagnosticLocation(Parent, SMgr, LC); 262 else 263 return PathDiagnosticLocation(S, SMgr, LC); 264 case Stmt::BinaryConditionalOperatorClass: 265 case Stmt::ConditionalOperatorClass: 266 // For '?', if we are referring to condition, just have the edge point 267 // to the entire '?' expression. 268 if (cast<AbstractConditionalOperator>(Parent)->getCond() == S) 269 return PathDiagnosticLocation(Parent, SMgr, LC); 270 else 271 return PathDiagnosticLocation(S, SMgr, LC); 272 case Stmt::DoStmtClass: 273 return PathDiagnosticLocation(S, SMgr, LC); 274 case Stmt::ForStmtClass: 275 if (cast<ForStmt>(Parent)->getBody() == S) 276 return PathDiagnosticLocation(S, SMgr, LC); 277 break; 278 case Stmt::IfStmtClass: 279 if (cast<IfStmt>(Parent)->getCond() != S) 280 return PathDiagnosticLocation(S, SMgr, LC); 281 break; 282 case Stmt::ObjCForCollectionStmtClass: 283 if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S) 284 return PathDiagnosticLocation(S, SMgr, LC); 285 break; 286 case Stmt::WhileStmtClass: 287 if (cast<WhileStmt>(Parent)->getCond() != S) 288 return PathDiagnosticLocation(S, SMgr, LC); 289 break; 290 default: 291 break; 292 } 293 294 S = Parent; 295 } 296 297 assert(S && "Cannot have null Stmt for PathDiagnosticLocation"); 298 299 // Special case: DeclStmts can appear in for statement declarations, in which 300 // case the ForStmt is the context. 301 if (isa<DeclStmt>(S)) { 302 if (const Stmt *Parent = P.getParent(S)) { 303 switch (Parent->getStmtClass()) { 304 case Stmt::ForStmtClass: 305 case Stmt::ObjCForCollectionStmtClass: 306 return PathDiagnosticLocation(Parent, SMgr, LC); 307 default: 308 break; 309 } 310 } 311 } 312 else if (isa<BinaryOperator>(S)) { 313 // Special case: the binary operator represents the initialization 314 // code in a for statement (this can happen when the variable being 315 // initialized is an old variable. 316 if (const ForStmt *FS = 317 dyn_cast_or_null<ForStmt>(P.getParentIgnoreParens(S))) { 318 if (FS->getInit() == S) 319 return PathDiagnosticLocation(FS, SMgr, LC); 320 } 321 } 322 323 return PathDiagnosticLocation(S, SMgr, LC); 324} 325 326//===----------------------------------------------------------------------===// 327// ScanNotableSymbols: closure-like callback for scanning Store bindings. 328//===----------------------------------------------------------------------===// 329 330static const VarDecl* GetMostRecentVarDeclBinding(const ExplodedNode *N, 331 ProgramStateManager& VMgr, 332 SVal X) { 333 334 for ( ; N ; N = N->pred_empty() ? 0 : *N->pred_begin()) { 335 336 ProgramPoint P = N->getLocation(); 337 338 if (!isa<PostStmt>(P)) 339 continue; 340 341 const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(cast<PostStmt>(P).getStmt()); 342 343 if (!DR) 344 continue; 345 346 SVal Y = N->getState()->getSVal(DR, N->getLocationContext()); 347 348 if (X != Y) 349 continue; 350 351 const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); 352 353 if (!VD) 354 continue; 355 356 return VD; 357 } 358 359 return 0; 360} 361 362namespace { 363class NotableSymbolHandler 364: public StoreManager::BindingsHandler { 365 366 SymbolRef Sym; 367 ProgramStateRef PrevSt; 368 const Stmt *S; 369 ProgramStateManager& VMgr; 370 const ExplodedNode *Pred; 371 PathDiagnostic& PD; 372 BugReporter& BR; 373 374public: 375 376 NotableSymbolHandler(SymbolRef sym, 377 ProgramStateRef prevst, 378 const Stmt *s, 379 ProgramStateManager& vmgr, 380 const ExplodedNode *pred, 381 PathDiagnostic& pd, 382 BugReporter& br) 383 : Sym(sym), 384 PrevSt(prevst), 385 S(s), 386 VMgr(vmgr), 387 Pred(pred), 388 PD(pd), 389 BR(br) {} 390 391 bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, 392 SVal V) { 393 394 SymbolRef ScanSym = V.getAsSymbol(); 395 396 if (ScanSym != Sym) 397 return true; 398 399 // Check if the previous state has this binding. 400 SVal X = PrevSt->getSVal(loc::MemRegionVal(R)); 401 402 if (X == V) // Same binding? 403 return true; 404 405 // Different binding. Only handle assignments for now. We don't pull 406 // this check out of the loop because we will eventually handle other 407 // cases. 408 409 VarDecl *VD = 0; 410 411 if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { 412 if (!B->isAssignmentOp()) 413 return true; 414 415 // What variable did we assign to? 416 DeclRefExpr *DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenCasts()); 417 418 if (!DR) 419 return true; 420 421 VD = dyn_cast<VarDecl>(DR->getDecl()); 422 } 423 else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) { 424 // FIXME: Eventually CFGs won't have DeclStmts. Right now we 425 // assume that each DeclStmt has a single Decl. This invariant 426 // holds by construction in the CFG. 427 VD = dyn_cast<VarDecl>(*DS->decl_begin()); 428 } 429 430 if (!VD) 431 return true; 432 433 // What is the most recently referenced variable with this binding? 434 const VarDecl *MostRecent = GetMostRecentVarDeclBinding(Pred, VMgr, V); 435 436 if (!MostRecent) 437 return true; 438 439 // Create the diagnostic. 440 if (Loc::isLocType(VD->getType())) { 441 llvm::SmallString<64> buf; 442 llvm::raw_svector_ostream os(buf); 443 os << '\'' << *VD << "' now aliases '" << *MostRecent << '\''; 444 PathDiagnosticLocation L = 445 PathDiagnosticLocation::createBegin(S, BR.getSourceManager(), 446 Pred->getLocationContext()); 447 PD.push_front(new PathDiagnosticEventPiece(L, os.str())); 448 } 449 450 return true; 451 } 452}; 453} 454 455static void HandleNotableSymbol(const ExplodedNode *N, 456 const Stmt *S, 457 SymbolRef Sym, BugReporter& BR, 458 PathDiagnostic& PD) { 459 460 const ExplodedNode *Pred = N->pred_empty() ? 0 : *N->pred_begin(); 461 ProgramStateRef PrevSt = Pred ? Pred->getState() : 0; 462 463 if (!PrevSt) 464 return; 465 466 // Look at the region bindings of the current state that map to the 467 // specified symbol. Are any of them not in the previous state? 468 ProgramStateManager& VMgr = cast<GRBugReporter>(BR).getStateManager(); 469 NotableSymbolHandler H(Sym, PrevSt, S, VMgr, Pred, PD, BR); 470 cast<GRBugReporter>(BR).getStateManager().iterBindings(N->getState(), H); 471} 472 473namespace { 474class ScanNotableSymbols 475: public StoreManager::BindingsHandler { 476 477 llvm::SmallSet<SymbolRef, 10> AlreadyProcessed; 478 const ExplodedNode *N; 479 const Stmt *S; 480 GRBugReporter& BR; 481 PathDiagnostic& PD; 482 483public: 484 ScanNotableSymbols(const ExplodedNode *n, const Stmt *s, 485 GRBugReporter& br, PathDiagnostic& pd) 486 : N(n), S(s), BR(br), PD(pd) {} 487 488 bool HandleBinding(StoreManager& SMgr, Store store, 489 const MemRegion* R, SVal V) { 490 491 SymbolRef ScanSym = V.getAsSymbol(); 492 493 if (!ScanSym) 494 return true; 495 496 if (!BR.isNotable(ScanSym)) 497 return true; 498 499 if (AlreadyProcessed.count(ScanSym)) 500 return true; 501 502 AlreadyProcessed.insert(ScanSym); 503 504 HandleNotableSymbol(N, S, ScanSym, BR, PD); 505 return true; 506 } 507}; 508} // end anonymous namespace 509 510//===----------------------------------------------------------------------===// 511// "Minimal" path diagnostic generation algorithm. 512//===----------------------------------------------------------------------===// 513 514static void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM); 515 516static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, 517 PathDiagnosticBuilder &PDB, 518 const ExplodedNode *N) { 519 520 SourceManager& SMgr = PDB.getSourceManager(); 521 const LocationContext *LC = PDB.getLocationContext(); 522 const ExplodedNode *NextNode = N->pred_empty() 523 ? NULL : *(N->pred_begin()); 524 while (NextNode) { 525 N = NextNode; 526 NextNode = GetPredecessorNode(N); 527 528 ProgramPoint P = N->getLocation(); 529 530 if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 531 const CFGBlock *Src = BE->getSrc(); 532 const CFGBlock *Dst = BE->getDst(); 533 const Stmt *T = Src->getTerminator(); 534 535 if (!T) 536 continue; 537 538 PathDiagnosticLocation Start = 539 PathDiagnosticLocation::createBegin(T, SMgr, 540 N->getLocationContext()); 541 542 switch (T->getStmtClass()) { 543 default: 544 break; 545 546 case Stmt::GotoStmtClass: 547 case Stmt::IndirectGotoStmtClass: { 548 const Stmt *S = GetNextStmt(N); 549 550 if (!S) 551 continue; 552 553 std::string sbuf; 554 llvm::raw_string_ostream os(sbuf); 555 const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S); 556 557 os << "Control jumps to line " 558 << End.asLocation().getExpansionLineNumber(); 559 PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 560 os.str())); 561 break; 562 } 563 564 case Stmt::SwitchStmtClass: { 565 // Figure out what case arm we took. 566 std::string sbuf; 567 llvm::raw_string_ostream os(sbuf); 568 569 if (const Stmt *S = Dst->getLabel()) { 570 PathDiagnosticLocation End(S, SMgr, LC); 571 572 switch (S->getStmtClass()) { 573 default: 574 os << "No cases match in the switch statement. " 575 "Control jumps to line " 576 << End.asLocation().getExpansionLineNumber(); 577 break; 578 case Stmt::DefaultStmtClass: 579 os << "Control jumps to the 'default' case at line " 580 << End.asLocation().getExpansionLineNumber(); 581 break; 582 583 case Stmt::CaseStmtClass: { 584 os << "Control jumps to 'case "; 585 const CaseStmt *Case = cast<CaseStmt>(S); 586 const Expr *LHS = Case->getLHS()->IgnoreParenCasts(); 587 588 // Determine if it is an enum. 589 bool GetRawInt = true; 590 591 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) { 592 // FIXME: Maybe this should be an assertion. Are there cases 593 // were it is not an EnumConstantDecl? 594 const EnumConstantDecl *D = 595 dyn_cast<EnumConstantDecl>(DR->getDecl()); 596 597 if (D) { 598 GetRawInt = false; 599 os << *D; 600 } 601 } 602 603 if (GetRawInt) 604 os << LHS->EvaluateKnownConstInt(PDB.getASTContext()); 605 606 os << ":' at line " 607 << End.asLocation().getExpansionLineNumber(); 608 break; 609 } 610 } 611 PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 612 os.str())); 613 } 614 else { 615 os << "'Default' branch taken. "; 616 const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N); 617 PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 618 os.str())); 619 } 620 621 break; 622 } 623 624 case Stmt::BreakStmtClass: 625 case Stmt::ContinueStmtClass: { 626 std::string sbuf; 627 llvm::raw_string_ostream os(sbuf); 628 PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 629 PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 630 os.str())); 631 break; 632 } 633 634 // Determine control-flow for ternary '?'. 635 case Stmt::BinaryConditionalOperatorClass: 636 case Stmt::ConditionalOperatorClass: { 637 std::string sbuf; 638 llvm::raw_string_ostream os(sbuf); 639 os << "'?' condition is "; 640 641 if (*(Src->succ_begin()+1) == Dst) 642 os << "false"; 643 else 644 os << "true"; 645 646 PathDiagnosticLocation End = PDB.ExecutionContinues(N); 647 648 if (const Stmt *S = End.asStmt()) 649 End = PDB.getEnclosingStmtLocation(S); 650 651 PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 652 os.str())); 653 break; 654 } 655 656 // Determine control-flow for short-circuited '&&' and '||'. 657 case Stmt::BinaryOperatorClass: { 658 if (!PDB.supportsLogicalOpControlFlow()) 659 break; 660 661 const BinaryOperator *B = cast<BinaryOperator>(T); 662 std::string sbuf; 663 llvm::raw_string_ostream os(sbuf); 664 os << "Left side of '"; 665 666 if (B->getOpcode() == BO_LAnd) { 667 os << "&&" << "' is "; 668 669 if (*(Src->succ_begin()+1) == Dst) { 670 os << "false"; 671 PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 672 PathDiagnosticLocation Start = 673 PathDiagnosticLocation::createOperatorLoc(B, SMgr); 674 PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 675 os.str())); 676 } 677 else { 678 os << "true"; 679 PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 680 PathDiagnosticLocation End = PDB.ExecutionContinues(N); 681 PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 682 os.str())); 683 } 684 } 685 else { 686 assert(B->getOpcode() == BO_LOr); 687 os << "||" << "' is "; 688 689 if (*(Src->succ_begin()+1) == Dst) { 690 os << "false"; 691 PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 692 PathDiagnosticLocation End = PDB.ExecutionContinues(N); 693 PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 694 os.str())); 695 } 696 else { 697 os << "true"; 698 PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 699 PathDiagnosticLocation Start = 700 PathDiagnosticLocation::createOperatorLoc(B, SMgr); 701 PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 702 os.str())); 703 } 704 } 705 706 break; 707 } 708 709 case Stmt::DoStmtClass: { 710 if (*(Src->succ_begin()) == Dst) { 711 std::string sbuf; 712 llvm::raw_string_ostream os(sbuf); 713 714 os << "Loop condition is true. "; 715 PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 716 717 if (const Stmt *S = End.asStmt()) 718 End = PDB.getEnclosingStmtLocation(S); 719 720 PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 721 os.str())); 722 } 723 else { 724 PathDiagnosticLocation End = PDB.ExecutionContinues(N); 725 726 if (const Stmt *S = End.asStmt()) 727 End = PDB.getEnclosingStmtLocation(S); 728 729 PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 730 "Loop condition is false. Exiting loop")); 731 } 732 733 break; 734 } 735 736 case Stmt::WhileStmtClass: 737 case Stmt::ForStmtClass: { 738 if (*(Src->succ_begin()+1) == Dst) { 739 std::string sbuf; 740 llvm::raw_string_ostream os(sbuf); 741 742 os << "Loop condition is false. "; 743 PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 744 if (const Stmt *S = End.asStmt()) 745 End = PDB.getEnclosingStmtLocation(S); 746 747 PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 748 os.str())); 749 } 750 else { 751 PathDiagnosticLocation End = PDB.ExecutionContinues(N); 752 if (const Stmt *S = End.asStmt()) 753 End = PDB.getEnclosingStmtLocation(S); 754 755 PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 756 "Loop condition is true. Entering loop body")); 757 } 758 759 break; 760 } 761 762 case Stmt::IfStmtClass: { 763 PathDiagnosticLocation End = PDB.ExecutionContinues(N); 764 765 if (const Stmt *S = End.asStmt()) 766 End = PDB.getEnclosingStmtLocation(S); 767 768 if (*(Src->succ_begin()+1) == Dst) 769 PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 770 "Taking false branch")); 771 else 772 PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 773 "Taking true branch")); 774 775 break; 776 } 777 } 778 } 779 780 if (NextNode) { 781 // Add diagnostic pieces from custom visitors. 782 BugReport *R = PDB.getBugReport(); 783 for (BugReport::visitor_iterator I = R->visitor_begin(), 784 E = R->visitor_end(); I!=E; ++I) { 785 if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) 786 PD.push_front(p); 787 } 788 } 789 790 if (const PostStmt *PS = dyn_cast<PostStmt>(&P)) { 791 // Scan the region bindings, and see if a "notable" symbol has a new 792 // lval binding. 793 ScanNotableSymbols SNS(N, PS->getStmt(), PDB.getBugReporter(), PD); 794 PDB.getStateManager().iterBindings(N->getState(), SNS); 795 } 796 } 797 798 // After constructing the full PathDiagnostic, do a pass over it to compact 799 // PathDiagnosticPieces that occur within a macro. 800 CompactPathDiagnostic(PD, PDB.getSourceManager()); 801} 802 803//===----------------------------------------------------------------------===// 804// "Extensive" PathDiagnostic generation. 805//===----------------------------------------------------------------------===// 806 807static bool IsControlFlowExpr(const Stmt *S) { 808 const Expr *E = dyn_cast<Expr>(S); 809 810 if (!E) 811 return false; 812 813 E = E->IgnoreParenCasts(); 814 815 if (isa<AbstractConditionalOperator>(E)) 816 return true; 817 818 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) 819 if (B->isLogicalOp()) 820 return true; 821 822 return false; 823} 824 825namespace { 826class ContextLocation : public PathDiagnosticLocation { 827 bool IsDead; 828public: 829 ContextLocation(const PathDiagnosticLocation &L, bool isdead = false) 830 : PathDiagnosticLocation(L), IsDead(isdead) {} 831 832 void markDead() { IsDead = true; } 833 bool isDead() const { return IsDead; } 834}; 835 836class EdgeBuilder { 837 std::vector<ContextLocation> CLocs; 838 typedef std::vector<ContextLocation>::iterator iterator; 839 PathDiagnostic &PD; 840 PathDiagnosticBuilder &PDB; 841 PathDiagnosticLocation PrevLoc; 842 843 bool IsConsumedExpr(const PathDiagnosticLocation &L); 844 845 bool containsLocation(const PathDiagnosticLocation &Container, 846 const PathDiagnosticLocation &Containee); 847 848 PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L); 849 850 PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L, 851 bool firstCharOnly = false) { 852 if (const Stmt *S = L.asStmt()) { 853 const Stmt *Original = S; 854 while (1) { 855 // Adjust the location for some expressions that are best referenced 856 // by one of their subexpressions. 857 switch (S->getStmtClass()) { 858 default: 859 break; 860 case Stmt::ParenExprClass: 861 case Stmt::GenericSelectionExprClass: 862 S = cast<Expr>(S)->IgnoreParens(); 863 firstCharOnly = true; 864 continue; 865 case Stmt::BinaryConditionalOperatorClass: 866 case Stmt::ConditionalOperatorClass: 867 S = cast<AbstractConditionalOperator>(S)->getCond(); 868 firstCharOnly = true; 869 continue; 870 case Stmt::ChooseExprClass: 871 S = cast<ChooseExpr>(S)->getCond(); 872 firstCharOnly = true; 873 continue; 874 case Stmt::BinaryOperatorClass: 875 S = cast<BinaryOperator>(S)->getLHS(); 876 firstCharOnly = true; 877 continue; 878 } 879 880 break; 881 } 882 883 if (S != Original) 884 L = PathDiagnosticLocation(S, L.getManager(), PDB.getLocationContext()); 885 } 886 887 if (firstCharOnly) 888 L = PathDiagnosticLocation::createSingleLocation(L); 889 890 return L; 891 } 892 893 void popLocation() { 894 if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) { 895 // For contexts, we only one the first character as the range. 896 rawAddEdge(cleanUpLocation(CLocs.back(), true)); 897 } 898 CLocs.pop_back(); 899 } 900 901public: 902 EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb) 903 : PD(pd), PDB(pdb) { 904 905 // If the PathDiagnostic already has pieces, add the enclosing statement 906 // of the first piece as a context as well. 907 if (!PD.empty()) { 908 PrevLoc = PD.begin()->getLocation(); 909 910 if (const Stmt *S = PrevLoc.asStmt()) 911 addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 912 } 913 } 914 915 ~EdgeBuilder() { 916 while (!CLocs.empty()) popLocation(); 917 918 // Finally, add an initial edge from the start location of the first 919 // statement (if it doesn't already exist). 920 PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin( 921 PDB.getLocationContext(), 922 PDB.getSourceManager()); 923 if (L.isValid()) 924 rawAddEdge(L); 925 } 926 927 void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false); 928 929 void rawAddEdge(PathDiagnosticLocation NewLoc); 930 931 void addContext(const Stmt *S); 932 void addExtendedContext(const Stmt *S); 933}; 934} // end anonymous namespace 935 936 937PathDiagnosticLocation 938EdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) { 939 if (const Stmt *S = L.asStmt()) { 940 if (IsControlFlowExpr(S)) 941 return L; 942 943 return PDB.getEnclosingStmtLocation(S); 944 } 945 946 return L; 947} 948 949bool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container, 950 const PathDiagnosticLocation &Containee) { 951 952 if (Container == Containee) 953 return true; 954 955 if (Container.asDecl()) 956 return true; 957 958 if (const Stmt *S = Containee.asStmt()) 959 if (const Stmt *ContainerS = Container.asStmt()) { 960 while (S) { 961 if (S == ContainerS) 962 return true; 963 S = PDB.getParent(S); 964 } 965 return false; 966 } 967 968 // Less accurate: compare using source ranges. 969 SourceRange ContainerR = Container.asRange(); 970 SourceRange ContaineeR = Containee.asRange(); 971 972 SourceManager &SM = PDB.getSourceManager(); 973 SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin()); 974 SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd()); 975 SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin()); 976 SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd()); 977 978 unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg); 979 unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd); 980 unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg); 981 unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd); 982 983 assert(ContainerBegLine <= ContainerEndLine); 984 assert(ContaineeBegLine <= ContaineeEndLine); 985 986 return (ContainerBegLine <= ContaineeBegLine && 987 ContainerEndLine >= ContaineeEndLine && 988 (ContainerBegLine != ContaineeBegLine || 989 SM.getExpansionColumnNumber(ContainerRBeg) <= 990 SM.getExpansionColumnNumber(ContaineeRBeg)) && 991 (ContainerEndLine != ContaineeEndLine || 992 SM.getExpansionColumnNumber(ContainerREnd) >= 993 SM.getExpansionColumnNumber(ContainerREnd))); 994} 995 996void EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) { 997 if (!PrevLoc.isValid()) { 998 PrevLoc = NewLoc; 999 return; 1000 } 1001 1002 const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc); 1003 const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc); 1004 1005 if (NewLocClean.asLocation() == PrevLocClean.asLocation()) 1006 return; 1007 1008 // FIXME: Ignore intra-macro edges for now. 1009 if (NewLocClean.asLocation().getExpansionLoc() == 1010 PrevLocClean.asLocation().getExpansionLoc()) 1011 return; 1012 1013 PD.push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean)); 1014 PrevLoc = NewLoc; 1015} 1016 1017void EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) { 1018 1019 if (!alwaysAdd && NewLoc.asLocation().isMacroID()) 1020 return; 1021 1022 const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc); 1023 1024 while (!CLocs.empty()) { 1025 ContextLocation &TopContextLoc = CLocs.back(); 1026 1027 // Is the top location context the same as the one for the new location? 1028 if (TopContextLoc == CLoc) { 1029 if (alwaysAdd) { 1030 if (IsConsumedExpr(TopContextLoc) && 1031 !IsControlFlowExpr(TopContextLoc.asStmt())) 1032 TopContextLoc.markDead(); 1033 1034 rawAddEdge(NewLoc); 1035 } 1036 1037 return; 1038 } 1039 1040 if (containsLocation(TopContextLoc, CLoc)) { 1041 if (alwaysAdd) { 1042 rawAddEdge(NewLoc); 1043 1044 if (IsConsumedExpr(CLoc) && !IsControlFlowExpr(CLoc.asStmt())) { 1045 CLocs.push_back(ContextLocation(CLoc, true)); 1046 return; 1047 } 1048 } 1049 1050 CLocs.push_back(CLoc); 1051 return; 1052 } 1053 1054 // Context does not contain the location. Flush it. 1055 popLocation(); 1056 } 1057 1058 // If we reach here, there is no enclosing context. Just add the edge. 1059 rawAddEdge(NewLoc); 1060} 1061 1062bool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) { 1063 if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt())) 1064 return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X); 1065 1066 return false; 1067} 1068 1069void EdgeBuilder::addExtendedContext(const Stmt *S) { 1070 if (!S) 1071 return; 1072 1073 const Stmt *Parent = PDB.getParent(S); 1074 while (Parent) { 1075 if (isa<CompoundStmt>(Parent)) 1076 Parent = PDB.getParent(Parent); 1077 else 1078 break; 1079 } 1080 1081 if (Parent) { 1082 switch (Parent->getStmtClass()) { 1083 case Stmt::DoStmtClass: 1084 case Stmt::ObjCAtSynchronizedStmtClass: 1085 addContext(Parent); 1086 default: 1087 break; 1088 } 1089 } 1090 1091 addContext(S); 1092} 1093 1094void EdgeBuilder::addContext(const Stmt *S) { 1095 if (!S) 1096 return; 1097 1098 PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.getLocationContext()); 1099 1100 while (!CLocs.empty()) { 1101 const PathDiagnosticLocation &TopContextLoc = CLocs.back(); 1102 1103 // Is the top location context the same as the one for the new location? 1104 if (TopContextLoc == L) 1105 return; 1106 1107 if (containsLocation(TopContextLoc, L)) { 1108 CLocs.push_back(L); 1109 return; 1110 } 1111 1112 // Context does not contain the location. Flush it. 1113 popLocation(); 1114 } 1115 1116 CLocs.push_back(L); 1117} 1118 1119static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, 1120 PathDiagnosticBuilder &PDB, 1121 const ExplodedNode *N) { 1122 EdgeBuilder EB(PD, PDB); 1123 const SourceManager& SM = PDB.getSourceManager(); 1124 1125 const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); 1126 while (NextNode) { 1127 N = NextNode; 1128 NextNode = GetPredecessorNode(N); 1129 ProgramPoint P = N->getLocation(); 1130 1131 do { 1132 // Block edges. 1133 if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 1134 const CFGBlock &Blk = *BE->getSrc(); 1135 const Stmt *Term = Blk.getTerminator(); 1136 1137 // Are we jumping to the head of a loop? Add a special diagnostic. 1138 if (const Stmt *Loop = BE->getDst()->getLoopTarget()) { 1139 PathDiagnosticLocation L(Loop, SM, PDB.getLocationContext()); 1140 const CompoundStmt *CS = NULL; 1141 1142 if (!Term) { 1143 if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) 1144 CS = dyn_cast<CompoundStmt>(FS->getBody()); 1145 else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) 1146 CS = dyn_cast<CompoundStmt>(WS->getBody()); 1147 } 1148 1149 PathDiagnosticEventPiece *p = 1150 new PathDiagnosticEventPiece(L, 1151 "Looping back to the head of the loop"); 1152 1153 EB.addEdge(p->getLocation(), true); 1154 PD.push_front(p); 1155 1156 if (CS) { 1157 PathDiagnosticLocation BL = 1158 PathDiagnosticLocation::createEndBrace(CS, SM); 1159 EB.addEdge(BL); 1160 } 1161 } 1162 1163 if (Term) 1164 EB.addContext(Term); 1165 1166 break; 1167 } 1168 1169 if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) { 1170 if (const CFGStmt *S = BE->getFirstElement().getAs<CFGStmt>()) { 1171 const Stmt *stmt = S->getStmt(); 1172 if (IsControlFlowExpr(stmt)) { 1173 // Add the proper context for '&&', '||', and '?'. 1174 EB.addContext(stmt); 1175 } 1176 else 1177 EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt()); 1178 } 1179 1180 break; 1181 } 1182 } while (0); 1183 1184 if (!NextNode) 1185 continue; 1186 1187 // Add pieces from custom visitors. 1188 BugReport *R = PDB.getBugReport(); 1189 for (BugReport::visitor_iterator I = R->visitor_begin(), 1190 E = R->visitor_end(); I!=E; ++I) { 1191 if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 1192 const PathDiagnosticLocation &Loc = p->getLocation(); 1193 EB.addEdge(Loc, true); 1194 PD.push_front(p); 1195 if (const Stmt *S = Loc.asStmt()) 1196 EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 1197 } 1198 } 1199 } 1200} 1201 1202//===----------------------------------------------------------------------===// 1203// Methods for BugType and subclasses. 1204//===----------------------------------------------------------------------===// 1205BugType::~BugType() { } 1206 1207void BugType::FlushReports(BugReporter &BR) {} 1208 1209void BuiltinBug::anchor() {} 1210 1211//===----------------------------------------------------------------------===// 1212// Methods for BugReport and subclasses. 1213//===----------------------------------------------------------------------===// 1214 1215void BugReport::NodeResolver::anchor() {} 1216 1217void BugReport::addVisitor(BugReporterVisitor* visitor) { 1218 if (!visitor) 1219 return; 1220 1221 llvm::FoldingSetNodeID ID; 1222 visitor->Profile(ID); 1223 void *InsertPos; 1224 1225 if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) { 1226 delete visitor; 1227 return; 1228 } 1229 1230 CallbacksSet.InsertNode(visitor, InsertPos); 1231 Callbacks = F.add(visitor, Callbacks); 1232} 1233 1234BugReport::~BugReport() { 1235 for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) { 1236 delete *I; 1237 } 1238} 1239 1240void BugReport::Profile(llvm::FoldingSetNodeID& hash) const { 1241 hash.AddPointer(&BT); 1242 hash.AddString(Description); 1243 if (Location.isValid()) { 1244 Location.Profile(hash); 1245 } else { 1246 assert(ErrorNode); 1247 hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode)); 1248 } 1249 1250 for (SmallVectorImpl<SourceRange>::const_iterator I = 1251 Ranges.begin(), E = Ranges.end(); I != E; ++I) { 1252 const SourceRange range = *I; 1253 if (!range.isValid()) 1254 continue; 1255 hash.AddInteger(range.getBegin().getRawEncoding()); 1256 hash.AddInteger(range.getEnd().getRawEncoding()); 1257 } 1258} 1259 1260const Stmt *BugReport::getStmt() const { 1261 if (!ErrorNode) 1262 return 0; 1263 1264 ProgramPoint ProgP = ErrorNode->getLocation(); 1265 const Stmt *S = NULL; 1266 1267 if (BlockEntrance *BE = dyn_cast<BlockEntrance>(&ProgP)) { 1268 CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit(); 1269 if (BE->getBlock() == &Exit) 1270 S = GetPreviousStmt(ErrorNode); 1271 } 1272 if (!S) 1273 S = GetStmt(ProgP); 1274 1275 return S; 1276} 1277 1278std::pair<BugReport::ranges_iterator, BugReport::ranges_iterator> 1279BugReport::getRanges() { 1280 // If no custom ranges, add the range of the statement corresponding to 1281 // the error node. 1282 if (Ranges.empty()) { 1283 if (const Expr *E = dyn_cast_or_null<Expr>(getStmt())) 1284 addRange(E->getSourceRange()); 1285 else 1286 return std::make_pair(ranges_iterator(), ranges_iterator()); 1287 } 1288 1289 // User-specified absence of range info. 1290 if (Ranges.size() == 1 && !Ranges.begin()->isValid()) 1291 return std::make_pair(ranges_iterator(), ranges_iterator()); 1292 1293 return std::make_pair(Ranges.begin(), Ranges.end()); 1294} 1295 1296PathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const { 1297 if (ErrorNode) { 1298 assert(!Location.isValid() && 1299 "Either Location or ErrorNode should be specified but not both."); 1300 1301 if (const Stmt *S = GetCurrentOrPreviousStmt(ErrorNode)) { 1302 const LocationContext *LC = ErrorNode->getLocationContext(); 1303 1304 // For member expressions, return the location of the '.' or '->'. 1305 if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) 1306 return PathDiagnosticLocation::createMemberLoc(ME, SM); 1307 // For binary operators, return the location of the operator. 1308 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) 1309 return PathDiagnosticLocation::createOperatorLoc(B, SM); 1310 1311 return PathDiagnosticLocation::createBegin(S, SM, LC); 1312 } 1313 } else { 1314 assert(Location.isValid()); 1315 return Location; 1316 } 1317 1318 return PathDiagnosticLocation(); 1319} 1320 1321//===----------------------------------------------------------------------===// 1322// Methods for BugReporter and subclasses. 1323//===----------------------------------------------------------------------===// 1324 1325BugReportEquivClass::~BugReportEquivClass() { 1326 for (iterator I=begin(), E=end(); I!=E; ++I) delete *I; 1327} 1328 1329GRBugReporter::~GRBugReporter() { } 1330BugReporterData::~BugReporterData() {} 1331 1332ExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); } 1333 1334ProgramStateManager& 1335GRBugReporter::getStateManager() { return Eng.getStateManager(); } 1336 1337BugReporter::~BugReporter() { 1338 FlushReports(); 1339 1340 // Free the bug reports we are tracking. 1341 typedef std::vector<BugReportEquivClass *> ContTy; 1342 for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end(); 1343 I != E; ++I) { 1344 delete *I; 1345 } 1346} 1347 1348void BugReporter::FlushReports() { 1349 if (BugTypes.isEmpty()) 1350 return; 1351 1352 // First flush the warnings for each BugType. This may end up creating new 1353 // warnings and new BugTypes. 1354 // FIXME: Only NSErrorChecker needs BugType's FlushReports. 1355 // Turn NSErrorChecker into a proper checker and remove this. 1356 SmallVector<const BugType*, 16> bugTypes; 1357 for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) 1358 bugTypes.push_back(*I); 1359 for (SmallVector<const BugType*, 16>::iterator 1360 I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I) 1361 const_cast<BugType*>(*I)->FlushReports(*this); 1362 1363 typedef llvm::FoldingSet<BugReportEquivClass> SetTy; 1364 for (SetTy::iterator EI=EQClasses.begin(), EE=EQClasses.end(); EI!=EE;++EI){ 1365 BugReportEquivClass& EQ = *EI; 1366 FlushReport(EQ); 1367 } 1368 1369 // BugReporter owns and deletes only BugTypes created implicitly through 1370 // EmitBasicReport. 1371 // FIXME: There are leaks from checkers that assume that the BugTypes they 1372 // create will be destroyed by the BugReporter. 1373 for (llvm::StringMap<BugType*>::iterator 1374 I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I) 1375 delete I->second; 1376 1377 // Remove all references to the BugType objects. 1378 BugTypes = F.getEmptySet(); 1379} 1380 1381//===----------------------------------------------------------------------===// 1382// PathDiagnostics generation. 1383//===----------------------------------------------------------------------===// 1384 1385static std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, 1386 std::pair<ExplodedNode*, unsigned> > 1387MakeReportGraph(const ExplodedGraph* G, 1388 SmallVectorImpl<const ExplodedNode*> &nodes) { 1389 1390 // Create the trimmed graph. It will contain the shortest paths from the 1391 // error nodes to the root. In the new graph we should only have one 1392 // error node unless there are two or more error nodes with the same minimum 1393 // path length. 1394 ExplodedGraph* GTrim; 1395 InterExplodedGraphMap* NMap; 1396 1397 llvm::DenseMap<const void*, const void*> InverseMap; 1398 llvm::tie(GTrim, NMap) = G->Trim(nodes.data(), nodes.data() + nodes.size(), 1399 &InverseMap); 1400 1401 // Create owning pointers for GTrim and NMap just to ensure that they are 1402 // released when this function exists. 1403 llvm::OwningPtr<ExplodedGraph> AutoReleaseGTrim(GTrim); 1404 llvm::OwningPtr<InterExplodedGraphMap> AutoReleaseNMap(NMap); 1405 1406 // Find the (first) error node in the trimmed graph. We just need to consult 1407 // the node map (NMap) which maps from nodes in the original graph to nodes 1408 // in the new graph. 1409 1410 std::queue<const ExplodedNode*> WS; 1411 typedef llvm::DenseMap<const ExplodedNode*, unsigned> IndexMapTy; 1412 IndexMapTy IndexMap; 1413 1414 for (unsigned nodeIndex = 0 ; nodeIndex < nodes.size(); ++nodeIndex) { 1415 const ExplodedNode *originalNode = nodes[nodeIndex]; 1416 if (const ExplodedNode *N = NMap->getMappedNode(originalNode)) { 1417 WS.push(N); 1418 IndexMap[originalNode] = nodeIndex; 1419 } 1420 } 1421 1422 assert(!WS.empty() && "No error node found in the trimmed graph."); 1423 1424 // Create a new (third!) graph with a single path. This is the graph 1425 // that will be returned to the caller. 1426 ExplodedGraph *GNew = new ExplodedGraph(); 1427 1428 // Sometimes the trimmed graph can contain a cycle. Perform a reverse BFS 1429 // to the root node, and then construct a new graph that contains only 1430 // a single path. 1431 llvm::DenseMap<const void*,unsigned> Visited; 1432 1433 unsigned cnt = 0; 1434 const ExplodedNode *Root = 0; 1435 1436 while (!WS.empty()) { 1437 const ExplodedNode *Node = WS.front(); 1438 WS.pop(); 1439 1440 if (Visited.find(Node) != Visited.end()) 1441 continue; 1442 1443 Visited[Node] = cnt++; 1444 1445 if (Node->pred_empty()) { 1446 Root = Node; 1447 break; 1448 } 1449 1450 for (ExplodedNode::const_pred_iterator I=Node->pred_begin(), 1451 E=Node->pred_end(); I!=E; ++I) 1452 WS.push(*I); 1453 } 1454 1455 assert(Root); 1456 1457 // Now walk from the root down the BFS path, always taking the successor 1458 // with the lowest number. 1459 ExplodedNode *Last = 0, *First = 0; 1460 NodeBackMap *BM = new NodeBackMap(); 1461 unsigned NodeIndex = 0; 1462 1463 for ( const ExplodedNode *N = Root ;;) { 1464 // Lookup the number associated with the current node. 1465 llvm::DenseMap<const void*,unsigned>::iterator I = Visited.find(N); 1466 assert(I != Visited.end()); 1467 1468 // Create the equivalent node in the new graph with the same state 1469 // and location. 1470 ExplodedNode *NewN = GNew->getNode(N->getLocation(), N->getState()); 1471 1472 // Store the mapping to the original node. 1473 llvm::DenseMap<const void*, const void*>::iterator IMitr=InverseMap.find(N); 1474 assert(IMitr != InverseMap.end() && "No mapping to original node."); 1475 (*BM)[NewN] = (const ExplodedNode*) IMitr->second; 1476 1477 // Link up the new node with the previous node. 1478 if (Last) 1479 NewN->addPredecessor(Last, *GNew); 1480 1481 Last = NewN; 1482 1483 // Are we at the final node? 1484 IndexMapTy::iterator IMI = 1485 IndexMap.find((const ExplodedNode*)(IMitr->second)); 1486 if (IMI != IndexMap.end()) { 1487 First = NewN; 1488 NodeIndex = IMI->second; 1489 break; 1490 } 1491 1492 // Find the next successor node. We choose the node that is marked 1493 // with the lowest DFS number. 1494 ExplodedNode::const_succ_iterator SI = N->succ_begin(); 1495 ExplodedNode::const_succ_iterator SE = N->succ_end(); 1496 N = 0; 1497 1498 for (unsigned MinVal = 0; SI != SE; ++SI) { 1499 1500 I = Visited.find(*SI); 1501 1502 if (I == Visited.end()) 1503 continue; 1504 1505 if (!N || I->second < MinVal) { 1506 N = *SI; 1507 MinVal = I->second; 1508 } 1509 } 1510 1511 assert(N); 1512 } 1513 1514 assert(First); 1515 1516 return std::make_pair(std::make_pair(GNew, BM), 1517 std::make_pair(First, NodeIndex)); 1518} 1519 1520/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object 1521/// and collapses PathDiagosticPieces that are expanded by macros. 1522static void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) { 1523 typedef std::vector<std::pair<PathDiagnosticMacroPiece*, SourceLocation> > 1524 MacroStackTy; 1525 1526 typedef std::vector<PathDiagnosticPiece*> 1527 PiecesTy; 1528 1529 MacroStackTy MacroStack; 1530 PiecesTy Pieces; 1531 1532 for (PathDiagnostic::iterator I = PD.begin(), E = PD.end(); I!=E; ++I) { 1533 // Get the location of the PathDiagnosticPiece. 1534 const FullSourceLoc Loc = I->getLocation().asLocation(); 1535 1536 // Determine the instantiation location, which is the location we group 1537 // related PathDiagnosticPieces. 1538 SourceLocation InstantiationLoc = Loc.isMacroID() ? 1539 SM.getExpansionLoc(Loc) : 1540 SourceLocation(); 1541 1542 if (Loc.isFileID()) { 1543 MacroStack.clear(); 1544 Pieces.push_back(&*I); 1545 continue; 1546 } 1547 1548 assert(Loc.isMacroID()); 1549 1550 // Is the PathDiagnosticPiece within the same macro group? 1551 if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) { 1552 MacroStack.back().first->push_back(&*I); 1553 continue; 1554 } 1555 1556 // We aren't in the same group. Are we descending into a new macro 1557 // or are part of an old one? 1558 PathDiagnosticMacroPiece *MacroGroup = 0; 1559 1560 SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ? 1561 SM.getExpansionLoc(Loc) : 1562 SourceLocation(); 1563 1564 // Walk the entire macro stack. 1565 while (!MacroStack.empty()) { 1566 if (InstantiationLoc == MacroStack.back().second) { 1567 MacroGroup = MacroStack.back().first; 1568 break; 1569 } 1570 1571 if (ParentInstantiationLoc == MacroStack.back().second) { 1572 MacroGroup = MacroStack.back().first; 1573 break; 1574 } 1575 1576 MacroStack.pop_back(); 1577 } 1578 1579 if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) { 1580 // Create a new macro group and add it to the stack. 1581 PathDiagnosticMacroPiece *NewGroup = 1582 new PathDiagnosticMacroPiece( 1583 PathDiagnosticLocation::createSingleLocation(I->getLocation())); 1584 1585 if (MacroGroup) 1586 MacroGroup->push_back(NewGroup); 1587 else { 1588 assert(InstantiationLoc.isFileID()); 1589 Pieces.push_back(NewGroup); 1590 } 1591 1592 MacroGroup = NewGroup; 1593 MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc)); 1594 } 1595 1596 // Finally, add the PathDiagnosticPiece to the group. 1597 MacroGroup->push_back(&*I); 1598 } 1599 1600 // Now take the pieces and construct a new PathDiagnostic. 1601 PD.resetPath(false); 1602 1603 for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) { 1604 if (PathDiagnosticMacroPiece *MP=dyn_cast<PathDiagnosticMacroPiece>(*I)) 1605 if (!MP->containsEvent()) { 1606 delete MP; 1607 continue; 1608 } 1609 1610 PD.push_back(*I); 1611 } 1612} 1613 1614void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, 1615 SmallVectorImpl<BugReport *> &bugReports) { 1616 1617 assert(!bugReports.empty()); 1618 SmallVector<const ExplodedNode *, 10> errorNodes; 1619 for (SmallVectorImpl<BugReport*>::iterator I = bugReports.begin(), 1620 E = bugReports.end(); I != E; ++I) { 1621 errorNodes.push_back((*I)->getErrorNode()); 1622 } 1623 1624 // Construct a new graph that contains only a single path from the error 1625 // node to a root. 1626 const std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, 1627 std::pair<ExplodedNode*, unsigned> >& 1628 GPair = MakeReportGraph(&getGraph(), errorNodes); 1629 1630 // Find the BugReport with the original location. 1631 assert(GPair.second.second < bugReports.size()); 1632 BugReport *R = bugReports[GPair.second.second]; 1633 assert(R && "No original report found for sliced graph."); 1634 1635 llvm::OwningPtr<ExplodedGraph> ReportGraph(GPair.first.first); 1636 llvm::OwningPtr<NodeBackMap> BackMap(GPair.first.second); 1637 const ExplodedNode *N = GPair.second.first; 1638 1639 // Start building the path diagnostic... 1640 PathDiagnosticBuilder PDB(*this, R, BackMap.get(), 1641 getPathDiagnosticConsumer()); 1642 1643 // Register additional node visitors. 1644 R->addVisitor(new NilReceiverBRVisitor()); 1645 R->addVisitor(new ConditionBRVisitor()); 1646 1647 // Generate the very last diagnostic piece - the piece is visible before 1648 // the trace is expanded. 1649 PathDiagnosticPiece *LastPiece = 0; 1650 for (BugReport::visitor_iterator I = R->visitor_begin(), 1651 E = R->visitor_end(); I!=E; ++I) { 1652 if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) { 1653 assert (!LastPiece && 1654 "There can only be one final piece in a diagnostic."); 1655 LastPiece = Piece; 1656 } 1657 } 1658 if (!LastPiece) 1659 LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R); 1660 if (LastPiece) 1661 PD.push_back(LastPiece); 1662 else 1663 return; 1664 1665 switch (PDB.getGenerationScheme()) { 1666 case PathDiagnosticConsumer::Extensive: 1667 GenerateExtensivePathDiagnostic(PD, PDB, N); 1668 break; 1669 case PathDiagnosticConsumer::Minimal: 1670 GenerateMinimalPathDiagnostic(PD, PDB, N); 1671 break; 1672 } 1673} 1674 1675void BugReporter::Register(BugType *BT) { 1676 BugTypes = F.add(BugTypes, BT); 1677} 1678 1679void BugReporter::EmitReport(BugReport* R) { 1680 // Compute the bug report's hash to determine its equivalence class. 1681 llvm::FoldingSetNodeID ID; 1682 R->Profile(ID); 1683 1684 // Lookup the equivance class. If there isn't one, create it. 1685 BugType& BT = R->getBugType(); 1686 Register(&BT); 1687 void *InsertPos; 1688 BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos); 1689 1690 if (!EQ) { 1691 EQ = new BugReportEquivClass(R); 1692 EQClasses.InsertNode(EQ, InsertPos); 1693 EQClassesVector.push_back(EQ); 1694 } 1695 else 1696 EQ->AddReport(R); 1697} 1698 1699 1700//===----------------------------------------------------------------------===// 1701// Emitting reports in equivalence classes. 1702//===----------------------------------------------------------------------===// 1703 1704namespace { 1705struct FRIEC_WLItem { 1706 const ExplodedNode *N; 1707 ExplodedNode::const_succ_iterator I, E; 1708 1709 FRIEC_WLItem(const ExplodedNode *n) 1710 : N(n), I(N->succ_begin()), E(N->succ_end()) {} 1711}; 1712} 1713 1714static BugReport * 1715FindReportInEquivalenceClass(BugReportEquivClass& EQ, 1716 SmallVectorImpl<BugReport*> &bugReports) { 1717 1718 BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end(); 1719 assert(I != E); 1720 BugReport *R = *I; 1721 BugType& BT = R->getBugType(); 1722 1723 // If we don't need to suppress any of the nodes because they are 1724 // post-dominated by a sink, simply add all the nodes in the equivalence class 1725 // to 'Nodes'. Any of the reports will serve as a "representative" report. 1726 if (!BT.isSuppressOnSink()) { 1727 for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) { 1728 const ExplodedNode *N = I->getErrorNode(); 1729 if (N) { 1730 R = *I; 1731 bugReports.push_back(R); 1732 } 1733 } 1734 return R; 1735 } 1736 1737 // For bug reports that should be suppressed when all paths are post-dominated 1738 // by a sink node, iterate through the reports in the equivalence class 1739 // until we find one that isn't post-dominated (if one exists). We use a 1740 // DFS traversal of the ExplodedGraph to find a non-sink node. We could write 1741 // this as a recursive function, but we don't want to risk blowing out the 1742 // stack for very long paths. 1743 BugReport *exampleReport = 0; 1744 1745 for (; I != E; ++I) { 1746 R = *I; 1747 const ExplodedNode *errorNode = R->getErrorNode(); 1748 1749 if (!errorNode) 1750 continue; 1751 if (errorNode->isSink()) { 1752 llvm_unreachable( 1753 "BugType::isSuppressSink() should not be 'true' for sink end nodes"); 1754 } 1755 // No successors? By definition this nodes isn't post-dominated by a sink. 1756 if (errorNode->succ_empty()) { 1757 bugReports.push_back(R); 1758 if (!exampleReport) 1759 exampleReport = R; 1760 continue; 1761 } 1762 1763 // At this point we know that 'N' is not a sink and it has at least one 1764 // successor. Use a DFS worklist to find a non-sink end-of-path node. 1765 typedef FRIEC_WLItem WLItem; 1766 typedef SmallVector<WLItem, 10> DFSWorkList; 1767 llvm::DenseMap<const ExplodedNode *, unsigned> Visited; 1768 1769 DFSWorkList WL; 1770 WL.push_back(errorNode); 1771 Visited[errorNode] = 1; 1772 1773 while (!WL.empty()) { 1774 WLItem &WI = WL.back(); 1775 assert(!WI.N->succ_empty()); 1776 1777 for (; WI.I != WI.E; ++WI.I) { 1778 const ExplodedNode *Succ = *WI.I; 1779 // End-of-path node? 1780 if (Succ->succ_empty()) { 1781 // If we found an end-of-path node that is not a sink. 1782 if (!Succ->isSink()) { 1783 bugReports.push_back(R); 1784 if (!exampleReport) 1785 exampleReport = R; 1786 WL.clear(); 1787 break; 1788 } 1789 // Found a sink? Continue on to the next successor. 1790 continue; 1791 } 1792 // Mark the successor as visited. If it hasn't been explored, 1793 // enqueue it to the DFS worklist. 1794 unsigned &mark = Visited[Succ]; 1795 if (!mark) { 1796 mark = 1; 1797 WL.push_back(Succ); 1798 break; 1799 } 1800 } 1801 1802 // The worklist may have been cleared at this point. First 1803 // check if it is empty before checking the last item. 1804 if (!WL.empty() && &WL.back() == &WI) 1805 WL.pop_back(); 1806 } 1807 } 1808 1809 // ExampleReport will be NULL if all the nodes in the equivalence class 1810 // were post-dominated by sinks. 1811 return exampleReport; 1812} 1813 1814//===----------------------------------------------------------------------===// 1815// DiagnosticCache. This is a hack to cache analyzer diagnostics. It 1816// uses global state, which eventually should go elsewhere. 1817//===----------------------------------------------------------------------===// 1818namespace { 1819class DiagCacheItem : public llvm::FoldingSetNode { 1820 llvm::FoldingSetNodeID ID; 1821public: 1822 DiagCacheItem(BugReport *R, PathDiagnostic *PD) { 1823 R->Profile(ID); 1824 PD->Profile(ID); 1825 } 1826 1827 void Profile(llvm::FoldingSetNodeID &id) { 1828 id = ID; 1829 } 1830 1831 llvm::FoldingSetNodeID &getID() { return ID; } 1832}; 1833} 1834 1835static bool IsCachedDiagnostic(BugReport *R, PathDiagnostic *PD) { 1836 // FIXME: Eventually this diagnostic cache should reside in something 1837 // like AnalysisManager instead of being a static variable. This is 1838 // really unsafe in the long term. 1839 typedef llvm::FoldingSet<DiagCacheItem> DiagnosticCache; 1840 static DiagnosticCache DC; 1841 1842 void *InsertPos; 1843 DiagCacheItem *Item = new DiagCacheItem(R, PD); 1844 1845 if (DC.FindNodeOrInsertPos(Item->getID(), InsertPos)) { 1846 delete Item; 1847 return true; 1848 } 1849 1850 DC.InsertNode(Item, InsertPos); 1851 return false; 1852} 1853 1854void BugReporter::FlushReport(BugReportEquivClass& EQ) { 1855 SmallVector<BugReport*, 10> bugReports; 1856 BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports); 1857 if (!exampleReport) 1858 return; 1859 1860 PathDiagnosticConsumer* PD = getPathDiagnosticConsumer(); 1861 1862 // FIXME: Make sure we use the 'R' for the path that was actually used. 1863 // Probably doesn't make a difference in practice. 1864 BugType& BT = exampleReport->getBugType(); 1865 1866 llvm::OwningPtr<PathDiagnostic> 1867 D(new PathDiagnostic(exampleReport->getBugType().getName(), 1868 !PD || PD->useVerboseDescription() 1869 ? exampleReport->getDescription() 1870 : exampleReport->getShortDescription(), 1871 BT.getCategory())); 1872 1873 if (!bugReports.empty()) 1874 GeneratePathDiagnostic(*D.get(), bugReports); 1875 1876 if (IsCachedDiagnostic(exampleReport, D.get())) 1877 return; 1878 1879 // Get the meta data. 1880 const BugReport::ExtraTextList &Meta = 1881 exampleReport->getExtraText(); 1882 for (BugReport::ExtraTextList::const_iterator i = Meta.begin(), 1883 e = Meta.end(); i != e; ++i) { 1884 D->addMeta(*i); 1885 } 1886 1887 // Emit a summary diagnostic to the regular Diagnostics engine. 1888 BugReport::ranges_iterator Beg, End; 1889 llvm::tie(Beg, End) = exampleReport->getRanges(); 1890 DiagnosticsEngine &Diag = getDiagnostic(); 1891 1892 // Search the description for '%', as that will be interpretted as a 1893 // format character by FormatDiagnostics. 1894 StringRef desc = exampleReport->getShortDescription(); 1895 unsigned ErrorDiag; 1896 { 1897 llvm::SmallString<512> TmpStr; 1898 llvm::raw_svector_ostream Out(TmpStr); 1899 for (StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I) 1900 if (*I == '%') 1901 Out << "%%"; 1902 else 1903 Out << *I; 1904 1905 Out.flush(); 1906 ErrorDiag = Diag.getCustomDiagID(DiagnosticsEngine::Warning, TmpStr); 1907 } 1908 1909 { 1910 DiagnosticBuilder diagBuilder = Diag.Report( 1911 exampleReport->getLocation(getSourceManager()).asLocation(), ErrorDiag); 1912 for (BugReport::ranges_iterator I = Beg; I != End; ++I) 1913 diagBuilder << *I; 1914 } 1915 1916 // Emit a full diagnostic for the path if we have a PathDiagnosticConsumer. 1917 if (!PD) 1918 return; 1919 1920 if (D->empty()) { 1921 PathDiagnosticPiece *piece = new PathDiagnosticEventPiece( 1922 exampleReport->getLocation(getSourceManager()), 1923 exampleReport->getDescription()); 1924 1925 for ( ; Beg != End; ++Beg) piece->addRange(*Beg); 1926 D->push_back(piece); 1927 } 1928 1929 PD->HandlePathDiagnostic(D.take()); 1930} 1931 1932void BugReporter::EmitBasicReport(StringRef name, StringRef str, 1933 PathDiagnosticLocation Loc, 1934 SourceRange* RBeg, unsigned NumRanges) { 1935 EmitBasicReport(name, "", str, Loc, RBeg, NumRanges); 1936} 1937 1938void BugReporter::EmitBasicReport(StringRef name, 1939 StringRef category, 1940 StringRef str, PathDiagnosticLocation Loc, 1941 SourceRange* RBeg, unsigned NumRanges) { 1942 1943 // 'BT' is owned by BugReporter. 1944 BugType *BT = getBugTypeForName(name, category); 1945 BugReport *R = new BugReport(*BT, str, Loc); 1946 for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg); 1947 EmitReport(R); 1948} 1949 1950BugType *BugReporter::getBugTypeForName(StringRef name, 1951 StringRef category) { 1952 llvm::SmallString<136> fullDesc; 1953 llvm::raw_svector_ostream(fullDesc) << name << ":" << category; 1954 llvm::StringMapEntry<BugType *> & 1955 entry = StrBugTypes.GetOrCreateValue(fullDesc); 1956 BugType *BT = entry.getValue(); 1957 if (!BT) { 1958 BT = new BugType(name, category); 1959 entry.setValue(BT); 1960 } 1961 return BT; 1962} 1963