BugReporter.cpp revision 1a7bcc41efb73d80fd45eb71494b073f388d333c
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 121c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// Recursively scan through a path and prune out calls and macros pieces 122c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// that aren't needed. Return true if afterwards the path contains 123c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// "interesting stuff" which means it should be pruned from the parent path. 12480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaksbool BugReporter::RemoveUneededCalls(PathPieces &pieces, BugReport *R) { 125c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek bool containsSomethingInteresting = false; 126c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek const unsigned N = pieces.size(); 127c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 128c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek for (unsigned i = 0 ; i < N ; ++i) { 129c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek // Remove the front piece from the path. If it is still something we 130c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek // want to keep once we are done, we will push it back on the end. 131c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek IntrusiveRefCntPtr<PathDiagnosticPiece> piece(pieces.front()); 132c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek pieces.pop_front(); 133c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 134725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek switch (piece->getKind()) { 135725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Call: { 136725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticCallPiece *call = cast<PathDiagnosticCallPiece>(piece); 13780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Check if the location context is interesting. 13880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks assert(LocationContextMap.count(call)); 13980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (R->isInteresting(LocationContextMap[call])) { 14080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks containsSomethingInteresting = true; 14180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 14280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 143725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // Recursively clean out the subclass. Keep this call around if 144725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // it contains any informative diagnostics. 14580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!RemoveUneededCalls(call->path, R)) 146725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek continue; 147725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek containsSomethingInteresting = true; 148725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 149725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 150725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Macro: { 151725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticMacroPiece *macro = cast<PathDiagnosticMacroPiece>(piece); 15280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!RemoveUneededCalls(macro->subPieces, R)) 153725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek continue; 154c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek containsSomethingInteresting = true; 155725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 156725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 157725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Event: { 158725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticEventPiece *event = cast<PathDiagnosticEventPiece>(piece); 159725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // We never throw away an event, but we do throw it away wholesale 160725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // as part of a path if we throw the entire path away. 16122505ef15e32db31a4f834a387cf73a913bc8f66Ted Kremenek containsSomethingInteresting |= !event->isPrunable(); 162725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 163725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 164725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::ControlFlow: 165725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 166c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek } 167c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 168c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek pieces.push_back(piece); 169c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek } 170c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 171c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek return containsSomethingInteresting; 172c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek} 173c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 174c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek//===----------------------------------------------------------------------===// 1753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnosticBuilder and its associated routines and helper objects. 176b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 177b479dadea93b93d3f0a335c3518b703f140b3f50Ted Kremenek 178c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xutypedef llvm::DenseMap<const ExplodedNode*, 179c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuconst ExplodedNode*> NodeBackMap; 1807dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek 181babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremeneknamespace { 182ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NodeMapClosure : public BugReport::NodeResolver { 1837dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeBackMap& M; 1847dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenekpublic: 1857dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeMapClosure(NodeBackMap *m) : M(*m) {} 1867dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek ~NodeMapClosure() {} 1871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1889c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *getOriginalNode(const ExplodedNode *N) { 1897dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeBackMap::iterator I = M.find(N); 1907dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek return I == M.end() ? 0 : I->second; 1917dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 1927dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek}; 1931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 194ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass PathDiagnosticBuilder : public BugReporterContext { 1957dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek BugReport *R; 196ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *PDC; 1976f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<ParentMap> PM; 1987dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeMapClosure NMC; 1991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic: 20059950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek const LocationContext *LC; 20159950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 2028966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek PathDiagnosticBuilder(GRBugReporter &br, 2031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump BugReport *r, NodeBackMap *Backmap, 204ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *pdc) 2058966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek : BugReporterContext(br), 20659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek R(r), PDC(pdc), NMC(Backmap), LC(r->getErrorNode()->getLocationContext()) 20759950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek {} 2081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2099c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N); 2101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2119c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os, 2129c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N); 2131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2148e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *getBugReport() { return R; } 2158e6431adab313e283a992698f6fc7afe62420999Anna Zaks 216212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); } 21759950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 21859950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek ParentMap& getParentMap() { return LC->getParentMap(); } 2191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 220c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek const Stmt *getParent(const Stmt *S) { 221c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek return getParentMap().getParent(S); 222c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek } 2231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2248966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek virtual NodeMapClosure& getNodeResolver() { return NMC; } 2257297134f128423fce2e88f92421ed135bded7d4eDouglas Gregor 226d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S); 2271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 228ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const { 229ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive; 2307dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 2317dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek 232babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek bool supportsLogicalOpControlFlow() const { 233babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek return PDC ? PDC->supportsLogicalOpControlFlow() : true; 2341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 235babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek}; 236babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek} // end anonymous namespace 237babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 23800605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 2399c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) { 2405f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetNextStmt(N)) 24159950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek return PathDiagnosticLocation(S, getSourceManager(), LC); 24200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek 2430cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return PathDiagnosticLocation::createDeclEnd(N->getLocationContext(), 2440cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks getSourceManager()); 245082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek} 2461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 24700605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 2489c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os, 2499c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N) { 250babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 251143ca222583a4a355fdc89af852deef287499300Ted Kremenek // Slow, but probably doesn't matter. 252b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek if (os.str().empty()) 253b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << ' '; 2541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 25500605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek const PathDiagnosticLocation &Loc = ExecutionContinues(N); 2561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 25700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek if (Loc.asStmt()) 258b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << "Execution continues on line " 259642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << getSourceManager().getExpansionLineNumber(Loc.asLocation()) 2608966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek << '.'; 2614f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 2624f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "Execution jumps to the end of the "; 2634f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek const Decl *D = N->getLocationContext()->getDecl(); 2644f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek if (isa<ObjCMethodDecl>(D)) 2654f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "method"; 2664f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else if (isa<FunctionDecl>(D)) 2674f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "function"; 2684f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 2694f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek assert(isa<BlockDecl>(D)); 2704f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "anonymous block"; 2714f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 2724f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << '.'; 2734f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 2741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 275082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek return Loc; 276143ca222583a4a355fdc89af852deef287499300Ted Kremenek} 277143ca222583a4a355fdc89af852deef287499300Ted Kremenek 278ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenekstatic bool IsNested(const Stmt *S, ParentMap &PM) { 279ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S))) 280ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek return true; 2811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 282ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const Stmt *Parent = PM.getParentIgnoreParens(S); 2831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 284ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (Parent) 285ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek switch (Parent->getStmtClass()) { 286ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::ForStmtClass: 287ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::DoStmtClass: 288ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::WhileStmtClass: 289ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek return true; 290ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek default: 291ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek break; 292ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek } 2931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 295ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek} 296ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek 297d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticLocation 298d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { 2999c378f705405d37f49795d5e915989de774fe11fTed Kremenek assert(S && "Null Stmt *passed to getEnclosingStmtLocation"); 3001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ParentMap &P = getParentMap(); 3018966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek SourceManager &SMgr = getSourceManager(); 302e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 303ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek while (IsNested(S, P)) { 3048c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const Stmt *Parent = P.getParentIgnoreParens(S); 3051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 306af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (!Parent) 307af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 3081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 309af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek switch (Parent->getStmtClass()) { 3105fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek case Stmt::BinaryOperatorClass: { 3115fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const BinaryOperator *B = cast<BinaryOperator>(Parent); 3125fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 313220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 3145fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek break; 3151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 316af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::CompoundStmtClass: 317af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::StmtExprClass: 318220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 3191d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ChooseExprClass: 3201d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // Similar to '?' if we are referring to condition, just have the edge 3211d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // point to the entire choose expression. 3221d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (cast<ChooseExpr>(Parent)->getCond() == S) 323220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 3241d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 325220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 32656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 3271d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ConditionalOperatorClass: 3281d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // For '?', if we are referring to condition, just have the edge point 3291d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // to the entire '?' expression. 33056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (cast<AbstractConditionalOperator>(Parent)->getCond() == S) 331220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 3321d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 333220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 334af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::DoStmtClass: 335220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 336af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ForStmtClass: 337af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ForStmt>(Parent)->getBody() == S) 338220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 3391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump break; 340af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::IfStmtClass: 341af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<IfStmt>(Parent)->getCond() != S) 342220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 3438bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek break; 344af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 345af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S) 346220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 347af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 348af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::WhileStmtClass: 349af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<WhileStmt>(Parent)->getCond() != S) 350220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 351af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 352af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek default: 353af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 354af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek } 355af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek 356d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek S = Parent; 357d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek } 3581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 359d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek assert(S && "Cannot have null Stmt for PathDiagnosticLocation"); 360e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 361e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // Special case: DeclStmts can appear in for statement declarations, in which 362e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // case the ForStmt is the context. 363e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (isa<DeclStmt>(S)) { 364e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (const Stmt *Parent = P.getParent(S)) { 365e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek switch (Parent->getStmtClass()) { 366e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek case Stmt::ForStmtClass: 367e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 368220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 369e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek default: 370e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek break; 3711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 3721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 373e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 374e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek else if (isa<BinaryOperator>(S)) { 375e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // Special case: the binary operator represents the initialization 376e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // code in a for statement (this can happen when the variable being 377e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // initialized is an old variable. 378e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (const ForStmt *FS = 379e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek dyn_cast_or_null<ForStmt>(P.getParentIgnoreParens(S))) { 380e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (FS->getInit() == S) 381220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(FS, SMgr, LC); 382e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 383e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 384e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 385220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 386d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek} 387d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 388cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 3893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// "Minimal" path diagnostic generation algorithm. 390cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 39156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zakstypedef std::pair<PathDiagnosticCallPiece*, const ExplodedNode*> StackDiagPair; 39256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zakstypedef SmallVector<StackDiagPair, 6> StackDiagVector; 39356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 394368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaksstatic void updateStackPiecesWithMessage(PathDiagnosticPiece *P, 39556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector &CallStack) { 396368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // If the piece contains a special message, add it to all the call 397368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // pieces on the active stack. 398368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (PathDiagnosticEventPiece *ep = 399368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks dyn_cast<PathDiagnosticEventPiece>(P)) { 400368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 40156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (ep->hasCallStackHint()) 40256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks for (StackDiagVector::iterator I = CallStack.begin(), 40356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks E = CallStack.end(); I != E; ++I) { 40456a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks PathDiagnosticCallPiece *CP = I->first; 40556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks const ExplodedNode *N = I->second; 4068fe4525680ce72e90cee3e58b5654e3ae955447fNAKAMURA Takumi std::string stackMsg = ep->getCallStackMessage(N); 40756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 408368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // The last message on the path to final bug is the most important 409368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // one. Since we traverse the path backwards, do not add the message 410368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // if one has been previously added. 41156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (!CP->hasCallStackMessage()) 41256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks CP->setCallStackMessage(stackMsg); 41356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks } 414368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 415368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks} 416cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 41777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM); 41814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 4193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekstatic void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, 4203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticBuilder &PDB, 4213bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose const ExplodedNode *N, 4223bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ArrayRef<BugReporterVisitor *> visitors) { 4238966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek 4243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceManager& SMgr = PDB.getSourceManager(); 42559950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek const LocationContext *LC = PDB.LC; 4269c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() 4273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek ? NULL : *(N->pred_begin()); 428368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 42956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector CallStack; 430368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 4313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (NextNode) { 4321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump N = NextNode; 43359950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC = N->getLocationContext(); 4343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NextNode = GetPredecessorNode(N); 4351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 43661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek ProgramPoint P = N->getLocation(); 43780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 43880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks do { 43980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (const CallExitEnd *CE = dyn_cast<CallExitEnd>(&P)) { 44080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece *C = 44180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece::construct(N, *CE, SMgr); 44280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GRBugReporter& BR = PDB.getBugReporter(); 44380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks BR.addCallPieceLocationContextPair(C, CE->getCalleeContext()); 44480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(C); 44580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.pushActivePath(&C->path); 44680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks CallStack.push_back(StackDiagPair(C, N)); 44780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 4489373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks } 449183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 45080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (const CallEnter *CE = dyn_cast<CallEnter>(&P)) { 45180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Flush all locations, and pop the active path. 45280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks bool VisitedEntireCall = PD.isWithinCall(); 45380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.popActivePath(); 45480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 45580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Either we just added a bunch of stuff to the top-level path, or 45680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // we have a previous CallExitEnd. If the former, it means that the 45780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // path terminated within a function call. We must then take the 45880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // current contents of the active path and place it within 45980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // a new PathDiagnosticCallPiece. 46080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece *C; 46180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (VisitedEntireCall) { 46280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 46380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } else { 46480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Decl *Caller = CE->getLocationContext()->getDecl(); 46580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 46680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GRBugReporter& BR = PDB.getBugReporter(); 46780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks BR.addCallPieceLocationContextPair(C, CE->getCalleeContext()); 46880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 46980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 47080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C->setCallee(*CE, SMgr); 47180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!CallStack.empty()) { 47280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks assert(CallStack.back().first == C); 47380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks CallStack.pop_back(); 47480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 47580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 476368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 4771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 47880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 47980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CFGBlock *Src = BE->getSrc(); 48080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CFGBlock *Dst = BE->getDst(); 48180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Stmt *T = Src->getTerminator(); 4821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 48380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!T) 48480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 4851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 48680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation Start = 48780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createBegin(T, SMgr, 48880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks N->getLocationContext()); 4891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 49080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks switch (T->getStmtClass()) { 49161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek default: 49261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 4931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 49461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek case Stmt::GotoStmtClass: 4951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::IndirectGotoStmtClass: { 4969c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Stmt *S = GetNextStmt(N); 4971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 49861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek if (!S) 49980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 5001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 501297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 5021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::raw_string_ostream os(sbuf); 503d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S); 5041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 50500605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os << "Control jumps to line " 50680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 50780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 50880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 50961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 51061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 5111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::SwitchStmtClass: { 51361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek // Figure out what case arm we took. 514297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 515297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 5161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5179c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const Stmt *S = Dst->getLabel()) { 518220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(S, SMgr, LC); 5191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5205a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek switch (S->getStmtClass()) { 52180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks default: 52280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "No cases match in the switch statement. " 52380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks "Control jumps to line " 52480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 52580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 52680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks case Stmt::DefaultStmtClass: 52780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "Control jumps to the 'default' case at line " 52880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 52980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 53080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 53180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks case Stmt::CaseStmtClass: { 53280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "Control jumps to 'case "; 53380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CaseStmt *Case = cast<CaseStmt>(S); 53480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Expr *LHS = Case->getLHS()->IgnoreParenCasts(); 53580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 53680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine if it is an enum. 53780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks bool GetRawInt = true; 53880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 53980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) { 54080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // FIXME: Maybe this should be an assertion. Are there cases 54180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // were it is not an EnumConstantDecl? 54280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const EnumConstantDecl *D = 54303509aea098772644bf4662dc1c88634818ceeccZhongxing Xu dyn_cast<EnumConstantDecl>(DR->getDecl()); 5441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 54580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (D) { 54680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GetRawInt = false; 54780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << *D; 5485a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek } 54980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 5509ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 55180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (GetRawInt) 55280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << LHS->EvaluateKnownConstInt(PDB.getASTContext()); 5539ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 55480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << ":' at line " 55580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 55680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 55761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 55880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 55980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 56080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 56161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 562567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek else { 563c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "'Default' branch taken. "; 5641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N); 56580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 56680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 567567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek } 5681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 56961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 57061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 5711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5722673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::BreakStmtClass: 5732673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::ContinueStmtClass: { 574297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 575297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 57600605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 57780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 57880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 5792673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek break; 5802673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek } 5811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 58280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine control-flow for ternary '?'. 58356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 584706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek case Stmt::ConditionalOperatorClass: { 585297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 586297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 5871d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek os << "'?' condition is "; 5881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 589706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()+1) == Dst) 590082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "false"; 591706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek else 592082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "true"; 5931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 59400605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 5951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5961d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (const Stmt *S = End.asStmt()) 5971d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 5981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 59980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 60080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 601babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 602babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 6031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 60480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine control-flow for short-circuited '&&' and '||'. 605babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek case Stmt::BinaryOperatorClass: { 606babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek if (!PDB.supportsLogicalOpControlFlow()) 607babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 6081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 60903509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const BinaryOperator *B = cast<BinaryOperator>(T); 610babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek std::string sbuf; 611babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek llvm::raw_string_ostream os(sbuf); 612babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek os << "Left side of '"; 6131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6142de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_LAnd) { 615f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "&&" << "' is "; 6161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 617f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 618f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 619220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 6200cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 62180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 62280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 62380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 6241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 625f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 626f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 627220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 628f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 62980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 63080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 6311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 632babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 633babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek else { 6342de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(B->getOpcode() == BO_LOr); 635f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "||" << "' is "; 6361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 637f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 638f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 639220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 640f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 64180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 64280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 643f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 644f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 645f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 646220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 6470cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 64880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 64980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 65080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 651f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 652babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 6531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 654706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek break; 655706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek } 6561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::DoStmtClass: { 658706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()) == Dst) { 659297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 660297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 6611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 662c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "Loop condition is true. "; 663d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 6641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 665d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 666d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 6671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 66880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 66980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 670082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 671082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek else { 67200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 6731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 674d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 675d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 6761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 67780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 67880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Loop condition is false. Exiting loop")); 6793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 6801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 6823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 6831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::WhileStmtClass: 6851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::ForStmtClass: { 6863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) { 6873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::string sbuf; 6883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::raw_string_ostream os(sbuf); 6891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek os << "Loop condition is false. "; 6913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 6923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 6933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 6941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 69580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 69680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 6973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 6983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 6993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 7013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 7021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 70380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 70480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Loop condition is true. Entering loop body")); 7053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 7083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::IfStmtClass: { 7113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 7143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 7151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) 71780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 71880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Taking false branch")); 7191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else 72080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 72180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Taking true branch")); 7221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 7243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 72580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 7263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 72780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } while(0); 7281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 729dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (NextNode) { 7308e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add diagnostic pieces from custom visitors. 7318e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 7323bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 7333bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = visitors.end(); 7343bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose I != E; ++I) { 735368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 7362042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 737368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks updateStackPiecesWithMessage(p, CallStack); 738368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 739dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 7408966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 7413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 74314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // After constructing the full PathDiagnostic, do a pass over it to compact 74414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // PathDiagnosticPieces that occur within a macro. 74577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager()); 7463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 7473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 7483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 7495fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek// "Extensive" PathDiagnostic generation. 7505fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 7515fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 7525fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenekstatic bool IsControlFlowExpr(const Stmt *S) { 7535fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const Expr *E = dyn_cast<Expr>(S); 7541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7555fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (!E) 7565fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return false; 7571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump E = E->IgnoreParenCasts(); 7591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 76056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (isa<AbstractConditionalOperator>(E)) 7615fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 7621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7635fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) 7645fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 7655fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 7661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 7685fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek} 7695fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 77014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremeneknamespace { 771ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ContextLocation : public PathDiagnosticLocation { 7728f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsDead; 7738f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekpublic: 7748f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation(const PathDiagnosticLocation &L, bool isdead = false) 7758f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek : PathDiagnosticLocation(L), IsDead(isdead) {} 7761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void markDead() { IsDead = true; } 7788f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool isDead() const { return IsDead; } 7798f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek}; 7801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 781ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass EdgeBuilder { 7828f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek std::vector<ContextLocation> CLocs; 7838f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek typedef std::vector<ContextLocation>::iterator iterator; 78414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnostic &PD; 78514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB; 78614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation PrevLoc; 7871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7888f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsConsumedExpr(const PathDiagnosticLocation &L); 7891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 79014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek bool containsLocation(const PathDiagnosticLocation &Container, 79114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee); 7921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 79314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L); 7941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7959650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L, 7969650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek bool firstCharOnly = false) { 7978c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (const Stmt *S = L.asStmt()) { 7989650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek const Stmt *Original = S; 7998c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek while (1) { 8008c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek // Adjust the location for some expressions that are best referenced 8018c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek // by one of their subexpressions. 8029650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek switch (S->getStmtClass()) { 8039650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek default: 8049650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek break; 8059650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ParenExprClass: 806f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne case Stmt::GenericSelectionExprClass: 807f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne S = cast<Expr>(S)->IgnoreParens(); 8089650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 8099650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 81056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 8119650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ConditionalOperatorClass: 81256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall S = cast<AbstractConditionalOperator>(S)->getCond(); 8139650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 8149650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 8159650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ChooseExprClass: 8169650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek S = cast<ChooseExpr>(S)->getCond(); 8179650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 8189650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 8199650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::BinaryOperatorClass: 8209650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek S = cast<BinaryOperator>(S)->getLHS(); 8219650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 8229650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 8239650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek } 8241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8259650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek break; 8268c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 8271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8289650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek if (S != Original) 82959950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek L = PathDiagnosticLocation(S, L.getManager(), PDB.LC); 8308c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 8311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8329650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek if (firstCharOnly) 8331531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks L = PathDiagnosticLocation::createSingleLocation(L); 8349650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek 8358c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek return L; 8368c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 8371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 83814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void popLocation() { 8398f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) { 8405c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // For contexts, we only one the first character as the range. 84107c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek rawAddEdge(cleanUpLocation(CLocs.back(), true)); 8425c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek } 84314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.pop_back(); 84414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 8451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 84614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekpublic: 84714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb) 84814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek : PD(pd), PDB(pdb) { 8491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 850a301a6773db085575ac51e3c966858180390c25bTed Kremenek // If the PathDiagnostic already has pieces, add the enclosing statement 851a301a6773db085575ac51e3c966858180390c25bTed Kremenek // of the first piece as a context as well. 852802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek if (!PD.path.empty()) { 853802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek PrevLoc = (*PD.path.begin())->getLocation(); 8541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 85514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = PrevLoc.asStmt()) 856e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 85714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 85814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 85914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 86014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ~EdgeBuilder() { 86114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) popLocation(); 8620cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 863a301a6773db085575ac51e3c966858180390c25bTed Kremenek // Finally, add an initial edge from the start location of the first 864a301a6773db085575ac51e3c966858180390c25bTed Kremenek // statement (if it doesn't already exist). 8650cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin( 86659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC, 8670cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PDB.getSourceManager()); 8680cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks if (L.isValid()) 8690cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks rawAddEdge(L); 87014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 87114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 8725de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek void flushLocations() { 8735de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek while (!CLocs.empty()) 8745de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek popLocation(); 8755de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek PrevLoc = PathDiagnosticLocation(); 8765de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek } 8775de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 87814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false); 8791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8808bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek void rawAddEdge(PathDiagnosticLocation NewLoc); 8811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 88214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addContext(const Stmt *S); 883183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose void addContext(const PathDiagnosticLocation &L); 884e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek void addExtendedContext(const Stmt *S); 8851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}; 88614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} // end anonymous namespace 88714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 88814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 88914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekPathDiagnosticLocation 89014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekEdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) { 89114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = L.asStmt()) { 89214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (IsControlFlowExpr(S)) 89314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 8941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return PDB.getEnclosingStmtLocation(S); 89614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 8971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 89814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 89914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 90014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 90114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekbool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container, 90214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee) { 90314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 90414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container == Containee) 90514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 9061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 90714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container.asDecl()) 90814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 9091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 91014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = Containee.asStmt()) 91114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *ContainerS = Container.asStmt()) { 91214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (S) { 91314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (S == ContainerS) 91414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 91514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek S = PDB.getParent(S); 91614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 91714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return false; 91814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 91914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 92014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Less accurate: compare using source ranges. 92114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContainerR = Container.asRange(); 92214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContaineeR = Containee.asRange(); 9231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 92414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceManager &SM = PDB.getSourceManager(); 925402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin()); 926402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd()); 927402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin()); 928402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd()); 9291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 930642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg); 931642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd); 932642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg); 933642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd); 9341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 93514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek assert(ContainerBegLine <= ContainerEndLine); 9361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(ContaineeBegLine <= ContaineeEndLine); 9371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 93814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return (ContainerBegLine <= ContaineeBegLine && 93914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ContainerEndLine >= ContaineeEndLine && 94014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerBegLine != ContaineeBegLine || 941a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerRBeg) <= 942a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContaineeRBeg)) && 94314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerEndLine != ContaineeEndLine || 944a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerREnd) >= 9456488dc31153be6f98b404c7860be6c66bb4ec917Ted Kremenek SM.getExpansionColumnNumber(ContaineeREnd))); 94614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 94714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 94814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) { 94914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!PrevLoc.isValid()) { 95014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PrevLoc = NewLoc; 95114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 95214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 9531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9548c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc); 9558c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc); 9561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9578c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (NewLocClean.asLocation() == PrevLocClean.asLocation()) 95814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 9591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 96014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // FIXME: Ignore intra-macro edges for now. 961402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth if (NewLocClean.asLocation().getExpansionLoc() == 962402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth PrevLocClean.asLocation().getExpansionLoc()) 96314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 96414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 9652042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean)); 9668c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek PrevLoc = NewLoc; 96714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 96814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 96914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) { 9701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 971a301a6773db085575ac51e3c966858180390c25bTed Kremenek if (!alwaysAdd && NewLoc.asLocation().isMacroID()) 972a301a6773db085575ac51e3c966858180390c25bTed Kremenek return; 9731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 97414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc); 97514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 97614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 9778f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation &TopContextLoc = CLocs.back(); 9781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 97914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 98014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == CLoc) { 9818f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 9824c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek if (IsConsumedExpr(TopContextLoc) && 9834c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek !IsControlFlowExpr(TopContextLoc.asStmt())) 9848f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek TopContextLoc.markDead(); 9858f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek 98614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 9878f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 98814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 98914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 99014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 99114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 99214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, CLoc)) { 9938f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 99414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 9951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9964c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek if (IsConsumedExpr(CLoc) && !IsControlFlowExpr(CLoc.asStmt())) { 9978f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek CLocs.push_back(ContextLocation(CLoc, true)); 9988f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return; 9998f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 10008f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 10011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 100214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(CLoc); 10031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 100414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 100514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 100614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 100714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 100814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 10091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10105c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // If we reach here, there is no enclosing context. Just add the edge. 10115c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek rawAddEdge(NewLoc); 101214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 101314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 10148f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekbool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) { 10158f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt())) 10168f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X); 10171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10188f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return false; 10198f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek} 10201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1021e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenekvoid EdgeBuilder::addExtendedContext(const Stmt *S) { 1022e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (!S) 1023e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek return; 10241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const Stmt *Parent = PDB.getParent(S); 1026e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek while (Parent) { 1027e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (isa<CompoundStmt>(Parent)) 1028e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek Parent = PDB.getParent(Parent); 1029e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek else 1030e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1031e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1032e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek 1033e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (Parent) { 1034e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek switch (Parent->getStmtClass()) { 1035e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::DoStmtClass: 1036e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 1037e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(Parent); 1038e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek default: 1039e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1040e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1041e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 10421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1043e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(S); 1044e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek} 10451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 104614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addContext(const Stmt *S) { 104714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!S) 104814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 104914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 105059950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.LC); 1051183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose addContext(L); 1052183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose} 10531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1054183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rosevoid EdgeBuilder::addContext(const PathDiagnosticLocation &L) { 105514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 105614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &TopContextLoc = CLocs.back(); 105714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 105814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 105914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == L) 106014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 106114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 106214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, L)) { 106314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 10641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 106514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 106614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 106714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 106814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 106914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 107014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 107114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 107214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 107314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 107411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// Cone-of-influence: support the reverse propagation of "interesting" symbols 107511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// and values by tracing interesting calculations backwards through evaluated 107611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// expressions along a path. This is probably overly complicated, but the idea 107711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// is that if an expression computed an "interesting" value, the child 107811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// expressions are are also likely to be "interesting" as well (which then 107911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// propagates to the values they in turn compute). This reverse propagation 108011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// is needed to track interesting correlations across function call boundaries, 108111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// where formal arguments bind to actual arguments, etc. This is also needed 108211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// because the constraint solver sometimes simplifies certain symbolic values 108311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// into constants when appropriate, and this complicates reasoning about 108411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// interesting values. 108511abcecc8c919673237cf37384290a1ef1943976Ted Kremenektypedef llvm::DenseSet<const Expr *> InterestingExprs; 108611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 108711abcecc8c919673237cf37384290a1ef1943976Ted Kremenekstatic void reversePropagateIntererstingSymbols(BugReport &R, 108811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs &IE, 108911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const ProgramState *State, 109011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const Expr *Ex, 109111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *LCtx) { 109211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek SVal V = State->getSVal(Ex, LCtx); 109311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (!(R.isInteresting(V) || IE.count(Ex))) 109411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek return; 109511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 109611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek switch (Ex->getStmtClass()) { 109711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek default: 109811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (!isa<CastExpr>(Ex)) 109911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek break; 110011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // Fall through. 110111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek case Stmt::BinaryOperatorClass: 110211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek case Stmt::UnaryOperatorClass: { 110311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek for (Stmt::const_child_iterator CI = Ex->child_begin(), 110411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CE = Ex->child_end(); 110511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CI != CE; ++CI) { 110611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *child = dyn_cast_or_null<Expr>(*CI)) { 110711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek IE.insert(child); 110811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek SVal ChildV = State->getSVal(child, LCtx); 110911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek R.markInteresting(ChildV); 111011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 111111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek break; 111211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 111311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 111411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 111511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 111611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek R.markInteresting(V); 111711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek} 111811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 111911abcecc8c919673237cf37384290a1ef1943976Ted Kremenekstatic void reversePropagateInterestingSymbols(BugReport &R, 112011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs &IE, 112111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const ProgramState *State, 112211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CalleeCtx, 112311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CallerCtx) 112411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek{ 1125852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose // FIXME: Handle non-CallExpr-based CallEvents. 112611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const StackFrameContext *Callee = CalleeCtx->getCurrentStackFrame(); 112711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const Stmt *CallSite = Callee->getCallSite(); 1128852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite)) { 112911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) { 113011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek FunctionDecl::param_const_iterator PI = FD->param_begin(), 113111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek PE = FD->param_end(); 113211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end(); 113311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek for (; AI != AE && PI != PE; ++AI, ++PI) { 113411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *ArgE = *AI) { 113511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const ParmVarDecl *PD = *PI) { 113611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek Loc LV = State->getLValue(PD, CalleeCtx); 113711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (R.isInteresting(LV) || R.isInteresting(State->getRawSVal(LV))) 113811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek IE.insert(ArgE); 113911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 114011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 114111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 114211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 114311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 114411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek} 114511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 114614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekstatic void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, 114714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB, 11483bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose const ExplodedNode *N, 11493bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ArrayRef<BugReporterVisitor *> visitors) { 115014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder EB(PD, PDB); 11510cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks const SourceManager& SM = PDB.getSourceManager(); 115256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector CallStack; 115311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs IE; 115414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 11559c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); 115614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (NextNode) { 115714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek N = NextNode; 115814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek NextNode = GetPredecessorNode(N); 115914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ProgramPoint P = N->getLocation(); 116014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 1161dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek do { 116211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const PostStmt *PS = dyn_cast<PostStmt>(&P)) { 116311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *Ex = PS->getStmtAs<Expr>()) 116411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 116511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek N->getState().getPtr(), Ex, 116611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek N->getLocationContext()); 116711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 116811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 11690b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks if (const CallExitEnd *CE = dyn_cast<CallExitEnd>(&P)) { 1170183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose const Stmt *S = CE->getCalleeContext()->getCallSite(); 1171183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) { 1172852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 1173852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose N->getState().getPtr(), Ex, 1174852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose N->getLocationContext()); 1175852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose } 1176183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 1177183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece *C = 1178183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece::construct(N, *CE, SM); 117980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GRBugReporter& BR = PDB.getBugReporter(); 118080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks BR.addCallPieceLocationContextPair(C, CE->getCalleeContext()); 1181183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 1182183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose EB.addEdge(C->callReturn, true); 1183183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose EB.flushLocations(); 1184183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 1185183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PD.getActivePath().push_front(C); 1186183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PD.pushActivePath(&C->path); 1187183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose CallStack.push_back(StackDiagPair(C, N)); 11885de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek break; 11895de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek } 11904ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek 11912042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // Pop the call hierarchy if we are done walking the contents 11922042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // of a function call. 11932042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek if (const CallEnter *CE = dyn_cast<CallEnter>(&P)) { 1194097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek // Add an edge to the start of the function. 1195097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek const Decl *D = CE->getCalleeContext()->getDecl(); 1196097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek PathDiagnosticLocation pos = 1197097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek PathDiagnosticLocation::createBegin(D, SM); 1198097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek EB.addEdge(pos); 1199097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek 1200097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek // Flush all locations, and pop the active path. 1201183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose bool VisitedEntireCall = PD.isWithinCall(); 12024ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek EB.flushLocations(); 12032042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.popActivePath(); 12044ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek PDB.LC = N->getLocationContext(); 1205097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek 1206183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose // Either we just added a bunch of stuff to the top-level path, or 1207183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose // we have a previous CallExitEnd. If the former, it means that the 12082042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // path terminated within a function call. We must then take the 12092042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // current contents of the active path and place it within 12102042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // a new PathDiagnosticCallPiece. 1211183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece *C; 1212183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose if (VisitedEntireCall) { 1213183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 1214183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose } else { 1215183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose const Decl *Caller = CE->getLocationContext()->getDecl(); 12169373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 121780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GRBugReporter& BR = PDB.getBugReporter(); 121880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks BR.addCallPieceLocationContextPair(C, CE->getCalleeContext()); 12199373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks } 1220852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose 1221183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose C->setCallee(*CE, SM); 1222183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose EB.addContext(C->getLocation()); 1223368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 1224368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (!CallStack.empty()) { 122556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks assert(CallStack.back().first == C); 1226368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks CallStack.pop_back(); 1227368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 12282042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek break; 12292042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek } 12304ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek 12314ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // Note that is important that we update the LocationContext 12324ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // after looking at CallExits. CallExit basically adds an 12334ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // edge in the *caller*, so we don't want to update the LocationContext 12344ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // too soon. 12354ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek PDB.LC = N->getLocationContext(); 12365de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 1237dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Block edges. 123811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 123911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // Does this represent entering a call? If so, look at propagating 124011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // interesting symbols across call boundaries. 124111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (NextNode) { 124211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CallerCtx = NextNode->getLocationContext(); 124311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CalleeCtx = PDB.LC; 124411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (CallerCtx != CalleeCtx) { 124511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek reversePropagateInterestingSymbols(*PDB.getBugReport(), IE, 124611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek N->getState().getPtr(), 124711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CalleeCtx, CallerCtx); 124811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 124911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 125011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 1251dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Are we jumping to the head of a loop? Add a special diagnostic. 1252f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) { 125359950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PathDiagnosticLocation L(Loop, SM, PDB.LC); 1254ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const CompoundStmt *CS = NULL; 12551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1256f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) 1257f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek CS = dyn_cast<CompoundStmt>(FS->getBody()); 1258f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) 1259f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek CS = dyn_cast<CompoundStmt>(WS->getBody()); 12601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1261dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek PathDiagnosticEventPiece *p = 1262dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek new PathDiagnosticEventPiece(L, 126307c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek "Looping back to the head of the loop"); 12642dd17abf11ae64339fa6bfaa57d76e13a5fbe5b8Ted Kremenek p->setPrunable(true); 12651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1266dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek EB.addEdge(p->getLocation(), true); 12672042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 12681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1269ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (CS) { 12700cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation BL = 12710cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createEndBrace(CS, SM); 127207c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek EB.addEdge(BL); 1273dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 12748bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 1275f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek 1276f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek if (const Stmt *Term = BE->getSrc()->getTerminator()) 1277ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek EB.addContext(Term); 12781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1279dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 12808bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 128114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 12821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) { 12831a7bcc41efb73d80fd45eb71494b073f388d333cJordan Rose CFGElement First = BE->getFirstElement(); 12841a7bcc41efb73d80fd45eb71494b073f388d333cJordan Rose if (const CFGStmt *S = First.getAs<CFGStmt>()) { 12853c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const Stmt *stmt = S->getStmt(); 12863c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (IsControlFlowExpr(stmt)) { 1287b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu // Add the proper context for '&&', '||', and '?'. 12883c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addContext(stmt); 1289b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 1290b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu else 12913c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt()); 1292dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 1293b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu 1294dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 1295dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 12965de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 12975de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 1298dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } while (0); 12991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1300dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (!NextNode) 130114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek continue; 13021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13038e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add pieces from custom visitors. 13048e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 13053bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 13063bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = visitors.end(); 13073bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose I != E; ++I) { 13088e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 13098966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek const PathDiagnosticLocation &Loc = p->getLocation(); 13108966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek EB.addEdge(Loc, true); 13112042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 1312368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks updateStackPiecesWithMessage(p, CallStack); 1313368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 13148966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek if (const Stmt *S = Loc.asStmt()) 13151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 13168966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 13171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 131814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 131914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 132014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 13215fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 13223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugType and subclasses. 13233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 1324404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios KyrtzidisBugType::~BugType() { } 1325404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 13263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugType::FlushReports(BugReporter &BR) {} 13273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 132899ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BuiltinBug::anchor() {} 132999ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 13303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 13313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReport and subclasses. 13323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 1333e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 133499ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BugReport::NodeResolver::anchor() {} 133599ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 13368e6431adab313e283a992698f6fc7afe62420999Anna Zaksvoid BugReport::addVisitor(BugReporterVisitor* visitor) { 13378e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (!visitor) 13388e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 13398e6431adab313e283a992698f6fc7afe62420999Anna Zaks 13408e6431adab313e283a992698f6fc7afe62420999Anna Zaks llvm::FoldingSetNodeID ID; 13418e6431adab313e283a992698f6fc7afe62420999Anna Zaks visitor->Profile(ID); 13428e6431adab313e283a992698f6fc7afe62420999Anna Zaks void *InsertPos; 13438e6431adab313e283a992698f6fc7afe62420999Anna Zaks 13448e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) { 13458e6431adab313e283a992698f6fc7afe62420999Anna Zaks delete visitor; 13468e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 13478e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 13488e6431adab313e283a992698f6fc7afe62420999Anna Zaks 13498e6431adab313e283a992698f6fc7afe62420999Anna Zaks CallbacksSet.InsertNode(visitor, InsertPos); 13503bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose Callbacks.push_back(visitor); 13513bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 13528e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 13538e6431adab313e283a992698f6fc7afe62420999Anna Zaks 13548e6431adab313e283a992698f6fc7afe62420999Anna ZaksBugReport::~BugReport() { 13558e6431adab313e283a992698f6fc7afe62420999Anna Zaks for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) { 1356dc757b049796949e4b11646445a6598f0bdabd7aAnna Zaks delete *I; 13578e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 1358c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek while (!interestingSymbols.empty()) { 1359c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek popInterestingSymbolsAndRegions(); 1360c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 13618e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 1362e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 136307189521a15d9c088216b943649cb9fe231cbb57Ted Kremenekconst Decl *BugReport::getDeclWithIssue() const { 136407189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek if (DeclWithIssue) 136507189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return DeclWithIssue; 136607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 136707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek const ExplodedNode *N = getErrorNode(); 136807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek if (!N) 136907189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return 0; 137007189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 137107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek const LocationContext *LC = N->getLocationContext(); 137207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return LC->getCurrentStackFrame()->getDecl(); 137307189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek} 137407189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 1375e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaksvoid BugReport::Profile(llvm::FoldingSetNodeID& hash) const { 1376e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddPointer(&BT); 1377e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddString(Description); 1378ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks if (UniqueingLocation.isValid()) { 1379ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks UniqueingLocation.Profile(hash); 1380ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks } else if (Location.isValid()) { 1381590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks Location.Profile(hash); 1382590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } else { 1383590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(ErrorNode); 1384590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode)); 1385590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } 1386e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 1387e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks for (SmallVectorImpl<SourceRange>::const_iterator I = 1388e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks Ranges.begin(), E = Ranges.end(); I != E; ++I) { 1389e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks const SourceRange range = *I; 1390e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!range.isValid()) 1391e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks continue; 1392e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getBegin().getRawEncoding()); 1393e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getEnd().getRawEncoding()); 1394e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 1395e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks} 13963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 139776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(SymbolRef sym) { 139876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!sym) 139976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return; 14003bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 14013bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // If the symbol wasn't already in our set, note a configuration change. 1402c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (getInterestingSymbols().insert(sym).second) 14033bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 14048ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose 14058ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose if (const SymbolMetadata *meta = dyn_cast<SymbolMetadata>(sym)) 1406c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek getInterestingRegions().insert(meta->getRegion()); 140776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 140876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 140976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(const MemRegion *R) { 141076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!R) 141176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return; 14123bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 14133bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // If the base region wasn't already in our set, note a configuration change. 141476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek R = R->getBaseRegion(); 1415c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (getInterestingRegions().insert(R).second) 14163bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 14178ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose 141876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 1419c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek getInterestingSymbols().insert(SR->getSymbol()); 142076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 142176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 142276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(SVal V) { 142376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek markInteresting(V.getAsRegion()); 142476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek markInteresting(V.getAsSymbol()); 142576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 142676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 142780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaksvoid BugReport::markInteresting(const LocationContext *LC) { 142880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!LC) 142980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return; 143080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks InterestingLocationContexts.insert(LC); 143180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks} 143280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 1433c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(SVal V) { 143476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return isInteresting(V.getAsRegion()) || isInteresting(V.getAsSymbol()); 143576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 143676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 1437c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(SymbolRef sym) { 143876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!sym) 143976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 14408ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose // We don't currently consider metadata symbols to be interesting 14418ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose // even if we know their region is interesting. Is that correct behavior? 1442c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return getInterestingSymbols().count(sym); 144376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 144476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 1445c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(const MemRegion *R) { 144676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!R) 144776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 144876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek R = R->getBaseRegion(); 1449c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek bool b = getInterestingRegions().count(R); 145076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (b) 145176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return true; 145276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 1453c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return getInterestingSymbols().count(SR->getSymbol()); 145476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 145576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 1456c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 145780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaksbool BugReport::isInteresting(const LocationContext *LC) { 145880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!LC) 145980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return false; 146080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return InterestingLocationContexts.count(LC); 146180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks} 146280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 1463c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::lazyInitializeInterestingSets() { 1464c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (interestingSymbols.empty()) { 1465c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.push_back(new Symbols()); 1466c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.push_back(new Regions()); 1467c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 1468c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 1469c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 1470c4bac8e376b98d633bb00ee5f510d5e58449753cTed KremenekBugReport::Symbols &BugReport::getInterestingSymbols() { 1471c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek lazyInitializeInterestingSets(); 1472c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return *interestingSymbols.back(); 1473c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 1474c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 1475c4bac8e376b98d633bb00ee5f510d5e58449753cTed KremenekBugReport::Regions &BugReport::getInterestingRegions() { 1476c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek lazyInitializeInterestingSets(); 1477c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return *interestingRegions.back(); 1478c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 1479c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 1480c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::pushInterestingSymbolsAndRegions() { 1481c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.push_back(new Symbols(getInterestingSymbols())); 1482c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.push_back(new Regions(getInterestingRegions())); 1483c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 1484c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 1485c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::popInterestingSymbolsAndRegions() { 1486c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek delete interestingSymbols.back(); 1487c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.pop_back(); 1488c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek delete interestingRegions.back(); 1489c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.pop_back(); 1490c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 149176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 14929c378f705405d37f49795d5e915989de774fe11fTed Kremenekconst Stmt *BugReport::getStmt() const { 1493e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!ErrorNode) 1494e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return 0; 1495e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 1496212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care ProgramPoint ProgP = ErrorNode->getLocation(); 14975f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek const Stmt *S = NULL; 14981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14999c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (BlockEntrance *BE = dyn_cast<BlockEntrance>(&ProgP)) { 1500fafd3834754d2093e0ad7a1c005860fd527ecb7fZhongxing Xu CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit(); 150150d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu if (BE->getBlock() == &Exit) 1502212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care S = GetPreviousStmt(ErrorNode); 15033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15045f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (!S) 15051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump S = GetStmt(ProgP); 15061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return S; 15083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 15093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1510640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidisstd::pair<BugReport::ranges_iterator, BugReport::ranges_iterator> 1511e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna ZaksBugReport::getRanges() { 1512e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // If no custom ranges, add the range of the statement corresponding to 1513e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // the error node. 1514e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (Ranges.empty()) { 1515e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (const Expr *E = dyn_cast_or_null<Expr>(getStmt())) 1516e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks addRange(E->getSourceRange()); 1517e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks else 1518e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 1519e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 1520e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 152114924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks // User-specified absence of range info. 152214924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks if (Ranges.size() == 1 && !Ranges.begin()->isValid()) 152314924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 152414924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks 1525e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(Ranges.begin(), Ranges.end()); 15263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 15273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1528590dd8e0959d8df5621827768987c4792b74fc06Anna ZaksPathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const { 1529b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks if (ErrorNode) { 1530590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(!Location.isValid() && 1531b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks "Either Location or ErrorNode should be specified but not both."); 1532b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks 15339c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const Stmt *S = GetCurrentOrPreviousStmt(ErrorNode)) { 1534590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks const LocationContext *LC = ErrorNode->getLocationContext(); 1535590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks 15363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // For member expressions, return the location of the '.' or '->'. 15375b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) 1538590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createMemberLoc(ME, SM); 15395b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek // For binary operators, return the location of the operator. 15405b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) 1541590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createOperatorLoc(B, SM); 15423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1543590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createBegin(S, SM, LC); 15443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1545b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } else { 1546b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks assert(Location.isValid()); 1547b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks return Location; 1548b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } 1549b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks 1550590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation(); 15513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 15523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 15533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 15543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReporter and subclasses. 15553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 15563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 15574a5f724538cbc275370c9504e8169ce92503256cBenjamin KramerBugReportEquivClass::~BugReportEquivClass() { } 1558a2f4ec0df645fc249d2945beef9653f03b175417Zhongxing XuGRBugReporter::~GRBugReporter() { } 15593106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReporterData::~BugReporterData() {} 15603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 156138b02b912e1a55c912f603c4369431264d36a381Zhongxing XuExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); } 15623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 156318c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekProgramStateManager& 15643106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekGRBugReporter::getStateManager() { return Eng.getStateManager(); } 15653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 15663b030a28cda2b953758507769c1d436bec5ec45eAnna ZaksBugReporter::~BugReporter() { 15673b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks FlushReports(); 15683b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks 15693b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks // Free the bug reports we are tracking. 15703b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks typedef std::vector<BugReportEquivClass *> ContTy; 15713b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end(); 15723b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks I != E; ++I) { 15733b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks delete *I; 15743b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks } 15753b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks} 15763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 15773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugReporter::FlushReports() { 15783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (BugTypes.isEmpty()) 15793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return; 15803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 15813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // First flush the warnings for each BugType. This may end up creating new 1582404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // warnings and new BugTypes. 1583404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: Only NSErrorChecker needs BugType's FlushReports. 1584404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // Turn NSErrorChecker into a proper checker and remove this. 15855f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<const BugType*, 16> bugTypes; 15863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) 1587404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis bugTypes.push_back(*I); 15885f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVector<const BugType*, 16>::iterator 1589404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I) 15903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const_cast<BugType*>(*I)->FlushReports(*this); 15913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1592d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks // We need to flush reports in deterministic order to ensure the order 1593d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks // of the reports is consistent between runs. 15940eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks typedef std::vector<BugReportEquivClass *> ContVecTy; 15950eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks for (ContVecTy::iterator EI=EQClassesVector.begin(), EE=EQClassesVector.end(); 15960eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks EI != EE; ++EI){ 15970eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks BugReportEquivClass& EQ = **EI; 1598404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis FlushReport(EQ); 15993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 16003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1601404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // BugReporter owns and deletes only BugTypes created implicitly through 1602404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // EmitBasicReport. 1603404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: There are leaks from checkers that assume that the BugTypes they 1604404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // create will be destroyed by the BugReporter. 1605404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis for (llvm::StringMap<BugType*>::iterator 1606404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I) 1607404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis delete I->second; 1608404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 16093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Remove all references to the BugType objects. 16103baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.getEmptySet(); 16113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 16123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 16133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 16143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnostics generation. 16153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 16163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 161738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xustatic std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, 1618c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::pair<ExplodedNode*, unsigned> > 161938b02b912e1a55c912f603c4369431264d36a381Zhongxing XuMakeReportGraph(const ExplodedGraph* G, 16205f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<const ExplodedNode*> &nodes) { 16211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the trimmed graph. It will contain the shortest paths from the 16231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // error nodes to the root. In the new graph we should only have one 16243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // error node unless there are two or more error nodes with the same minimum 16253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // path length. 162638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu ExplodedGraph* GTrim; 1627c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu InterExplodedGraphMap* NMap; 16283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 16293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*, const void*> InverseMap; 163040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek llvm::tie(GTrim, NMap) = G->Trim(nodes.data(), nodes.data() + nodes.size(), 163140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek &InverseMap); 16321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create owning pointers for GTrim and NMap just to ensure that they are 16343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // released when this function exists. 16356f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<ExplodedGraph> AutoReleaseGTrim(GTrim); 16366f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<InterExplodedGraphMap> AutoReleaseNMap(NMap); 16371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the (first) error node in the trimmed graph. We just need to consult 16393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // the node map (NMap) which maps from nodes in the original graph to nodes 16403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // in the new graph. 1641938332c657390d1e782e0adc03b092993edae962Ted Kremenek 1642c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::queue<const ExplodedNode*> WS; 164338b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu typedef llvm::DenseMap<const ExplodedNode*, unsigned> IndexMapTy; 1644938332c657390d1e782e0adc03b092993edae962Ted Kremenek IndexMapTy IndexMap; 16453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 164640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek for (unsigned nodeIndex = 0 ; nodeIndex < nodes.size(); ++nodeIndex) { 164740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek const ExplodedNode *originalNode = nodes[nodeIndex]; 164840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (const ExplodedNode *N = NMap->getMappedNode(originalNode)) { 1649938332c657390d1e782e0adc03b092993edae962Ted Kremenek WS.push(N); 165040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek IndexMap[originalNode] = nodeIndex; 16513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 165240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 16531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1654938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(!WS.empty() && "No error node found in the trimmed graph."); 16553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 16563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create a new (third!) graph with a single path. This is the graph 16573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // that will be returned to the caller. 1658c77a55126fcad66fb086f8e100a494caa2496a2dZhongxing Xu ExplodedGraph *GNew = new ExplodedGraph(); 16591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Sometimes the trimmed graph can contain a cycle. Perform a reverse BFS 16613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // to the root node, and then construct a new graph that contains only 16623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // a single path. 16633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*,unsigned> Visited; 16641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek unsigned cnt = 0; 16669c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *Root = 0; 16671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!WS.empty()) { 16699c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *Node = WS.front(); 16703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek WS.pop(); 16711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Visited.find(Node) != Visited.end()) 16733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 16741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Visited[Node] = cnt++; 16761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Node->pred_empty()) { 16783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Root = Node; 16793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 16803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 16811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1682c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu for (ExplodedNode::const_pred_iterator I=Node->pred_begin(), 16833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek E=Node->pred_end(); I!=E; ++I) 16843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek WS.push(*I); 16853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 16861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1687938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(Root); 16881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now walk from the root down the BFS path, always taking the successor 16903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // with the lowest number. 16911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ExplodedNode *Last = 0, *First = 0; 16923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NodeBackMap *BM = new NodeBackMap(); 1693938332c657390d1e782e0adc03b092993edae962Ted Kremenek unsigned NodeIndex = 0; 16941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1695c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu for ( const ExplodedNode *N = Root ;;) { 16963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Lookup the number associated with the current node. 16973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*,unsigned>::iterator I = Visited.find(N); 1698938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(I != Visited.end()); 16991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the equivalent node in the new graph with the same state 17013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // and location. 17029c378f705405d37f49795d5e915989de774fe11fTed Kremenek ExplodedNode *NewN = GNew->getNode(N->getLocation(), N->getState()); 17031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Store the mapping to the original node. 17053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*, const void*>::iterator IMitr=InverseMap.find(N); 17063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(IMitr != InverseMap.end() && "No mapping to original node."); 1707c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu (*BM)[NewN] = (const ExplodedNode*) IMitr->second; 17081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Link up the new node with the previous node. 17103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Last) 17115fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek NewN->addPredecessor(Last, *GNew); 17121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Last = NewN; 17141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Are we at the final node? 1716938332c657390d1e782e0adc03b092993edae962Ted Kremenek IndexMapTy::iterator IMI = 1717c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu IndexMap.find((const ExplodedNode*)(IMitr->second)); 1718938332c657390d1e782e0adc03b092993edae962Ted Kremenek if (IMI != IndexMap.end()) { 17193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek First = NewN; 1720938332c657390d1e782e0adc03b092993edae962Ted Kremenek NodeIndex = IMI->second; 17213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 17223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 17231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the next successor node. We choose the node that is marked 17253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // with the lowest DFS number. 1726c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::const_succ_iterator SI = N->succ_begin(); 1727c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::const_succ_iterator SE = N->succ_end(); 17283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek N = 0; 17291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (unsigned MinVal = 0; SI != SE; ++SI) { 17311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek I = Visited.find(*SI); 17331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (I == Visited.end()) 17353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 17361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!N || I->second < MinVal) { 17383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek N = *SI; 17393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MinVal = I->second; 17403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 17413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 17421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1743938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(N); 17443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 17451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1746938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(First); 1747938332c657390d1e782e0adc03b092993edae962Ted Kremenek 17483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return std::make_pair(std::make_pair(GNew, BM), 17493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::make_pair(First, NodeIndex)); 17503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 1751d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 17523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object 17533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// and collapses PathDiagosticPieces that are expanded by macros. 175477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) { 17552042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek typedef std::vector<std::pair<IntrusiveRefCntPtr<PathDiagnosticMacroPiece>, 17562042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek SourceLocation> > MacroStackTy; 17571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1758c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith typedef std::vector<IntrusiveRefCntPtr<PathDiagnosticPiece> > 17593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy; 17601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStackTy MacroStack; 17623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy Pieces; 17631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 176477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek for (PathPieces::const_iterator I = path.begin(), E = path.end(); 17652042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek I!=E; ++I) { 176677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 176777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek PathDiagnosticPiece *piece = I->getPtr(); 176877d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 176977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek // Recursively compact calls. 177077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek if (PathDiagnosticCallPiece *call=dyn_cast<PathDiagnosticCallPiece>(piece)){ 177177d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek CompactPathDiagnostic(call->path, SM); 177277d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek } 177377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 17743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Get the location of the PathDiagnosticPiece. 177577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek const FullSourceLoc Loc = piece->getLocation().asLocation(); 17761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine the instantiation location, which is the location we group 17783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // related PathDiagnosticPieces. 17791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation InstantiationLoc = Loc.isMacroID() ? 1780402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 17813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 17821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Loc.isFileID()) { 17843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.clear(); 178577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek Pieces.push_back(piece); 17863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 17873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1788706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek 17893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(Loc.isMacroID()); 17901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Is the PathDiagnosticPiece within the same macro group? 17923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) { 179377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek MacroStack.back().first->subPieces.push_back(piece); 17943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 17953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1796d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 17973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // We aren't in the same group. Are we descending into a new macro 17983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // or are part of an old one? 1799c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith IntrusiveRefCntPtr<PathDiagnosticMacroPiece> MacroGroup; 1800d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 18013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ? 1802402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 18033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 18041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Walk the entire macro stack. 18063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!MacroStack.empty()) { 18073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (InstantiationLoc == MacroStack.back().second) { 18083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 18093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 18103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 18111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (ParentInstantiationLoc == MacroStack.back().second) { 18133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 18143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 181561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 18161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.pop_back(); 18186837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek } 18191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) { 18213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create a new macro group and add it to the stack. 1822590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticMacroPiece *NewGroup = 1823590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks new PathDiagnosticMacroPiece( 182477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek PathDiagnosticLocation::createSingleLocation(piece->getLocation())); 18255a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek 18263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (MacroGroup) 1827802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek MacroGroup->subPieces.push_back(NewGroup); 18283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 18293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(InstantiationLoc.isFileID()); 18303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Pieces.push_back(NewGroup); 18313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 18321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = NewGroup; 18343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc)); 18357dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 18363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 18373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Finally, add the PathDiagnosticPiece to the group. 183877d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek MacroGroup->subPieces.push_back(piece); 18393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 18401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now take the pieces and construct a new PathDiagnostic. 184277d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek path.clear(); 18431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 184477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) 184577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek path.push_back(*I); 184661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 184761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 18483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, 1849c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticConsumer &PC, 1850c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek ArrayRef<BugReport *> &bugReports) { 18511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 185240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek assert(!bugReports.empty()); 18535f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<const ExplodedNode *, 10> errorNodes; 1854c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (ArrayRef<BugReport*>::iterator I = bugReports.begin(), 1855c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek E = bugReports.end(); I != E; ++I) { 185640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek errorNodes.push_back((*I)->getErrorNode()); 185740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 18581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Construct a new graph that contains only a single path from the error 18601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // node to a root. 186138b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu const std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, 1862c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::pair<ExplodedNode*, unsigned> >& 186340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek GPair = MakeReportGraph(&getGraph(), errorNodes); 18641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the BugReport with the original location. 186640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek assert(GPair.second.second < bugReports.size()); 186740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *R = bugReports[GPair.second.second]; 18683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(R && "No original report found for sliced graph."); 18691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18706f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<ExplodedGraph> ReportGraph(GPair.first.first); 18716f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<NodeBackMap> BackMap(GPair.first.second); 1872c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode *N = GPair.second.first; 18731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Start building the path diagnostic... 1875c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticBuilder PDB(*this, R, BackMap.get(), &PC); 18761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18778e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Register additional node visitors. 187850bbc165b063155cc23c360deb7b865502e068e2Anna Zaks R->addVisitor(new NilReceiverBRVisitor()); 187950bbc165b063155cc23c360deb7b865502e068e2Anna Zaks R->addVisitor(new ConditionBRVisitor()); 18801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18813bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose BugReport::VisitorList visitors; 18823bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose unsigned originalReportConfigToken, finalReportConfigToken; 18833bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 18843bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // While generating diagnostics, it's possible the visitors will decide 18853bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // new symbols and regions are interesting, or add other visitors based on 18863bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // the information they find. If they do, we need to regenerate the path 18873bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // based on our new report configuration. 18883bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose do { 18893bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // Get a clean copy of all the visitors. 18903bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (BugReport::visitor_iterator I = R->visitor_begin(), 18913bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = R->visitor_end(); I != E; ++I) 18923bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose visitors.push_back((*I)->clone()); 18933bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 18943bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // Clear out the active path from any previous work. 18953a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose PD.resetPath(); 18963bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose originalReportConfigToken = R->getConfigurationChangeToken(); 18973bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 18983bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // Generate the very last diagnostic piece - the piece is visible before 18993bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // the trace is expanded. 19003bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose PathDiagnosticPiece *LastPiece = 0; 19013bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end(); 19023bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose I != E; ++I) { 19033bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) { 19043bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose assert (!LastPiece && 19053bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose "There can only be one final piece in a diagnostic."); 19063bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose LastPiece = Piece; 19073bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose } 190823f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks } 19093bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose if (!LastPiece) 19103bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R); 19113bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose if (LastPiece) 19123a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose PD.setEndOfPath(LastPiece); 19133bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose else 19143bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose return; 191523f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks 19163bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose switch (PDB.getGenerationScheme()) { 1917ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie case PathDiagnosticConsumer::Extensive: 19183bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose GenerateExtensivePathDiagnostic(PD, PDB, N, visitors); 19195fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek break; 1920ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie case PathDiagnosticConsumer::Minimal: 19213bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose GenerateMinimalPathDiagnostic(PD, PDB, N, visitors); 19223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 1923c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek case PathDiagnosticConsumer::None: 1924c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek llvm_unreachable("PathDiagnosticConsumer::None should never appear here"); 19253bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose } 19263bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 19273bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // Clean up the visitors we used. 19283bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose llvm::DeleteContainerPointers(visitors); 19293bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 19303bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // Did anything change while generating this path? 19313bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose finalReportConfigToken = R->getConfigurationChangeToken(); 19323bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose } while(finalReportConfigToken != originalReportConfigToken); 19333bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 1934c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek // Finally, prune the diagnostic path of uninteresting stuff. 1935ed7948b55fa4b2505f240cc5287137f451172b4cTed Kremenek if (R->shouldPrunePath()) { 193680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks bool hasSomethingInteresting = RemoveUneededCalls(PD.getMutablePieces(), R); 1937ed7948b55fa4b2505f240cc5287137f451172b4cTed Kremenek assert(hasSomethingInteresting); 1938ed7948b55fa4b2505f240cc5287137f451172b4cTed Kremenek (void) hasSomethingInteresting; 1939ed7948b55fa4b2505f240cc5287137f451172b4cTed Kremenek } 19403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 19411aa44c7c9198796085b77c6bdd7c90030845a688Ted Kremenek 1942cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::Register(BugType *BT) { 19433baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.add(BugTypes, BT); 194476d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek} 194576d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek 19461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid BugReporter::EmitReport(BugReport* R) { 1947cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // Compute the bug report's hash to determine its equivalence class. 1948cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek llvm::FoldingSetNodeID ID; 1949cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek R->Profile(ID); 19501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Lookup the equivance class. If there isn't one, create it. 1952cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek BugType& BT = R->getBugType(); 1953cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek Register(&BT); 1954cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek void *InsertPos; 1955404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos); 19561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1957cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek if (!EQ) { 1958cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ = new BugReportEquivClass(R); 1959404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis EQClasses.InsertNode(EQ, InsertPos); 19603b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks EQClassesVector.push_back(EQ); 1961cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek } 1962cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek else 1963cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ->AddReport(R); 196461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 196561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 196606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 196706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 196806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek// Emitting reports in equivalence classes. 196906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 197006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 197106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremeneknamespace { 1972ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamstruct FRIEC_WLItem { 197306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *N; 197406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek ExplodedNode::const_succ_iterator I, E; 197506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 197606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek FRIEC_WLItem(const ExplodedNode *n) 197706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek : N(n), I(N->succ_begin()), E(N->succ_end()) {} 197806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek}; 197906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek} 198006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 198161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenekstatic BugReport * 198261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted KremenekFindReportInEquivalenceClass(BugReportEquivClass& EQ, 19835f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<BugReport*> &bugReports) { 198461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 198506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end(); 198606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(I != E); 19874a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer BugType& BT = I->getBugType(); 198861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 198940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // If we don't need to suppress any of the nodes because they are 199040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // post-dominated by a sink, simply add all the nodes in the equivalence class 199140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // to 'Nodes'. Any of the reports will serve as a "representative" report. 199261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!BT.isSuppressOnSink()) { 19934a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer BugReport *R = I; 199461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) { 19959c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N = I->getErrorNode(); 199661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (N) { 19974a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer R = I; 199840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek bugReports.push_back(R); 199961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 200061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 200106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek return R; 200261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 200361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 200406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // For bug reports that should be suppressed when all paths are post-dominated 200506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // by a sink node, iterate through the reports in the equivalence class 200606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // until we find one that isn't post-dominated (if one exists). We use a 200706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // DFS traversal of the ExplodedGraph to find a non-sink node. We could write 200806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // this as a recursive function, but we don't want to risk blowing out the 200906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // stack for very long paths. 201040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = 0; 201161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 201206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; I != E; ++I) { 20134a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer const ExplodedNode *errorNode = I->getErrorNode(); 201406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 201540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!errorNode) 201606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 201740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->isSink()) { 2018b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable( 201906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek "BugType::isSuppressSink() should not be 'true' for sink end nodes"); 202006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 202161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // No successors? By definition this nodes isn't post-dominated by a sink. 202240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->succ_empty()) { 20234a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer bugReports.push_back(I); 202440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 20254a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer exampleReport = I; 202661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek continue; 202761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 202861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 202906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // At this point we know that 'N' is not a sink and it has at least one 203006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // successor. Use a DFS worklist to find a non-sink end-of-path node. 203106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek typedef FRIEC_WLItem WLItem; 20325f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<WLItem, 10> DFSWorkList; 203306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek llvm::DenseMap<const ExplodedNode *, unsigned> Visited; 203406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 203506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek DFSWorkList WL; 203640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek WL.push_back(errorNode); 203740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek Visited[errorNode] = 1; 203806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 203906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek while (!WL.empty()) { 204006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WLItem &WI = WL.back(); 204106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(!WI.N->succ_empty()); 204206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 204306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; WI.I != WI.E; ++WI.I) { 204406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *Succ = *WI.I; 204506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // End-of-path node? 204606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (Succ->succ_empty()) { 204761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // If we found an end-of-path node that is not a sink. 204861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!Succ->isSink()) { 20494a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer bugReports.push_back(I); 205040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 20514a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer exampleReport = I; 205261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek WL.clear(); 205361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek break; 205461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 205506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Found a sink? Continue on to the next successor. 205606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 205706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 205806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Mark the successor as visited. If it hasn't been explored, 205906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // enqueue it to the DFS worklist. 206006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek unsigned &mark = Visited[Succ]; 206106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (!mark) { 206206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek mark = 1; 206306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.push_back(Succ); 206406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek break; 206506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 206606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 206761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 206861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // The worklist may have been cleared at this point. First 206961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // check if it is empty before checking the last item. 207061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!WL.empty() && &WL.back() == &WI) 207106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.pop_back(); 207206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 207306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 207406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 207561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // ExampleReport will be NULL if all the nodes in the equivalence class 207661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // were post-dominated by sinks. 207740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek return exampleReport; 207861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek} 2079e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 2080cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::FlushReport(BugReportEquivClass& EQ) { 20815f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BugReport*, 10> bugReports; 208240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports); 2083c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (exampleReport) { 2084c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek const PathDiagnosticConsumers &C = getPathDiagnosticConsumers(); 2085c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (PathDiagnosticConsumers::const_iterator I=C.begin(), 2086c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek E=C.end(); I != E; ++I) { 2087c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek FlushReport(exampleReport, **I, bugReports); 2088c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 2089c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 2090c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 2091c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2092c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReporter::FlushReport(BugReport *exampleReport, 2093c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticConsumer &PD, 2094c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek ArrayRef<BugReport*> bugReports) { 20951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2096cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // FIXME: Make sure we use the 'R' for the path that was actually used. 20971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Probably doesn't make a difference in practice. 209840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugType& BT = exampleReport->getBugType(); 20991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21006f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<PathDiagnostic> 210107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek D(new PathDiagnostic(exampleReport->getDeclWithIssue(), 210207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek exampleReport->getBugType().getName(), 21033a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose exampleReport->getDescription(), 21043a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose exampleReport->getShortDescription(/*Fallback=*/false), 2105d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek BT.getCategory())); 2106d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek 2107c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // Generate the full path diagnostic, using the generation scheme 2108c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // specified by the PathDiagnosticConsumer. 2109c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (PD.getGenerationScheme() != PathDiagnosticConsumer::None) { 2110c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (!bugReports.empty()) 2111c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek GeneratePathDiagnostic(*D.get(), PD, bugReports); 21122f0e89ea96292d2974eb1a7dddc0e9870aa86bb7Ted Kremenek } 21133148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek 2114c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // If the path is empty, generate a single step path with the location 2115c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // of the issue. 2116802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek if (D->path.empty()) { 2117c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticLocation L = exampleReport->getLocation(getSourceManager()); 2118c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticPiece *piece = 2119c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek new PathDiagnosticEventPiece(L, exampleReport->getDescription()); 2120c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek BugReport::ranges_iterator Beg, End; 2121c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek llvm::tie(Beg, End) = exampleReport->getRanges(); 212207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek for ( ; Beg != End; ++Beg) 212307189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek piece->addRange(*Beg); 21243a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose D->setEndOfPath(piece); 21253148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek } 21261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2127c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // Get the meta data. 2128c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek const BugReport::ExtraTextList &Meta = exampleReport->getExtraText(); 2129c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (BugReport::ExtraTextList::const_iterator i = Meta.begin(), 2130c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek e = Meta.end(); i != e; ++i) { 2131c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek D->addMeta(*i); 2132c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 2133c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2134c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PD.HandlePathDiagnostic(D.take()); 213561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 213657202071e477530e9348bc76671ee369b2399b92Ted Kremenek 213707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenekvoid BugReporter::EmitBasicReport(const Decl *DeclWithIssue, 213807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek StringRef name, 21395f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category, 2140590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks StringRef str, PathDiagnosticLocation Loc, 21418c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek SourceRange* RBeg, unsigned NumRanges) { 21421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2143404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // 'BT' is owned by BugReporter. 2144404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = getBugTypeForName(name, category); 2145590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks BugReport *R = new BugReport(*BT, str, Loc); 214607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek R->setDeclWithIssue(DeclWithIssue); 2147cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg); 2148cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EmitReport(R); 2149cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek} 2150404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 21515f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerBugType *BugReporter::getBugTypeForName(StringRef name, 21525f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category) { 2153f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<136> fullDesc; 2154404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::raw_svector_ostream(fullDesc) << name << ":" << category; 2155404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::StringMapEntry<BugType *> & 2156404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry = StrBugTypes.GetOrCreateValue(fullDesc); 2157404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = entry.getValue(); 2158404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis if (!BT) { 2159404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BT = new BugType(name, category); 2160404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry.setValue(BT); 2161404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis } 2162404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis return BT; 2163404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis} 2164