BugReporter.cpp revision 368f3b070e8cb657a65bfa443d60256676d269e7
161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// BugReporter.cpp - Generate PathDiagnostics for Bugs ------------*- C++ -*--// 261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// 361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// The LLVM Compiler Infrastructure 461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// 561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// This file is distributed under the University of Illinois Open Source 661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// License. See LICENSE.TXT for details. 761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// 861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//===----------------------------------------------------------------------===// 961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// 1061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// This file defines BugReporter, a utility class for generating 116c07bdba93b095b66e2c8c82dd5ed458fa8285eaTed Kremenek// PathDiagnostics. 1261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// 1361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//===----------------------------------------------------------------------===// 1461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 159b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 169b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 179b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 1861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/AST/ASTContext.h" 19e41611aa2237d06a0ef61db4528fb2883a8defcdTed Kremenek#include "clang/Analysis/CFG.h" 20c35fb7d67d515659ad2325b4f6ec97c9fe64fb63Benjamin Kramer#include "clang/AST/DeclObjC.h" 2161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/AST/Expr.h" 2200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek#include "clang/AST/ParentMap.h" 2316f0049415ec596504891259e2a83e19871c0d52Chris Lattner#include "clang/AST/StmtObjC.h" 2416f0049415ec596504891259e2a83e19871c0d52Chris Lattner#include "clang/Basic/SourceManager.h" 2561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/Analysis/ProgramPoint.h" 269b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 27405674c26c52b05df0d833fae6bae818cd52bc32Chris Lattner#include "llvm/Support/raw_ostream.h" 28331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek#include "llvm/ADT/DenseMap.h" 298fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h" 30cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek#include "llvm/ADT/STLExtras.h" 3100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek#include "llvm/ADT/OwningPtr.h" 32802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek#include "llvm/ADT/IntrusiveRefCntPtr.h" 3310aa55410bbecbb658ce14a5f801d50cf06d12dfTed Kremenek#include <queue> 3461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 3561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenekusing namespace clang; 369ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 3761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 388966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed KremenekBugReporterVisitor::~BugReporterVisitor() {} 391b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek 4099ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BugReporterContext::anchor() {} 4199ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 42cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Helper routines for walking the ExplodedGraph and fetching statements. 44cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 4561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 469c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic inline const Stmt *GetStmt(const ProgramPoint &P) { 47592362b46ad69db0db0988e7f9d8cbe647510bddTed Kremenek if (const StmtPoint* SP = dyn_cast<StmtPoint>(&P)) 48592362b46ad69db0db0988e7f9d8cbe647510bddTed Kremenek return SP->getStmt(); 499c378f705405d37f49795d5e915989de774fe11fTed Kremenek else if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) 5061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek return BE->getSrc()->getTerminator(); 51852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose else if (const CallEnter *CE = dyn_cast<CallEnter>(&P)) 52852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose return CE->getCallExpr(); 53852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose else if (const CallExitEnd *CEE = dyn_cast<CallExitEnd>(&P)) 54852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose return CEE->getCalleeContext()->getCallSite(); 551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 56b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return 0; 5761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 5861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 59c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic inline const ExplodedNode* 609c378f705405d37f49795d5e915989de774fe11fTed KremenekGetPredecessorNode(const ExplodedNode *N) { 61b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return N->pred_empty() ? NULL : *(N->pred_begin()); 62706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek} 63706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek 64c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic inline const ExplodedNode* 659c378f705405d37f49795d5e915989de774fe11fTed KremenekGetSuccessorNode(const ExplodedNode *N) { 66b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return N->succ_empty() ? NULL : *(N->succ_begin()); 67bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek} 682673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek 699c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic const Stmt *GetPreviousStmt(const ExplodedNode *N) { 70b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek for (N = GetPredecessorNode(N); N; N = GetPredecessorNode(N)) 715f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) 72b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 74b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return 0; 75b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek} 76b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek 779c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic const Stmt *GetNextStmt(const ExplodedNode *N) { 78b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek for (N = GetSuccessorNode(N); N; N = GetSuccessorNode(N)) 795f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) { 80f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek // Check if the statement is '?' or '&&'/'||'. These are "merges", 81f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek // not actual statement points. 82f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek switch (S->getStmtClass()) { 83f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek case Stmt::ChooseExprClass: 8456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: continue; 85f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek case Stmt::ConditionalOperatorClass: continue; 86f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek case Stmt::BinaryOperatorClass: { 872de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode(); 882de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (Op == BO_LAnd || Op == BO_LOr) 89f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek continue; 90f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek break; 91f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 92f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek default: 93f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek break; 94f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 95b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 96f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return 0; 99bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek} 100bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek 1015f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt* 1029c378f705405d37f49795d5e915989de774fe11fTed KremenekGetCurrentOrPreviousStmt(const ExplodedNode *N) { 1035f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) 104b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 1051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 106b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return GetPreviousStmt(N); 107b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek} 1081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1095f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt* 1109c378f705405d37f49795d5e915989de774fe11fTed KremenekGetCurrentOrNextStmt(const ExplodedNode *N) { 1115f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) 112b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 1131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 114b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return GetNextStmt(N); 1153148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek} 1163148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek 117b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 118c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek// Diagnostic cleanup. 119c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek//===----------------------------------------------------------------------===// 120c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 121b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenekstatic PathDiagnosticEventPiece * 122b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted KremenekeventsDescribeSameCondition(PathDiagnosticEventPiece *X, 123b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek PathDiagnosticEventPiece *Y) { 124b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // Prefer diagnostics that come from ConditionBRVisitor over 125b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // those that came from TrackConstraintBRVisitor. 126b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek const void *tagPreferred = ConditionBRVisitor::getTag(); 127b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek const void *tagLesser = TrackConstraintBRVisitor::getTag(); 128b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 129b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (X->getLocation() != Y->getLocation()) 130b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return 0; 131b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 132b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (X->getTag() == tagPreferred && Y->getTag() == tagLesser) 133b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return X; 134b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 135b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (Y->getTag() == tagPreferred && X->getTag() == tagLesser) 136b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return Y; 137b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 138b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return 0; 139b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek} 140b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 1413800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// An optimization pass over PathPieces that removes redundant diagnostics 1423800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// generated by both ConditionBRVisitor and TrackConstraintBRVisitor. Both 1433800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// BugReporterVisitors use different methods to generate diagnostics, with 1443800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// one capable of emitting diagnostics in some cases but not in others. This 1453800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// can lead to redundant diagnostic pieces at the same point in a path. 1463800165e56107df7430520aa98afdf7065db2dd2Ted Kremenekstatic void removeRedundantMsgs(PathPieces &path) { 147b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek unsigned N = path.size(); 148b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (N < 2) 149b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return; 1503800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek // NOTE: this loop intentionally is not using an iterator. Instead, we 1513800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek // are streaming the path and modifying it in place. This is done by 1523800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek // grabbing the front, processing it, and if we decide to keep it append 1533800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek // it to the end of the path. The entire path is processed in this way. 154b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek for (unsigned i = 0; i < N; ++i) { 155b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek IntrusiveRefCntPtr<PathDiagnosticPiece> piece(path.front()); 156b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek path.pop_front(); 157b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 158b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek switch (piece->getKind()) { 159b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek case clang::ento::PathDiagnosticPiece::Call: 1603800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek removeRedundantMsgs(cast<PathDiagnosticCallPiece>(piece)->path); 161b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 162b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek case clang::ento::PathDiagnosticPiece::Macro: 1633800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek removeRedundantMsgs(cast<PathDiagnosticMacroPiece>(piece)->subPieces); 164b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 165b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek case clang::ento::PathDiagnosticPiece::ControlFlow: 166b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 167b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek case clang::ento::PathDiagnosticPiece::Event: { 168b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (i == N-1) 169b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 170b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 171b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (PathDiagnosticEventPiece *nextEvent = 172b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek dyn_cast<PathDiagnosticEventPiece>(path.front().getPtr())) { 173b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek PathDiagnosticEventPiece *event = 174b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek cast<PathDiagnosticEventPiece>(piece); 175b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // Check to see if we should keep one of the two pieces. If we 176b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // come up with a preference, record which piece to keep, and consume 177b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // another piece from the path. 178b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (PathDiagnosticEventPiece *pieceToKeep = 179b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek eventsDescribeSameCondition(event, nextEvent)) { 180b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek piece = pieceToKeep; 181b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek path.pop_front(); 182b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek ++i; 183b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 184b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 185b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 186b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 187b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 188b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek path.push_back(piece); 189b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 190b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek} 191b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 192c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// Recursively scan through a path and prune out calls and macros pieces 193c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// that aren't needed. Return true if afterwards the path contains 194c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// "interesting stuff" which means it should be pruned from the parent path. 195a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenekbool BugReporter::RemoveUneededCalls(PathPieces &pieces, BugReport *R, 196368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose PathDiagnosticLocation *LastCallLocation) { 197c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek bool containsSomethingInteresting = false; 198c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek const unsigned N = pieces.size(); 199c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 200c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek for (unsigned i = 0 ; i < N ; ++i) { 201c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek // Remove the front piece from the path. If it is still something we 202c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek // want to keep once we are done, we will push it back on the end. 203c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek IntrusiveRefCntPtr<PathDiagnosticPiece> piece(pieces.front()); 204c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek pieces.pop_front(); 205c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 206a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek // Throw away pieces with invalid locations. 207a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek if (piece->getKind() != PathDiagnosticPiece::Call && 208a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek piece->getLocation().asLocation().isInvalid()) 209a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek continue; 210a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 211725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek switch (piece->getKind()) { 212725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Call: { 213725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticCallPiece *call = cast<PathDiagnosticCallPiece>(piece); 21480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Check if the location context is interesting. 21580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks assert(LocationContextMap.count(call)); 21680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (R->isInteresting(LocationContextMap[call])) { 21780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks containsSomethingInteresting = true; 21880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 21980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 220368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose 221368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose if (LastCallLocation) { 222368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose if (!call->callEnter.asLocation().isValid()) 223368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose call->callEnter = *LastCallLocation; 224368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose if (!call->callReturn.asLocation().isValid()) 225368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose call->callReturn = *LastCallLocation; 226368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose } 227368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose 228725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // Recursively clean out the subclass. Keep this call around if 229725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // it contains any informative diagnostics. 230368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose if (call->callEnterWithin.asLocation().isValid()) 231368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose LastCallLocation = &call->callEnterWithin; 232368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose else 233368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose LastCallLocation = &call->callEnter; 234a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 235368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose assert(LastCallLocation && "Outermost call has an invalid location"); 236368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose if (!RemoveUneededCalls(call->path, R, LastCallLocation)) 237368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose continue; 238a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 239725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek containsSomethingInteresting = true; 240725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 241725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 242725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Macro: { 243725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticMacroPiece *macro = cast<PathDiagnosticMacroPiece>(piece); 24480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!RemoveUneededCalls(macro->subPieces, R)) 245725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek continue; 246c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek containsSomethingInteresting = true; 247725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 248725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 249725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Event: { 250725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticEventPiece *event = cast<PathDiagnosticEventPiece>(piece); 251a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 252725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // We never throw away an event, but we do throw it away wholesale 253725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // as part of a path if we throw the entire path away. 25422505ef15e32db31a4f834a387cf73a913bc8f66Ted Kremenek containsSomethingInteresting |= !event->isPrunable(); 255725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 256725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 257725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::ControlFlow: 258725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 259c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek } 260c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 261c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek pieces.push_back(piece); 262c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek } 263c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 264c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek return containsSomethingInteresting; 265c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek} 266c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 267c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek//===----------------------------------------------------------------------===// 2683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnosticBuilder and its associated routines and helper objects. 269b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 270b479dadea93b93d3f0a335c3518b703f140b3f50Ted Kremenek 271c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xutypedef llvm::DenseMap<const ExplodedNode*, 272c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuconst ExplodedNode*> NodeBackMap; 2737dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek 274babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremeneknamespace { 275ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NodeMapClosure : public BugReport::NodeResolver { 2767dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeBackMap& M; 2777dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenekpublic: 2787dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeMapClosure(NodeBackMap *m) : M(*m) {} 2797dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek ~NodeMapClosure() {} 2801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2819c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *getOriginalNode(const ExplodedNode *N) { 2827dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeBackMap::iterator I = M.find(N); 2837dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek return I == M.end() ? 0 : I->second; 2847dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 2857dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek}; 2861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 287ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass PathDiagnosticBuilder : public BugReporterContext { 2887dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek BugReport *R; 289ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *PDC; 2906f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<ParentMap> PM; 2917dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeMapClosure NMC; 2921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic: 29359950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek const LocationContext *LC; 29459950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 2958966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek PathDiagnosticBuilder(GRBugReporter &br, 2961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump BugReport *r, NodeBackMap *Backmap, 297ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *pdc) 2988966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek : BugReporterContext(br), 29959950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek R(r), PDC(pdc), NMC(Backmap), LC(r->getErrorNode()->getLocationContext()) 30059950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek {} 3011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3029c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N); 3031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3049c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os, 3059c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N); 3061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3078e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *getBugReport() { return R; } 3088e6431adab313e283a992698f6fc7afe62420999Anna Zaks 309212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); } 31059950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 31159950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek ParentMap& getParentMap() { return LC->getParentMap(); } 3121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 313c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek const Stmt *getParent(const Stmt *S) { 314c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek return getParentMap().getParent(S); 315c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek } 3161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3178966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek virtual NodeMapClosure& getNodeResolver() { return NMC; } 3187297134f128423fce2e88f92421ed135bded7d4eDouglas Gregor 319d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S); 3201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 321ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const { 322ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive; 3237dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 3247dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek 325babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek bool supportsLogicalOpControlFlow() const { 326babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek return PDC ? PDC->supportsLogicalOpControlFlow() : true; 3271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 328babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek}; 329babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek} // end anonymous namespace 330babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 33100605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 3329c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) { 3335f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetNextStmt(N)) 33459950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek return PathDiagnosticLocation(S, getSourceManager(), LC); 33500605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek 3360cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return PathDiagnosticLocation::createDeclEnd(N->getLocationContext(), 3370cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks getSourceManager()); 338082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek} 3391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 34000605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 3419c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os, 3429c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N) { 343babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 344143ca222583a4a355fdc89af852deef287499300Ted Kremenek // Slow, but probably doesn't matter. 345b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek if (os.str().empty()) 346b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << ' '; 3471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 34800605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek const PathDiagnosticLocation &Loc = ExecutionContinues(N); 3491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 35000605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek if (Loc.asStmt()) 351b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << "Execution continues on line " 352642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << getSourceManager().getExpansionLineNumber(Loc.asLocation()) 3538966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek << '.'; 3544f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 3554f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "Execution jumps to the end of the "; 3564f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek const Decl *D = N->getLocationContext()->getDecl(); 3574f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek if (isa<ObjCMethodDecl>(D)) 3584f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "method"; 3594f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else if (isa<FunctionDecl>(D)) 3604f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "function"; 3614f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 3624f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek assert(isa<BlockDecl>(D)); 3634f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "anonymous block"; 3644f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 3654f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << '.'; 3664f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 3671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 368082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek return Loc; 369143ca222583a4a355fdc89af852deef287499300Ted Kremenek} 370143ca222583a4a355fdc89af852deef287499300Ted Kremenek 371ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenekstatic bool IsNested(const Stmt *S, ParentMap &PM) { 372ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S))) 373ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek return true; 3741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 375ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const Stmt *Parent = PM.getParentIgnoreParens(S); 3761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 377ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (Parent) 378ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek switch (Parent->getStmtClass()) { 379ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::ForStmtClass: 380ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::DoStmtClass: 381ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::WhileStmtClass: 382ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek return true; 383ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek default: 384ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek break; 385ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek } 3861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 388ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek} 389ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek 390d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticLocation 391d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { 3929c378f705405d37f49795d5e915989de774fe11fTed Kremenek assert(S && "Null Stmt *passed to getEnclosingStmtLocation"); 3931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ParentMap &P = getParentMap(); 3948966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek SourceManager &SMgr = getSourceManager(); 395e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 396ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek while (IsNested(S, P)) { 3978c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const Stmt *Parent = P.getParentIgnoreParens(S); 3981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 399af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (!Parent) 400af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 4011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 402af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek switch (Parent->getStmtClass()) { 4035fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek case Stmt::BinaryOperatorClass: { 4045fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const BinaryOperator *B = cast<BinaryOperator>(Parent); 4055fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 406220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 4075fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek break; 4081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 409af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::CompoundStmtClass: 410af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::StmtExprClass: 411220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 4121d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ChooseExprClass: 4131d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // Similar to '?' if we are referring to condition, just have the edge 4141d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // point to the entire choose expression. 4151d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (cast<ChooseExpr>(Parent)->getCond() == S) 416220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 4171d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 418220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 41956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 4201d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ConditionalOperatorClass: 4211d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // For '?', if we are referring to condition, just have the edge point 4221d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // to the entire '?' expression. 42356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (cast<AbstractConditionalOperator>(Parent)->getCond() == S) 424220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 4251d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 426220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 427af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::DoStmtClass: 428220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 429af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ForStmtClass: 430af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ForStmt>(Parent)->getBody() == S) 431220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 4321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump break; 433af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::IfStmtClass: 434af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<IfStmt>(Parent)->getCond() != S) 435220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 4368bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek break; 437af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 438af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S) 439220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 440af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 441af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::WhileStmtClass: 442af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<WhileStmt>(Parent)->getCond() != S) 443220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 444af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 445af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek default: 446af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 447af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek } 448af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek 449d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek S = Parent; 450d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek } 4511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 452d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek assert(S && "Cannot have null Stmt for PathDiagnosticLocation"); 453e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 454e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // Special case: DeclStmts can appear in for statement declarations, in which 455e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // case the ForStmt is the context. 456e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (isa<DeclStmt>(S)) { 457e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (const Stmt *Parent = P.getParent(S)) { 458e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek switch (Parent->getStmtClass()) { 459e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek case Stmt::ForStmtClass: 460e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 461220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 462e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek default: 463e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek break; 4641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 4651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 466e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 467e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek else if (isa<BinaryOperator>(S)) { 468e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // Special case: the binary operator represents the initialization 469e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // code in a for statement (this can happen when the variable being 470e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // initialized is an old variable. 471e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (const ForStmt *FS = 472e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek dyn_cast_or_null<ForStmt>(P.getParentIgnoreParens(S))) { 473e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (FS->getInit() == S) 474220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(FS, SMgr, LC); 475e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 476e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 477e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 478220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 479d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek} 480d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 481cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 482d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose// "Visitors only" path diagnostic generation algorithm. 483d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose//===----------------------------------------------------------------------===// 484d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rosestatic bool GenerateVisitorsOnlyPathDiagnostic(PathDiagnostic &PD, 485d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose PathDiagnosticBuilder &PDB, 486d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose const ExplodedNode *N, 487d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose ArrayRef<BugReporterVisitor *> visitors) { 488d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // All path generation skips the very first node (the error node). 489d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // This is because there is special handling for the end-of-path note. 490d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose N = N->getFirstPred(); 491d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!N) 492d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return true; 493d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 494d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose BugReport *R = PDB.getBugReport(); 495d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose while (const ExplodedNode *Pred = N->getFirstPred()) { 496d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 497d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose E = visitors.end(); 498d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose I != E; ++I) { 499d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // Visit all the node pairs, but throw the path pieces away. 500d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose PathDiagnosticPiece *Piece = (*I)->VisitNode(N, Pred, PDB, *R); 501d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose delete Piece; 502d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose } 503d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 504d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose N = Pred; 505d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose } 506d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 507d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return R->isValid(); 508d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose} 509d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 510d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose//===----------------------------------------------------------------------===// 5113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// "Minimal" path diagnostic generation algorithm. 512cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 51356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zakstypedef std::pair<PathDiagnosticCallPiece*, const ExplodedNode*> StackDiagPair; 51456a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zakstypedef SmallVector<StackDiagPair, 6> StackDiagVector; 51556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 516368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaksstatic void updateStackPiecesWithMessage(PathDiagnosticPiece *P, 51756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector &CallStack) { 518368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // If the piece contains a special message, add it to all the call 519368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // pieces on the active stack. 520368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (PathDiagnosticEventPiece *ep = 521368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks dyn_cast<PathDiagnosticEventPiece>(P)) { 522368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 52356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (ep->hasCallStackHint()) 52456a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks for (StackDiagVector::iterator I = CallStack.begin(), 52556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks E = CallStack.end(); I != E; ++I) { 52656a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks PathDiagnosticCallPiece *CP = I->first; 52756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks const ExplodedNode *N = I->second; 5288fe4525680ce72e90cee3e58b5654e3ae955447fNAKAMURA Takumi std::string stackMsg = ep->getCallStackMessage(N); 52956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 530368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // The last message on the path to final bug is the most important 531368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // one. Since we traverse the path backwards, do not add the message 532368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // if one has been previously added. 53356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (!CP->hasCallStackMessage()) 53456a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks CP->setCallStackMessage(stackMsg); 53556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks } 536368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 537368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks} 538cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 53977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM); 54014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 5418347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosestatic bool GenerateMinimalPathDiagnostic(PathDiagnostic& PD, 5423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticBuilder &PDB, 5433bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose const ExplodedNode *N, 5443bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ArrayRef<BugReporterVisitor *> visitors) { 5458966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek 5463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceManager& SMgr = PDB.getSourceManager(); 54759950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek const LocationContext *LC = PDB.LC; 5489c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() 5493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek ? NULL : *(N->pred_begin()); 550368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 55156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector CallStack; 552368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 5533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (NextNode) { 5541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump N = NextNode; 55559950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC = N->getLocationContext(); 5563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NextNode = GetPredecessorNode(N); 5571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 55861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek ProgramPoint P = N->getLocation(); 55980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 56080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks do { 56180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (const CallExitEnd *CE = dyn_cast<CallExitEnd>(&P)) { 56280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece *C = 56380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece::construct(N, *CE, SMgr); 56480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GRBugReporter& BR = PDB.getBugReporter(); 56580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks BR.addCallPieceLocationContextPair(C, CE->getCalleeContext()); 56680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(C); 56780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.pushActivePath(&C->path); 56880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks CallStack.push_back(StackDiagPair(C, N)); 56980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 5709373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks } 571183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 57280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (const CallEnter *CE = dyn_cast<CallEnter>(&P)) { 57380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Flush all locations, and pop the active path. 57480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks bool VisitedEntireCall = PD.isWithinCall(); 57580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.popActivePath(); 57680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 57780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Either we just added a bunch of stuff to the top-level path, or 57880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // we have a previous CallExitEnd. If the former, it means that the 57980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // path terminated within a function call. We must then take the 58080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // current contents of the active path and place it within 58180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // a new PathDiagnosticCallPiece. 58280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece *C; 58380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (VisitedEntireCall) { 58480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 58580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } else { 58680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Decl *Caller = CE->getLocationContext()->getDecl(); 58780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 58880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GRBugReporter& BR = PDB.getBugReporter(); 58980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks BR.addCallPieceLocationContextPair(C, CE->getCalleeContext()); 59080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 59180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 59280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C->setCallee(*CE, SMgr); 59380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!CallStack.empty()) { 59480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks assert(CallStack.back().first == C); 59580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks CallStack.pop_back(); 59680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 59780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 598368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 5991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 60080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 60180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CFGBlock *Src = BE->getSrc(); 60280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CFGBlock *Dst = BE->getDst(); 60380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Stmt *T = Src->getTerminator(); 6041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 60580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!T) 60680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 6071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 60880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation Start = 60980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createBegin(T, SMgr, 61080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks N->getLocationContext()); 6111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 61280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks switch (T->getStmtClass()) { 61361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek default: 61461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 6151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 61661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek case Stmt::GotoStmtClass: 6171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::IndirectGotoStmtClass: { 6189c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Stmt *S = GetNextStmt(N); 6191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 62061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek if (!S) 62180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 6221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 623297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 6241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::raw_string_ostream os(sbuf); 625d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S); 6261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 62700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os << "Control jumps to line " 62880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 62980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 63080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 63161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 63261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 6331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::SwitchStmtClass: { 63561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek // Figure out what case arm we took. 636297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 637297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 6381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6399c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const Stmt *S = Dst->getLabel()) { 640220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(S, SMgr, LC); 6411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6425a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek switch (S->getStmtClass()) { 64380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks default: 64480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "No cases match in the switch statement. " 64580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks "Control jumps to line " 64680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 64780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 64880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks case Stmt::DefaultStmtClass: 64980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "Control jumps to the 'default' case at line " 65080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 65180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 65280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 65380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks case Stmt::CaseStmtClass: { 65480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "Control jumps to 'case "; 65580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CaseStmt *Case = cast<CaseStmt>(S); 65680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Expr *LHS = Case->getLHS()->IgnoreParenCasts(); 65780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 65880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine if it is an enum. 65980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks bool GetRawInt = true; 66080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 66180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) { 66280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // FIXME: Maybe this should be an assertion. Are there cases 66380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // were it is not an EnumConstantDecl? 66480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const EnumConstantDecl *D = 66503509aea098772644bf4662dc1c88634818ceeccZhongxing Xu dyn_cast<EnumConstantDecl>(DR->getDecl()); 6661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 66780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (D) { 66880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GetRawInt = false; 66980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << *D; 6705a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek } 67180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 6729ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 67380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (GetRawInt) 67480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << LHS->EvaluateKnownConstInt(PDB.getASTContext()); 6759ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 67680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << ":' at line " 67780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 67880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 67961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 68080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 68180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 68280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 68361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 684567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek else { 685c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "'Default' branch taken. "; 6861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N); 68780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 68880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 689567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek } 6901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 69161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 69261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 6931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6942673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::BreakStmtClass: 6952673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::ContinueStmtClass: { 696297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 697297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 69800605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 69980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 70080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 7012673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek break; 7022673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek } 7031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 70480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine control-flow for ternary '?'. 70556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 706706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek case Stmt::ConditionalOperatorClass: { 707297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 708297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 7091d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek os << "'?' condition is "; 7101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 711706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()+1) == Dst) 712082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "false"; 713706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek else 714082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "true"; 7151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 71600605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7181d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (const Stmt *S = End.asStmt()) 7191d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 7201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 72180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 72280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 723babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 724babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 7251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 72680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine control-flow for short-circuited '&&' and '||'. 727babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek case Stmt::BinaryOperatorClass: { 728babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek if (!PDB.supportsLogicalOpControlFlow()) 729babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 7301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 73103509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const BinaryOperator *B = cast<BinaryOperator>(T); 732babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek std::string sbuf; 733babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek llvm::raw_string_ostream os(sbuf); 734babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek os << "Left side of '"; 7351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7362de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_LAnd) { 737f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "&&" << "' is "; 7381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 739f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 740f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 741220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 7420cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 74380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 74480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 74580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 7461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 747f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 748f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 749220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 750f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 75180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 75280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 7531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 754babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 755babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek else { 7562de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(B->getOpcode() == BO_LOr); 757f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "||" << "' is "; 7581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 759f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 760f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 761220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 762f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 76380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 76480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 765f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 766f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 767f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 768220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 7690cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 77080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 77180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 77280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 773f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 774babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 7751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 776706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek break; 777706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek } 7781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::DoStmtClass: { 780706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()) == Dst) { 781297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 782297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 7831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 784c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "Loop condition is true. "; 785d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 7861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 787d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 788d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 7891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 79080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 79180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 792082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 793082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek else { 79400605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 796d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 797d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 7981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 79980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 80080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Loop condition is false. Exiting loop")); 8013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 8043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::WhileStmtClass: 8071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::ForStmtClass: { 8083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) { 8093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::string sbuf; 8103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::raw_string_ostream os(sbuf); 8111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek os << "Loop condition is false. "; 8133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 8143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 8153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 8161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 81780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 81880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 8193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 8213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 8223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 8233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 8241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 82580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 82680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Loop condition is true. Entering loop body")); 8273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 8303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::IfStmtClass: { 8333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 8341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 8363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 8371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) 83980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 84080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Taking false branch")); 8411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else 84280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 84380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Taking true branch")); 8441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 8463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 84780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 8483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 84980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } while(0); 8501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 851dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (NextNode) { 8528e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add diagnostic pieces from custom visitors. 8538e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 8543bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 8553bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = visitors.end(); 8563bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose I != E; ++I) { 857368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 8582042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 859368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks updateStackPiecesWithMessage(p, CallStack); 860368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 861dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 8628966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 8633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8658347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose if (!PDB.getBugReport()->isValid()) 8668347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return false; 8678347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 86814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // After constructing the full PathDiagnostic, do a pass over it to compact 86914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // PathDiagnosticPieces that occur within a macro. 87077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager()); 8718347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return true; 8723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 8733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 8743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 8755fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek// "Extensive" PathDiagnostic generation. 8765fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 8775fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 8785fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenekstatic bool IsControlFlowExpr(const Stmt *S) { 8795fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const Expr *E = dyn_cast<Expr>(S); 8801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8815fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (!E) 8825fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return false; 8831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump E = E->IgnoreParenCasts(); 8851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 88656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (isa<AbstractConditionalOperator>(E)) 8875fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 8881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8895fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) 8905fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 8915fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 8921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 8945fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek} 8955fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 89614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremeneknamespace { 897ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ContextLocation : public PathDiagnosticLocation { 8988f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsDead; 8998f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekpublic: 9008f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation(const PathDiagnosticLocation &L, bool isdead = false) 9018f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek : PathDiagnosticLocation(L), IsDead(isdead) {} 9021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void markDead() { IsDead = true; } 9048f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool isDead() const { return IsDead; } 9058f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek}; 9061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 907ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass EdgeBuilder { 9088f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek std::vector<ContextLocation> CLocs; 9098f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek typedef std::vector<ContextLocation>::iterator iterator; 91014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnostic &PD; 91114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB; 91214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation PrevLoc; 9131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9148f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsConsumedExpr(const PathDiagnosticLocation &L); 9151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 91614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek bool containsLocation(const PathDiagnosticLocation &Container, 91714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee); 9181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 91914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L); 9201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9219650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L, 9229650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek bool firstCharOnly = false) { 9238c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (const Stmt *S = L.asStmt()) { 9249650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek const Stmt *Original = S; 9258c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek while (1) { 9268c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek // Adjust the location for some expressions that are best referenced 9278c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek // by one of their subexpressions. 9289650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek switch (S->getStmtClass()) { 9299650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek default: 9309650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek break; 9319650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ParenExprClass: 932f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne case Stmt::GenericSelectionExprClass: 933f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne S = cast<Expr>(S)->IgnoreParens(); 9349650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 9359650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 93656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 9379650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ConditionalOperatorClass: 93856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall S = cast<AbstractConditionalOperator>(S)->getCond(); 9399650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 9409650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 9419650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ChooseExprClass: 9429650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek S = cast<ChooseExpr>(S)->getCond(); 9439650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 9449650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 9459650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::BinaryOperatorClass: 9469650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek S = cast<BinaryOperator>(S)->getLHS(); 9479650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 9489650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 9499650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek } 9501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9519650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek break; 9528c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 9531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9549650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek if (S != Original) 95559950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek L = PathDiagnosticLocation(S, L.getManager(), PDB.LC); 9568c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 9571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9589650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek if (firstCharOnly) 9591531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks L = PathDiagnosticLocation::createSingleLocation(L); 9609650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek 9618c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek return L; 9628c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 9631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 96414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void popLocation() { 9658f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) { 9665c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // For contexts, we only one the first character as the range. 96707c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek rawAddEdge(cleanUpLocation(CLocs.back(), true)); 9685c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek } 96914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.pop_back(); 97014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 9711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 97214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekpublic: 97314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb) 97414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek : PD(pd), PDB(pdb) { 9751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 976a301a6773db085575ac51e3c966858180390c25bTed Kremenek // If the PathDiagnostic already has pieces, add the enclosing statement 977a301a6773db085575ac51e3c966858180390c25bTed Kremenek // of the first piece as a context as well. 978802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek if (!PD.path.empty()) { 979802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek PrevLoc = (*PD.path.begin())->getLocation(); 9801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = PrevLoc.asStmt()) 982e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 98314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 98414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 98514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 98614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ~EdgeBuilder() { 98714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) popLocation(); 9880cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 989a301a6773db085575ac51e3c966858180390c25bTed Kremenek // Finally, add an initial edge from the start location of the first 990a301a6773db085575ac51e3c966858180390c25bTed Kremenek // statement (if it doesn't already exist). 9910cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin( 99259950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC, 9930cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PDB.getSourceManager()); 9940cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks if (L.isValid()) 9950cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks rawAddEdge(L); 99614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 99714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 9985de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek void flushLocations() { 9995de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek while (!CLocs.empty()) 10005de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek popLocation(); 10015de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek PrevLoc = PathDiagnosticLocation(); 10025de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek } 10035de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 100414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false); 10051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10068bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek void rawAddEdge(PathDiagnosticLocation NewLoc); 10071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 100814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addContext(const Stmt *S); 1009183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose void addContext(const PathDiagnosticLocation &L); 1010e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek void addExtendedContext(const Stmt *S); 10111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}; 101214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} // end anonymous namespace 101314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 101414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 101514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekPathDiagnosticLocation 101614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekEdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) { 101714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = L.asStmt()) { 101814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (IsControlFlowExpr(S)) 101914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 10201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return PDB.getEnclosingStmtLocation(S); 102214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 10231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 102414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 102514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 102614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 102714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekbool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container, 102814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee) { 102914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 103014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container == Containee) 103114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 10321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 103314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container.asDecl()) 103414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 10351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 103614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = Containee.asStmt()) 103714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *ContainerS = Container.asStmt()) { 103814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (S) { 103914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (S == ContainerS) 104014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 104114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek S = PDB.getParent(S); 104214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 104314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return false; 104414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 104514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 104614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Less accurate: compare using source ranges. 104714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContainerR = Container.asRange(); 104814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContaineeR = Containee.asRange(); 10491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 105014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceManager &SM = PDB.getSourceManager(); 1051402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin()); 1052402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd()); 1053402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin()); 1054402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd()); 10551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1056642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg); 1057642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd); 1058642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg); 1059642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd); 10601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 106114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek assert(ContainerBegLine <= ContainerEndLine); 10621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(ContaineeBegLine <= ContaineeEndLine); 10631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 106414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return (ContainerBegLine <= ContaineeBegLine && 106514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ContainerEndLine >= ContaineeEndLine && 106614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerBegLine != ContaineeBegLine || 1067a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerRBeg) <= 1068a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContaineeRBeg)) && 106914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerEndLine != ContaineeEndLine || 1070a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerREnd) >= 10716488dc31153be6f98b404c7860be6c66bb4ec917Ted Kremenek SM.getExpansionColumnNumber(ContaineeREnd))); 107214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 107314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 107414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) { 107514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!PrevLoc.isValid()) { 107614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PrevLoc = NewLoc; 107714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 107814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 10791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10808c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc); 10818c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc); 10821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1083a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek if (PrevLocClean.asLocation().isInvalid()) { 1084a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek PrevLoc = NewLoc; 1085a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek return; 1086a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek } 1087a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 10888c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (NewLocClean.asLocation() == PrevLocClean.asLocation()) 108914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 10901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 109114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // FIXME: Ignore intra-macro edges for now. 1092402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth if (NewLocClean.asLocation().getExpansionLoc() == 1093402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth PrevLocClean.asLocation().getExpansionLoc()) 109414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 109514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 10962042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean)); 10978c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek PrevLoc = NewLoc; 109814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 109914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 110014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) { 11011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1102a301a6773db085575ac51e3c966858180390c25bTed Kremenek if (!alwaysAdd && NewLoc.asLocation().isMacroID()) 1103a301a6773db085575ac51e3c966858180390c25bTed Kremenek return; 11041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 110514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc); 110614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 110714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 11088f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation &TopContextLoc = CLocs.back(); 11091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 111014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 111114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == CLoc) { 11128f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 11134c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek if (IsConsumedExpr(TopContextLoc) && 11144c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek !IsControlFlowExpr(TopContextLoc.asStmt())) 11158f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek TopContextLoc.markDead(); 11168f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek 111714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 11188f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 111914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 112014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 112114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 112214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 112314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, CLoc)) { 11248f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 112514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 11261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11274c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek if (IsConsumedExpr(CLoc) && !IsControlFlowExpr(CLoc.asStmt())) { 11288f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek CLocs.push_back(ContextLocation(CLoc, true)); 11298f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return; 11308f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 11318f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 11321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 113314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(CLoc); 11341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 113514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 113614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 113714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 113814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 113914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 11401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11415c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // If we reach here, there is no enclosing context. Just add the edge. 11425c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek rawAddEdge(NewLoc); 114314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 114414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 11458f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekbool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) { 11468f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt())) 11478f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X); 11481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11498f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return false; 11508f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek} 11511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1152e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenekvoid EdgeBuilder::addExtendedContext(const Stmt *S) { 1153e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (!S) 1154e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek return; 11551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const Stmt *Parent = PDB.getParent(S); 1157e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek while (Parent) { 1158e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (isa<CompoundStmt>(Parent)) 1159e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek Parent = PDB.getParent(Parent); 1160e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek else 1161e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1162e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1163e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek 1164e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (Parent) { 1165e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek switch (Parent->getStmtClass()) { 1166e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::DoStmtClass: 1167e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 1168e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(Parent); 1169e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek default: 1170e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1171e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1172e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 11731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1174e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(S); 1175e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek} 11761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 117714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addContext(const Stmt *S) { 117814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!S) 117914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 118014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 118159950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.LC); 1182183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose addContext(L); 1183183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose} 11841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1185183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rosevoid EdgeBuilder::addContext(const PathDiagnosticLocation &L) { 118614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 118714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &TopContextLoc = CLocs.back(); 118814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 118914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 119014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == L) 119114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 119214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 119314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, L)) { 119414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 11951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 119614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 119714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 119814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 119914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 120014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 120114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 120214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 120314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 120414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 120511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// Cone-of-influence: support the reverse propagation of "interesting" symbols 120611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// and values by tracing interesting calculations backwards through evaluated 120711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// expressions along a path. This is probably overly complicated, but the idea 120811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// is that if an expression computed an "interesting" value, the child 120911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// expressions are are also likely to be "interesting" as well (which then 121011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// propagates to the values they in turn compute). This reverse propagation 121111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// is needed to track interesting correlations across function call boundaries, 121211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// where formal arguments bind to actual arguments, etc. This is also needed 121311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// because the constraint solver sometimes simplifies certain symbolic values 121411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// into constants when appropriate, and this complicates reasoning about 121511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// interesting values. 121611abcecc8c919673237cf37384290a1ef1943976Ted Kremenektypedef llvm::DenseSet<const Expr *> InterestingExprs; 121711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 121811abcecc8c919673237cf37384290a1ef1943976Ted Kremenekstatic void reversePropagateIntererstingSymbols(BugReport &R, 121911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs &IE, 122011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const ProgramState *State, 122111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const Expr *Ex, 122211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *LCtx) { 122311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek SVal V = State->getSVal(Ex, LCtx); 122411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (!(R.isInteresting(V) || IE.count(Ex))) 122511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek return; 122611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 122711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek switch (Ex->getStmtClass()) { 122811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek default: 122911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (!isa<CastExpr>(Ex)) 123011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek break; 123111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // Fall through. 123211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek case Stmt::BinaryOperatorClass: 123311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek case Stmt::UnaryOperatorClass: { 123411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek for (Stmt::const_child_iterator CI = Ex->child_begin(), 123511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CE = Ex->child_end(); 123611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CI != CE; ++CI) { 123711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *child = dyn_cast_or_null<Expr>(*CI)) { 123811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek IE.insert(child); 123911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek SVal ChildV = State->getSVal(child, LCtx); 124011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek R.markInteresting(ChildV); 124111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 124211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek break; 124311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 124411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 124511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 124611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 124711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek R.markInteresting(V); 124811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek} 124911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 125011abcecc8c919673237cf37384290a1ef1943976Ted Kremenekstatic void reversePropagateInterestingSymbols(BugReport &R, 125111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs &IE, 125211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const ProgramState *State, 125311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CalleeCtx, 125411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CallerCtx) 125511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek{ 1256852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose // FIXME: Handle non-CallExpr-based CallEvents. 125711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const StackFrameContext *Callee = CalleeCtx->getCurrentStackFrame(); 125811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const Stmt *CallSite = Callee->getCallSite(); 1259852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite)) { 126011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) { 126111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek FunctionDecl::param_const_iterator PI = FD->param_begin(), 126211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek PE = FD->param_end(); 126311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end(); 126411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek for (; AI != AE && PI != PE; ++AI, ++PI) { 126511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *ArgE = *AI) { 126611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const ParmVarDecl *PD = *PI) { 126711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek Loc LV = State->getLValue(PD, CalleeCtx); 126811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (R.isInteresting(LV) || R.isInteresting(State->getRawSVal(LV))) 126911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek IE.insert(ArgE); 127011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 127111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 127211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 127311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 127411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 127511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek} 127611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 12778347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosestatic bool GenerateExtensivePathDiagnostic(PathDiagnostic& PD, 127814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB, 12793bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose const ExplodedNode *N, 12803bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ArrayRef<BugReporterVisitor *> visitors) { 128114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder EB(PD, PDB); 12820cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks const SourceManager& SM = PDB.getSourceManager(); 128356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector CallStack; 128411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs IE; 128514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 12869c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); 128714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (NextNode) { 128814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek N = NextNode; 128914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek NextNode = GetPredecessorNode(N); 129014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ProgramPoint P = N->getLocation(); 129114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 1292dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek do { 129311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const PostStmt *PS = dyn_cast<PostStmt>(&P)) { 129411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *Ex = PS->getStmtAs<Expr>()) 129511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 129611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek N->getState().getPtr(), Ex, 129711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek N->getLocationContext()); 129811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 129911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 13000b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks if (const CallExitEnd *CE = dyn_cast<CallExitEnd>(&P)) { 1301183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose const Stmt *S = CE->getCalleeContext()->getCallSite(); 1302183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) { 1303852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 1304852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose N->getState().getPtr(), Ex, 1305852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose N->getLocationContext()); 1306852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose } 1307183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 1308183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece *C = 1309183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece::construct(N, *CE, SM); 131080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GRBugReporter& BR = PDB.getBugReporter(); 131180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks BR.addCallPieceLocationContextPair(C, CE->getCalleeContext()); 1312183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 1313183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose EB.addEdge(C->callReturn, true); 1314183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose EB.flushLocations(); 1315183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 1316183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PD.getActivePath().push_front(C); 1317183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PD.pushActivePath(&C->path); 1318183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose CallStack.push_back(StackDiagPair(C, N)); 13195de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek break; 13205de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek } 13214ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek 13222042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // Pop the call hierarchy if we are done walking the contents 13232042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // of a function call. 13242042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek if (const CallEnter *CE = dyn_cast<CallEnter>(&P)) { 1325097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek // Add an edge to the start of the function. 1326097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek const Decl *D = CE->getCalleeContext()->getDecl(); 1327097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek PathDiagnosticLocation pos = 1328097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek PathDiagnosticLocation::createBegin(D, SM); 1329097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek EB.addEdge(pos); 1330097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek 1331097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek // Flush all locations, and pop the active path. 1332183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose bool VisitedEntireCall = PD.isWithinCall(); 13334ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek EB.flushLocations(); 13342042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.popActivePath(); 13354ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek PDB.LC = N->getLocationContext(); 1336097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek 1337183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose // Either we just added a bunch of stuff to the top-level path, or 1338183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose // we have a previous CallExitEnd. If the former, it means that the 13392042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // path terminated within a function call. We must then take the 13402042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // current contents of the active path and place it within 13412042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // a new PathDiagnosticCallPiece. 1342183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece *C; 1343183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose if (VisitedEntireCall) { 1344183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 1345183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose } else { 1346183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose const Decl *Caller = CE->getLocationContext()->getDecl(); 13479373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 134880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GRBugReporter& BR = PDB.getBugReporter(); 134980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks BR.addCallPieceLocationContextPair(C, CE->getCalleeContext()); 13509373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks } 1351852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose 1352183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose C->setCallee(*CE, SM); 1353183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose EB.addContext(C->getLocation()); 1354368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 1355368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (!CallStack.empty()) { 135656a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks assert(CallStack.back().first == C); 1357368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks CallStack.pop_back(); 1358368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 13592042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek break; 13602042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek } 13614ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek 13624ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // Note that is important that we update the LocationContext 13634ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // after looking at CallExits. CallExit basically adds an 13644ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // edge in the *caller*, so we don't want to update the LocationContext 13654ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // too soon. 13664ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek PDB.LC = N->getLocationContext(); 13675de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 1368dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Block edges. 136911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 137011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // Does this represent entering a call? If so, look at propagating 137111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // interesting symbols across call boundaries. 137211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (NextNode) { 137311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CallerCtx = NextNode->getLocationContext(); 137411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CalleeCtx = PDB.LC; 137511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (CallerCtx != CalleeCtx) { 137611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek reversePropagateInterestingSymbols(*PDB.getBugReport(), IE, 137711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek N->getState().getPtr(), 137811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CalleeCtx, CallerCtx); 137911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 138011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 138111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 1382dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Are we jumping to the head of a loop? Add a special diagnostic. 1383f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) { 138459950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PathDiagnosticLocation L(Loop, SM, PDB.LC); 1385ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const CompoundStmt *CS = NULL; 13861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1387f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) 1388f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek CS = dyn_cast<CompoundStmt>(FS->getBody()); 1389f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) 1390f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek CS = dyn_cast<CompoundStmt>(WS->getBody()); 13911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1392dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek PathDiagnosticEventPiece *p = 1393dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek new PathDiagnosticEventPiece(L, 139407c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek "Looping back to the head of the loop"); 13952dd17abf11ae64339fa6bfaa57d76e13a5fbe5b8Ted Kremenek p->setPrunable(true); 13961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1397dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek EB.addEdge(p->getLocation(), true); 13982042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 13991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1400ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (CS) { 14010cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation BL = 14020cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createEndBrace(CS, SM); 140307c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek EB.addEdge(BL); 1404dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 14058bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 1406f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek 1407f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek if (const Stmt *Term = BE->getSrc()->getTerminator()) 1408ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek EB.addContext(Term); 14091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1410dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 14118bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 141214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 14131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) { 14141a7bcc41efb73d80fd45eb71494b073f388d333cJordan Rose CFGElement First = BE->getFirstElement(); 14151a7bcc41efb73d80fd45eb71494b073f388d333cJordan Rose if (const CFGStmt *S = First.getAs<CFGStmt>()) { 14163c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const Stmt *stmt = S->getStmt(); 14173c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (IsControlFlowExpr(stmt)) { 1418b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu // Add the proper context for '&&', '||', and '?'. 14193c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addContext(stmt); 1420b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 1421b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu else 14223c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt()); 1423dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 1424b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu 1425dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 1426dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 14275de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 14285de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 1429dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } while (0); 14301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1431dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (!NextNode) 143214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek continue; 14331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14348e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add pieces from custom visitors. 14358e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 14363bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 14373bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = visitors.end(); 14383bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose I != E; ++I) { 14398e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 14408966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek const PathDiagnosticLocation &Loc = p->getLocation(); 14418966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek EB.addEdge(Loc, true); 14422042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 1443368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks updateStackPiecesWithMessage(p, CallStack); 1444368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 14458966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek if (const Stmt *S = Loc.asStmt()) 14461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 14478966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 14481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 144914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 14508347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 14518347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return PDB.getBugReport()->isValid(); 145214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 145314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 14545fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 14553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugType and subclasses. 14563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 1457404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios KyrtzidisBugType::~BugType() { } 1458404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 14593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugType::FlushReports(BugReporter &BR) {} 14603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 146199ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BuiltinBug::anchor() {} 146299ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 14633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 14643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReport and subclasses. 14653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 1466e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 146799ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BugReport::NodeResolver::anchor() {} 146899ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 14698e6431adab313e283a992698f6fc7afe62420999Anna Zaksvoid BugReport::addVisitor(BugReporterVisitor* visitor) { 14708e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (!visitor) 14718e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 14728e6431adab313e283a992698f6fc7afe62420999Anna Zaks 14738e6431adab313e283a992698f6fc7afe62420999Anna Zaks llvm::FoldingSetNodeID ID; 14748e6431adab313e283a992698f6fc7afe62420999Anna Zaks visitor->Profile(ID); 14758e6431adab313e283a992698f6fc7afe62420999Anna Zaks void *InsertPos; 14768e6431adab313e283a992698f6fc7afe62420999Anna Zaks 14778e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) { 14788e6431adab313e283a992698f6fc7afe62420999Anna Zaks delete visitor; 14798e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 14808e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 14818e6431adab313e283a992698f6fc7afe62420999Anna Zaks 14828e6431adab313e283a992698f6fc7afe62420999Anna Zaks CallbacksSet.InsertNode(visitor, InsertPos); 14833bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose Callbacks.push_back(visitor); 14843bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 14858e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 14868e6431adab313e283a992698f6fc7afe62420999Anna Zaks 14878e6431adab313e283a992698f6fc7afe62420999Anna ZaksBugReport::~BugReport() { 14888e6431adab313e283a992698f6fc7afe62420999Anna Zaks for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) { 1489dc757b049796949e4b11646445a6598f0bdabd7aAnna Zaks delete *I; 14908e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 1491c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek while (!interestingSymbols.empty()) { 1492c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek popInterestingSymbolsAndRegions(); 1493c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 14948e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 1495e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 149607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenekconst Decl *BugReport::getDeclWithIssue() const { 149707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek if (DeclWithIssue) 149807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return DeclWithIssue; 149907189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 150007189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek const ExplodedNode *N = getErrorNode(); 150107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek if (!N) 150207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return 0; 150307189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 150407189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek const LocationContext *LC = N->getLocationContext(); 150507189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return LC->getCurrentStackFrame()->getDecl(); 150607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek} 150707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 1508e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaksvoid BugReport::Profile(llvm::FoldingSetNodeID& hash) const { 1509e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddPointer(&BT); 1510e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddString(Description); 1511ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks if (UniqueingLocation.isValid()) { 1512ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks UniqueingLocation.Profile(hash); 1513ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks } else if (Location.isValid()) { 1514590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks Location.Profile(hash); 1515590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } else { 1516590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(ErrorNode); 1517590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode)); 1518590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } 1519e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 1520e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks for (SmallVectorImpl<SourceRange>::const_iterator I = 1521e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks Ranges.begin(), E = Ranges.end(); I != E; ++I) { 1522e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks const SourceRange range = *I; 1523e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!range.isValid()) 1524e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks continue; 1525e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getBegin().getRawEncoding()); 1526e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getEnd().getRawEncoding()); 1527e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 1528e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks} 15293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 153076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(SymbolRef sym) { 153176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!sym) 153276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return; 15333bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 15343bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // If the symbol wasn't already in our set, note a configuration change. 1535c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (getInterestingSymbols().insert(sym).second) 15363bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 15378ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose 15388ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose if (const SymbolMetadata *meta = dyn_cast<SymbolMetadata>(sym)) 1539c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek getInterestingRegions().insert(meta->getRegion()); 154076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 154176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 154276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(const MemRegion *R) { 154376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!R) 154476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return; 15453bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 15463bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // If the base region wasn't already in our set, note a configuration change. 154776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek R = R->getBaseRegion(); 1548c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (getInterestingRegions().insert(R).second) 15493bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 15508ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose 155176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 1552c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek getInterestingSymbols().insert(SR->getSymbol()); 155376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 155476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 155576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(SVal V) { 155676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek markInteresting(V.getAsRegion()); 155776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek markInteresting(V.getAsSymbol()); 155876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 155976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 156080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaksvoid BugReport::markInteresting(const LocationContext *LC) { 156180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!LC) 156280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return; 156380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks InterestingLocationContexts.insert(LC); 156480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks} 156580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 1566c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(SVal V) { 156776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return isInteresting(V.getAsRegion()) || isInteresting(V.getAsSymbol()); 156876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 156976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 1570c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(SymbolRef sym) { 157176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!sym) 157276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 15738ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose // We don't currently consider metadata symbols to be interesting 15748ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose // even if we know their region is interesting. Is that correct behavior? 1575c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return getInterestingSymbols().count(sym); 157676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 157776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 1578c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(const MemRegion *R) { 157976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!R) 158076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 158176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek R = R->getBaseRegion(); 1582c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek bool b = getInterestingRegions().count(R); 158376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (b) 158476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return true; 158576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 1586c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return getInterestingSymbols().count(SR->getSymbol()); 158776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 158876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 1589c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 159080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaksbool BugReport::isInteresting(const LocationContext *LC) { 159180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!LC) 159280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return false; 159380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return InterestingLocationContexts.count(LC); 159480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks} 159580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 1596c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::lazyInitializeInterestingSets() { 1597c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (interestingSymbols.empty()) { 1598c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.push_back(new Symbols()); 1599c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.push_back(new Regions()); 1600c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 1601c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 1602c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 1603c4bac8e376b98d633bb00ee5f510d5e58449753cTed KremenekBugReport::Symbols &BugReport::getInterestingSymbols() { 1604c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek lazyInitializeInterestingSets(); 1605c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return *interestingSymbols.back(); 1606c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 1607c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 1608c4bac8e376b98d633bb00ee5f510d5e58449753cTed KremenekBugReport::Regions &BugReport::getInterestingRegions() { 1609c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek lazyInitializeInterestingSets(); 1610c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return *interestingRegions.back(); 1611c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 1612c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 1613c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::pushInterestingSymbolsAndRegions() { 1614c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.push_back(new Symbols(getInterestingSymbols())); 1615c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.push_back(new Regions(getInterestingRegions())); 1616c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 1617c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 1618c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::popInterestingSymbolsAndRegions() { 1619c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek delete interestingSymbols.back(); 1620c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.pop_back(); 1621c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek delete interestingRegions.back(); 1622c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.pop_back(); 1623c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 162476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 16259c378f705405d37f49795d5e915989de774fe11fTed Kremenekconst Stmt *BugReport::getStmt() const { 1626e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!ErrorNode) 1627e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return 0; 1628e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 1629212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care ProgramPoint ProgP = ErrorNode->getLocation(); 16305f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek const Stmt *S = NULL; 16311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16329c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (BlockEntrance *BE = dyn_cast<BlockEntrance>(&ProgP)) { 1633fafd3834754d2093e0ad7a1c005860fd527ecb7fZhongxing Xu CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit(); 163450d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu if (BE->getBlock() == &Exit) 1635212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care S = GetPreviousStmt(ErrorNode); 16363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 16375f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (!S) 16381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump S = GetStmt(ProgP); 16391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return S; 16413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 16423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1643640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidisstd::pair<BugReport::ranges_iterator, BugReport::ranges_iterator> 1644e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna ZaksBugReport::getRanges() { 1645e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // If no custom ranges, add the range of the statement corresponding to 1646e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // the error node. 1647e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (Ranges.empty()) { 1648e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (const Expr *E = dyn_cast_or_null<Expr>(getStmt())) 1649e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks addRange(E->getSourceRange()); 1650e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks else 1651e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 1652e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 1653e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 165414924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks // User-specified absence of range info. 165514924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks if (Ranges.size() == 1 && !Ranges.begin()->isValid()) 165614924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 165714924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks 1658e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(Ranges.begin(), Ranges.end()); 16593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 16603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1661590dd8e0959d8df5621827768987c4792b74fc06Anna ZaksPathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const { 1662b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks if (ErrorNode) { 1663590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(!Location.isValid() && 1664b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks "Either Location or ErrorNode should be specified but not both."); 1665b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks 16669c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const Stmt *S = GetCurrentOrPreviousStmt(ErrorNode)) { 1667590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks const LocationContext *LC = ErrorNode->getLocationContext(); 1668590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks 16693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // For member expressions, return the location of the '.' or '->'. 16705b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) 1671590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createMemberLoc(ME, SM); 16725b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek // For binary operators, return the location of the operator. 16735b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) 1674590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createOperatorLoc(B, SM); 16753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1676590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createBegin(S, SM, LC); 16773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1678b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } else { 1679b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks assert(Location.isValid()); 1680b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks return Location; 1681b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } 1682b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks 1683590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation(); 16843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 16853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 16863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 16873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReporter and subclasses. 16883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 16893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 16904a5f724538cbc275370c9504e8169ce92503256cBenjamin KramerBugReportEquivClass::~BugReportEquivClass() { } 1691a2f4ec0df645fc249d2945beef9653f03b175417Zhongxing XuGRBugReporter::~GRBugReporter() { } 16923106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReporterData::~BugReporterData() {} 16933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 169438b02b912e1a55c912f603c4369431264d36a381Zhongxing XuExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); } 16953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 169618c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekProgramStateManager& 16973106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekGRBugReporter::getStateManager() { return Eng.getStateManager(); } 16983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 16993b030a28cda2b953758507769c1d436bec5ec45eAnna ZaksBugReporter::~BugReporter() { 17003b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks FlushReports(); 17013b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks 17023b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks // Free the bug reports we are tracking. 17033b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks typedef std::vector<BugReportEquivClass *> ContTy; 17043b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end(); 17053b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks I != E; ++I) { 17063b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks delete *I; 17073b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks } 17083b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks} 17093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 17103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugReporter::FlushReports() { 17113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (BugTypes.isEmpty()) 17123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return; 17133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 17143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // First flush the warnings for each BugType. This may end up creating new 1715404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // warnings and new BugTypes. 1716404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: Only NSErrorChecker needs BugType's FlushReports. 1717404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // Turn NSErrorChecker into a proper checker and remove this. 17185f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<const BugType*, 16> bugTypes; 17193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) 1720404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis bugTypes.push_back(*I); 17215f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVector<const BugType*, 16>::iterator 1722404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I) 17233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const_cast<BugType*>(*I)->FlushReports(*this); 17243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1725d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks // We need to flush reports in deterministic order to ensure the order 1726d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks // of the reports is consistent between runs. 17270eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks typedef std::vector<BugReportEquivClass *> ContVecTy; 17280eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks for (ContVecTy::iterator EI=EQClassesVector.begin(), EE=EQClassesVector.end(); 17290eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks EI != EE; ++EI){ 17300eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks BugReportEquivClass& EQ = **EI; 1731404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis FlushReport(EQ); 17323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 17333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1734404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // BugReporter owns and deletes only BugTypes created implicitly through 1735404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // EmitBasicReport. 1736404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: There are leaks from checkers that assume that the BugTypes they 1737404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // create will be destroyed by the BugReporter. 1738404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis for (llvm::StringMap<BugType*>::iterator 1739404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I) 1740404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis delete I->second; 1741404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 17423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Remove all references to the BugType objects. 17433baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.getEmptySet(); 17443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 17453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 17463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 17473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnostics generation. 17483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 17493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 175038b02b912e1a55c912f603c4369431264d36a381Zhongxing Xustatic std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, 1751c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::pair<ExplodedNode*, unsigned> > 175238b02b912e1a55c912f603c4369431264d36a381Zhongxing XuMakeReportGraph(const ExplodedGraph* G, 17535f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<const ExplodedNode*> &nodes) { 17541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the trimmed graph. It will contain the shortest paths from the 17561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // error nodes to the root. In the new graph we should only have one 17573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // error node unless there are two or more error nodes with the same minimum 17583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // path length. 175938b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu ExplodedGraph* GTrim; 1760c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu InterExplodedGraphMap* NMap; 17613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 17623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*, const void*> InverseMap; 176340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek llvm::tie(GTrim, NMap) = G->Trim(nodes.data(), nodes.data() + nodes.size(), 176440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek &InverseMap); 17651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create owning pointers for GTrim and NMap just to ensure that they are 17673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // released when this function exists. 17686f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<ExplodedGraph> AutoReleaseGTrim(GTrim); 17696f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<InterExplodedGraphMap> AutoReleaseNMap(NMap); 17701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the (first) error node in the trimmed graph. We just need to consult 17723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // the node map (NMap) which maps from nodes in the original graph to nodes 17733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // in the new graph. 1774938332c657390d1e782e0adc03b092993edae962Ted Kremenek 1775c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::queue<const ExplodedNode*> WS; 177638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu typedef llvm::DenseMap<const ExplodedNode*, unsigned> IndexMapTy; 1777938332c657390d1e782e0adc03b092993edae962Ted Kremenek IndexMapTy IndexMap; 17783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 177940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek for (unsigned nodeIndex = 0 ; nodeIndex < nodes.size(); ++nodeIndex) { 178040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek const ExplodedNode *originalNode = nodes[nodeIndex]; 178140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (const ExplodedNode *N = NMap->getMappedNode(originalNode)) { 1782938332c657390d1e782e0adc03b092993edae962Ted Kremenek WS.push(N); 178340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek IndexMap[originalNode] = nodeIndex; 17843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 178540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 17861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1787938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(!WS.empty() && "No error node found in the trimmed graph."); 17883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 17893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create a new (third!) graph with a single path. This is the graph 17903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // that will be returned to the caller. 1791c77a55126fcad66fb086f8e100a494caa2496a2dZhongxing Xu ExplodedGraph *GNew = new ExplodedGraph(); 17921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Sometimes the trimmed graph can contain a cycle. Perform a reverse BFS 17943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // to the root node, and then construct a new graph that contains only 17953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // a single path. 17963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*,unsigned> Visited; 17971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek unsigned cnt = 0; 17999c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *Root = 0; 18001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!WS.empty()) { 18029c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *Node = WS.front(); 18033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek WS.pop(); 18041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Visited.find(Node) != Visited.end()) 18063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 18071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Visited[Node] = cnt++; 18091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Node->pred_empty()) { 18113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Root = Node; 18123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 18133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 18141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1815c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu for (ExplodedNode::const_pred_iterator I=Node->pred_begin(), 18163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek E=Node->pred_end(); I!=E; ++I) 18173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek WS.push(*I); 18183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 18191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1820938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(Root); 18211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now walk from the root down the BFS path, always taking the successor 18233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // with the lowest number. 18241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ExplodedNode *Last = 0, *First = 0; 18253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NodeBackMap *BM = new NodeBackMap(); 1826938332c657390d1e782e0adc03b092993edae962Ted Kremenek unsigned NodeIndex = 0; 18271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1828c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu for ( const ExplodedNode *N = Root ;;) { 18293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Lookup the number associated with the current node. 18303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*,unsigned>::iterator I = Visited.find(N); 1831938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(I != Visited.end()); 18321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the equivalent node in the new graph with the same state 18343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // and location. 18359c378f705405d37f49795d5e915989de774fe11fTed Kremenek ExplodedNode *NewN = GNew->getNode(N->getLocation(), N->getState()); 18361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Store the mapping to the original node. 18383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*, const void*>::iterator IMitr=InverseMap.find(N); 18393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(IMitr != InverseMap.end() && "No mapping to original node."); 1840c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu (*BM)[NewN] = (const ExplodedNode*) IMitr->second; 18411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Link up the new node with the previous node. 18433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Last) 18445fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek NewN->addPredecessor(Last, *GNew); 18451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Last = NewN; 18471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Are we at the final node? 1849938332c657390d1e782e0adc03b092993edae962Ted Kremenek IndexMapTy::iterator IMI = 1850c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu IndexMap.find((const ExplodedNode*)(IMitr->second)); 1851938332c657390d1e782e0adc03b092993edae962Ted Kremenek if (IMI != IndexMap.end()) { 18523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek First = NewN; 1853938332c657390d1e782e0adc03b092993edae962Ted Kremenek NodeIndex = IMI->second; 18543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 18553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 18561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the next successor node. We choose the node that is marked 18583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // with the lowest DFS number. 1859c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::const_succ_iterator SI = N->succ_begin(); 1860c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::const_succ_iterator SE = N->succ_end(); 18613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek N = 0; 18621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (unsigned MinVal = 0; SI != SE; ++SI) { 18641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek I = Visited.find(*SI); 18661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (I == Visited.end()) 18683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 18691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!N || I->second < MinVal) { 18713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek N = *SI; 18723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MinVal = I->second; 18733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 18743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 18751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1876938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(N); 18773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 18781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1879938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(First); 1880938332c657390d1e782e0adc03b092993edae962Ted Kremenek 18813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return std::make_pair(std::make_pair(GNew, BM), 18823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::make_pair(First, NodeIndex)); 18833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 1884d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 18853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object 18863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// and collapses PathDiagosticPieces that are expanded by macros. 188777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) { 18882042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek typedef std::vector<std::pair<IntrusiveRefCntPtr<PathDiagnosticMacroPiece>, 18892042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek SourceLocation> > MacroStackTy; 18901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1891c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith typedef std::vector<IntrusiveRefCntPtr<PathDiagnosticPiece> > 18923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy; 18931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStackTy MacroStack; 18953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy Pieces; 18961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 189777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek for (PathPieces::const_iterator I = path.begin(), E = path.end(); 18982042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek I!=E; ++I) { 189977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 190077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek PathDiagnosticPiece *piece = I->getPtr(); 190177d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 190277d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek // Recursively compact calls. 190377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek if (PathDiagnosticCallPiece *call=dyn_cast<PathDiagnosticCallPiece>(piece)){ 190477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek CompactPathDiagnostic(call->path, SM); 190577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek } 190677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 19073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Get the location of the PathDiagnosticPiece. 190877d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek const FullSourceLoc Loc = piece->getLocation().asLocation(); 19091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine the instantiation location, which is the location we group 19113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // related PathDiagnosticPieces. 19121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation InstantiationLoc = Loc.isMacroID() ? 1913402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 19143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 19151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Loc.isFileID()) { 19173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.clear(); 191877d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek Pieces.push_back(piece); 19193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 19203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1921706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek 19223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(Loc.isMacroID()); 19231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Is the PathDiagnosticPiece within the same macro group? 19253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) { 192677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek MacroStack.back().first->subPieces.push_back(piece); 19273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 19283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1929d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 19303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // We aren't in the same group. Are we descending into a new macro 19313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // or are part of an old one? 1932c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith IntrusiveRefCntPtr<PathDiagnosticMacroPiece> MacroGroup; 1933d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 19343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ? 1935402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 19363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 19371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Walk the entire macro stack. 19393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!MacroStack.empty()) { 19403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (InstantiationLoc == MacroStack.back().second) { 19413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 19423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 19433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 19441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (ParentInstantiationLoc == MacroStack.back().second) { 19463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 19473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 194861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 19491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.pop_back(); 19516837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek } 19521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) { 19543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create a new macro group and add it to the stack. 1955590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticMacroPiece *NewGroup = 1956590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks new PathDiagnosticMacroPiece( 195777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek PathDiagnosticLocation::createSingleLocation(piece->getLocation())); 19585a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek 19593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (MacroGroup) 1960802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek MacroGroup->subPieces.push_back(NewGroup); 19613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 19623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(InstantiationLoc.isFileID()); 19633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Pieces.push_back(NewGroup); 19643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 19651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = NewGroup; 19673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc)); 19687dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 19693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 19703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Finally, add the PathDiagnosticPiece to the group. 197177d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek MacroGroup->subPieces.push_back(piece); 19723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 19731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now take the pieces and construct a new PathDiagnostic. 197577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek path.clear(); 19761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 197777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) 197877d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek path.push_back(*I); 197961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 198061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 19818347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosebool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, 1982c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticConsumer &PC, 1983c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek ArrayRef<BugReport *> &bugReports) { 198440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek assert(!bugReports.empty()); 19858347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 19868347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose bool HasValid = false; 19875f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<const ExplodedNode *, 10> errorNodes; 1988c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (ArrayRef<BugReport*>::iterator I = bugReports.begin(), 1989c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek E = bugReports.end(); I != E; ++I) { 19908347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose if ((*I)->isValid()) { 19918347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose HasValid = true; 199240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek errorNodes.push_back((*I)->getErrorNode()); 19938347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose } else { 19948347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose errorNodes.push_back(0); 19958347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose } 199640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 19971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19988347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose // If all the reports have been marked invalid, we're done. 19998347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose if (!HasValid) 20008347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return false; 20018347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 20023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Construct a new graph that contains only a single path from the error 20031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // node to a root. 200438b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu const std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, 2005c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::pair<ExplodedNode*, unsigned> >& 200640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek GPair = MakeReportGraph(&getGraph(), errorNodes); 20071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the BugReport with the original location. 200940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek assert(GPair.second.second < bugReports.size()); 201040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *R = bugReports[GPair.second.second]; 20113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(R && "No original report found for sliced graph."); 20128347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose assert(R->isValid() && "Report selected from trimmed graph marked invalid."); 20131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20146f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<ExplodedGraph> ReportGraph(GPair.first.first); 20156f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<NodeBackMap> BackMap(GPair.first.second); 2016c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode *N = GPair.second.first; 20171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Start building the path diagnostic... 2019c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticBuilder PDB(*this, R, BackMap.get(), &PC); 20201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20218e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Register additional node visitors. 202250bbc165b063155cc23c360deb7b865502e068e2Anna Zaks R->addVisitor(new NilReceiverBRVisitor()); 202350bbc165b063155cc23c360deb7b865502e068e2Anna Zaks R->addVisitor(new ConditionBRVisitor()); 20241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20253bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose BugReport::VisitorList visitors; 20263bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose unsigned originalReportConfigToken, finalReportConfigToken; 20273bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 20283bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // While generating diagnostics, it's possible the visitors will decide 20293bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // new symbols and regions are interesting, or add other visitors based on 20303bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // the information they find. If they do, we need to regenerate the path 20313bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // based on our new report configuration. 20323bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose do { 20333bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // Get a clean copy of all the visitors. 20343bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (BugReport::visitor_iterator I = R->visitor_begin(), 20353bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = R->visitor_end(); I != E; ++I) 20363bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose visitors.push_back((*I)->clone()); 20373bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 20383bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // Clear out the active path from any previous work. 20393a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose PD.resetPath(); 20403bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose originalReportConfigToken = R->getConfigurationChangeToken(); 20413bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 20423bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // Generate the very last diagnostic piece - the piece is visible before 20433bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // the trace is expanded. 2044d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (PDB.getGenerationScheme() != PathDiagnosticConsumer::None) { 2045d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose PathDiagnosticPiece *LastPiece = 0; 2046d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end(); 2047d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose I != E; ++I) { 2048d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) { 2049d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose assert (!LastPiece && 2050d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose "There can only be one final piece in a diagnostic."); 2051d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose LastPiece = Piece; 2052d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose } 20533bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose } 2054d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!LastPiece) 2055d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R); 2056d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (LastPiece) 2057d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose PD.setEndOfPath(LastPiece); 2058d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose else 2059d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return false; 206023f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks } 206123f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks 20623bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose switch (PDB.getGenerationScheme()) { 2063ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie case PathDiagnosticConsumer::Extensive: 20648347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose if (!GenerateExtensivePathDiagnostic(PD, PDB, N, visitors)) { 20658347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose assert(!R->isValid() && "Failed on valid report"); 20668347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose // Try again. We'll filter out the bad report when we trim the graph. 20678347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose // FIXME: It would be more efficient to use the same intermediate 20688347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose // trimmed graph, and just repeat the shortest-path search. 20698347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return generatePathDiagnostic(PD, PC, bugReports); 20708347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose } 20715fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek break; 2072ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie case PathDiagnosticConsumer::Minimal: 20738347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose if (!GenerateMinimalPathDiagnostic(PD, PDB, N, visitors)) { 20748347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose assert(!R->isValid() && "Failed on valid report"); 20758347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose // Try again. We'll filter out the bad report when we trim the graph. 20768347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return generatePathDiagnostic(PD, PC, bugReports); 20778347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose } 20783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 2079c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek case PathDiagnosticConsumer::None: 2080d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!GenerateVisitorsOnlyPathDiagnostic(PD, PDB, N, visitors)) { 2081d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose assert(!R->isValid() && "Failed on valid report"); 2082d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // Try again. We'll filter out the bad report when we trim the graph. 2083d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return generatePathDiagnostic(PD, PC, bugReports); 2084d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose } 2085d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose break; 20863bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose } 20873bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 20883bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // Clean up the visitors we used. 20893bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose llvm::DeleteContainerPointers(visitors); 20903bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 20913bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // Did anything change while generating this path? 20923bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose finalReportConfigToken = R->getConfigurationChangeToken(); 20933bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose } while(finalReportConfigToken != originalReportConfigToken); 20943bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 2095c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek // Finally, prune the diagnostic path of uninteresting stuff. 2096b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (!PD.path.empty()) { 2097b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // Remove messages that are basically the same. 20983800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek removeRedundantMsgs(PD.getMutablePieces()); 2099b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 2100b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (R->shouldPrunePath()) { 2101b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek bool hasSomethingInteresting = RemoveUneededCalls(PD.getMutablePieces(), 2102b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek R); 2103b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek assert(hasSomethingInteresting); 2104b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek (void) hasSomethingInteresting; 2105b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 2106ed7948b55fa4b2505f240cc5287137f451172b4cTed Kremenek } 21078347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 21088347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return true; 21093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 21101aa44c7c9198796085b77c6bdd7c90030845a688Ted Kremenek 2111cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::Register(BugType *BT) { 21123baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.add(BugTypes, BT); 211376d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek} 211476d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek 2115785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rosevoid BugReporter::emitReport(BugReport* R) { 2116cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // Compute the bug report's hash to determine its equivalence class. 2117cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek llvm::FoldingSetNodeID ID; 2118cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek R->Profile(ID); 21191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Lookup the equivance class. If there isn't one, create it. 2121cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek BugType& BT = R->getBugType(); 2122cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek Register(&BT); 2123cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek void *InsertPos; 2124404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos); 21251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2126cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek if (!EQ) { 2127cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ = new BugReportEquivClass(R); 2128404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis EQClasses.InsertNode(EQ, InsertPos); 21293b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks EQClassesVector.push_back(EQ); 2130cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek } 2131cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek else 2132cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ->AddReport(R); 213361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 213461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 213506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 213606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 213706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek// Emitting reports in equivalence classes. 213806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 213906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 214006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremeneknamespace { 2141ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamstruct FRIEC_WLItem { 214206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *N; 214306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek ExplodedNode::const_succ_iterator I, E; 214406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 214506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek FRIEC_WLItem(const ExplodedNode *n) 214606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek : N(n), I(N->succ_begin()), E(N->succ_end()) {} 214706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek}; 214806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek} 214906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 215061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenekstatic BugReport * 215161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted KremenekFindReportInEquivalenceClass(BugReportEquivClass& EQ, 21525f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<BugReport*> &bugReports) { 215361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 215406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end(); 215506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(I != E); 21564a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer BugType& BT = I->getBugType(); 215761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 215840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // If we don't need to suppress any of the nodes because they are 215940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // post-dominated by a sink, simply add all the nodes in the equivalence class 216040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // to 'Nodes'. Any of the reports will serve as a "representative" report. 216161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!BT.isSuppressOnSink()) { 21624a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer BugReport *R = I; 216361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) { 21649c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N = I->getErrorNode(); 216561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (N) { 21664a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer R = I; 216740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek bugReports.push_back(R); 216861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 216961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 217006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek return R; 217161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 217261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 217306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // For bug reports that should be suppressed when all paths are post-dominated 217406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // by a sink node, iterate through the reports in the equivalence class 217506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // until we find one that isn't post-dominated (if one exists). We use a 217606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // DFS traversal of the ExplodedGraph to find a non-sink node. We could write 217706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // this as a recursive function, but we don't want to risk blowing out the 217806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // stack for very long paths. 217940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = 0; 218061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 218106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; I != E; ++I) { 21824a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer const ExplodedNode *errorNode = I->getErrorNode(); 218306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 218440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!errorNode) 218506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 218640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->isSink()) { 2187b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable( 218806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek "BugType::isSuppressSink() should not be 'true' for sink end nodes"); 218906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 219061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // No successors? By definition this nodes isn't post-dominated by a sink. 219140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->succ_empty()) { 21924a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer bugReports.push_back(I); 219340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 21944a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer exampleReport = I; 219561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek continue; 219661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 219761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 219806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // At this point we know that 'N' is not a sink and it has at least one 219906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // successor. Use a DFS worklist to find a non-sink end-of-path node. 220006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek typedef FRIEC_WLItem WLItem; 22015f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<WLItem, 10> DFSWorkList; 220206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek llvm::DenseMap<const ExplodedNode *, unsigned> Visited; 220306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 220406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek DFSWorkList WL; 220540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek WL.push_back(errorNode); 220640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek Visited[errorNode] = 1; 220706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 220806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek while (!WL.empty()) { 220906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WLItem &WI = WL.back(); 221006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(!WI.N->succ_empty()); 221106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 221206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; WI.I != WI.E; ++WI.I) { 221306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *Succ = *WI.I; 221406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // End-of-path node? 221506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (Succ->succ_empty()) { 221661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // If we found an end-of-path node that is not a sink. 221761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!Succ->isSink()) { 22184a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer bugReports.push_back(I); 221940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 22204a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer exampleReport = I; 222161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek WL.clear(); 222261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek break; 222361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 222406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Found a sink? Continue on to the next successor. 222506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 222606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 222706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Mark the successor as visited. If it hasn't been explored, 222806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // enqueue it to the DFS worklist. 222906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek unsigned &mark = Visited[Succ]; 223006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (!mark) { 223106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek mark = 1; 223206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.push_back(Succ); 223306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek break; 223406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 223506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 223661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 223761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // The worklist may have been cleared at this point. First 223861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // check if it is empty before checking the last item. 223961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!WL.empty() && &WL.back() == &WI) 224006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.pop_back(); 224106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 224206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 224306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 224461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // ExampleReport will be NULL if all the nodes in the equivalence class 224561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // were post-dominated by sinks. 224640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek return exampleReport; 224761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek} 2248e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 2249cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::FlushReport(BugReportEquivClass& EQ) { 22505f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BugReport*, 10> bugReports; 225140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports); 2252c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (exampleReport) { 2253c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek const PathDiagnosticConsumers &C = getPathDiagnosticConsumers(); 2254c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (PathDiagnosticConsumers::const_iterator I=C.begin(), 2255c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek E=C.end(); I != E; ++I) { 2256c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek FlushReport(exampleReport, **I, bugReports); 2257c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 2258c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 2259c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 2260c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2261c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReporter::FlushReport(BugReport *exampleReport, 2262c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticConsumer &PD, 2263c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek ArrayRef<BugReport*> bugReports) { 22641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2265cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // FIXME: Make sure we use the 'R' for the path that was actually used. 22661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Probably doesn't make a difference in practice. 226740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugType& BT = exampleReport->getBugType(); 22681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 22696f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<PathDiagnostic> 227007189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek D(new PathDiagnostic(exampleReport->getDeclWithIssue(), 227107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek exampleReport->getBugType().getName(), 22723a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose exampleReport->getDescription(), 22733a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose exampleReport->getShortDescription(/*Fallback=*/false), 2274d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek BT.getCategory())); 2275d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek 2276c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // Generate the full path diagnostic, using the generation scheme 2277d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // specified by the PathDiagnosticConsumer. Note that we have to generate 2278d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // path diagnostics even for consumers which do not support paths, because 2279d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // the BugReporterVisitors may mark this bug as a false positive. 2280d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!bugReports.empty()) 2281d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!generatePathDiagnostic(*D.get(), PD, bugReports)) 2282d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return; 22833148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek 2284c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // If the path is empty, generate a single step path with the location 2285c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // of the issue. 2286802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek if (D->path.empty()) { 2287c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticLocation L = exampleReport->getLocation(getSourceManager()); 2288c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticPiece *piece = 2289c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek new PathDiagnosticEventPiece(L, exampleReport->getDescription()); 2290c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek BugReport::ranges_iterator Beg, End; 2291c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek llvm::tie(Beg, End) = exampleReport->getRanges(); 229207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek for ( ; Beg != End; ++Beg) 229307189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek piece->addRange(*Beg); 22943a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose D->setEndOfPath(piece); 22953148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek } 22961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2297c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // Get the meta data. 2298c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek const BugReport::ExtraTextList &Meta = exampleReport->getExtraText(); 2299c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (BugReport::ExtraTextList::const_iterator i = Meta.begin(), 2300c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek e = Meta.end(); i != e; ++i) { 2301c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek D->addMeta(*i); 2302c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 2303c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2304c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PD.HandlePathDiagnostic(D.take()); 230561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 230657202071e477530e9348bc76671ee369b2399b92Ted Kremenek 230707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenekvoid BugReporter::EmitBasicReport(const Decl *DeclWithIssue, 230807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek StringRef name, 23095f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category, 2310590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks StringRef str, PathDiagnosticLocation Loc, 23118c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek SourceRange* RBeg, unsigned NumRanges) { 23121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2313404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // 'BT' is owned by BugReporter. 2314404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = getBugTypeForName(name, category); 2315590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks BugReport *R = new BugReport(*BT, str, Loc); 231607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek R->setDeclWithIssue(DeclWithIssue); 2317cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg); 2318785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose emitReport(R); 2319cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek} 2320404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 23215f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerBugType *BugReporter::getBugTypeForName(StringRef name, 23225f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category) { 2323f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<136> fullDesc; 2324404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::raw_svector_ostream(fullDesc) << name << ":" << category; 2325404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::StringMapEntry<BugType *> & 2326404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry = StrBugTypes.GetOrCreateValue(fullDesc); 2327404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = entry.getValue(); 2328404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis if (!BT) { 2329404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BT = new BugType(name, category); 2330404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry.setValue(BT); 2331404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis } 2332404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis return BT; 2333404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis} 2334