BugReporter.cpp revision 77d09441e59d3bced6c3d55505eb3a67a784fe02
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(); 511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 52b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return 0; 5361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 5461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 55c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic inline const ExplodedNode* 569c378f705405d37f49795d5e915989de774fe11fTed KremenekGetPredecessorNode(const ExplodedNode *N) { 57b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return N->pred_empty() ? NULL : *(N->pred_begin()); 58706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek} 59706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek 60c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic inline const ExplodedNode* 619c378f705405d37f49795d5e915989de774fe11fTed KremenekGetSuccessorNode(const ExplodedNode *N) { 62b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return N->succ_empty() ? NULL : *(N->succ_begin()); 63bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek} 642673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek 659c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic const Stmt *GetPreviousStmt(const ExplodedNode *N) { 66b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek for (N = GetPredecessorNode(N); N; N = GetPredecessorNode(N)) 675f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) 68b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 70b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return 0; 71b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek} 72b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek 739c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic const Stmt *GetNextStmt(const ExplodedNode *N) { 74b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek for (N = GetSuccessorNode(N); N; N = GetSuccessorNode(N)) 755f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) { 76f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek // Check if the statement is '?' or '&&'/'||'. These are "merges", 77f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek // not actual statement points. 78f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek switch (S->getStmtClass()) { 79f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek case Stmt::ChooseExprClass: 8056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: continue; 81f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek case Stmt::ConditionalOperatorClass: continue; 82f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek case Stmt::BinaryOperatorClass: { 832de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode(); 842de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (Op == BO_LAnd || Op == BO_LOr) 85f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek continue; 86f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek break; 87f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 88f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek default: 89f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek break; 90f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 91b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 92f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 94b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return 0; 95bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek} 96bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek 975f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt* 989c378f705405d37f49795d5e915989de774fe11fTed KremenekGetCurrentOrPreviousStmt(const ExplodedNode *N) { 995f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) 100b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 1011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 102b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return GetPreviousStmt(N); 103b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek} 1041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1055f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt* 1069c378f705405d37f49795d5e915989de774fe11fTed KremenekGetCurrentOrNextStmt(const ExplodedNode *N) { 1075f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) 108b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 1091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 110b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return GetNextStmt(N); 1113148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek} 1123148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek 113b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 114c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek// Diagnostic cleanup. 115c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek//===----------------------------------------------------------------------===// 116c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 117c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// Recursively scan through a path and prune out calls and macros pieces 118c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// that aren't needed. Return true if afterwards the path contains 119c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// "interesting stuff" which means it should be pruned from the parent path. 120c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenekstatic bool RemoveUneededCalls(PathPieces &pieces) { 121c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek bool containsSomethingInteresting = false; 122c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek const unsigned N = pieces.size(); 123c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 124c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek for (unsigned i = 0 ; i < N ; ++i) { 125c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek // Remove the front piece from the path. If it is still something we 126c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek // want to keep once we are done, we will push it back on the end. 127c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek IntrusiveRefCntPtr<PathDiagnosticPiece> piece(pieces.front()); 128c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek pieces.pop_front(); 129c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 130725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek switch (piece->getKind()) { 131725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Call: { 132725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticCallPiece *call = cast<PathDiagnosticCallPiece>(piece); 133725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // Recursively clean out the subclass. Keep this call around if 134725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // it contains any informative diagnostics. 135725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek if (!RemoveUneededCalls(call->path)) 136725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek continue; 137725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek containsSomethingInteresting = true; 138725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 139725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 140725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Macro: { 141725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticMacroPiece *macro = cast<PathDiagnosticMacroPiece>(piece); 142725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek if (!RemoveUneededCalls(macro->subPieces)) 143725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek continue; 144c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek containsSomethingInteresting = true; 145725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 146725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 147725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Event: { 148725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticEventPiece *event = cast<PathDiagnosticEventPiece>(piece); 149725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // We never throw away an event, but we do throw it away wholesale 150725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // as part of a path if we throw the entire path away. 151725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek if (!event->isPrunable()) 152725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek containsSomethingInteresting = true; 153725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 154725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 155725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::ControlFlow: 156725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 157c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek } 158c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 159c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek pieces.push_back(piece); 160c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek } 161c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 162c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek return containsSomethingInteresting; 163c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek} 164c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 165c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek//===----------------------------------------------------------------------===// 1663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnosticBuilder and its associated routines and helper objects. 167b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 168b479dadea93b93d3f0a335c3518b703f140b3f50Ted Kremenek 169c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xutypedef llvm::DenseMap<const ExplodedNode*, 170c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuconst ExplodedNode*> NodeBackMap; 1717dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek 172babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremeneknamespace { 173ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NodeMapClosure : public BugReport::NodeResolver { 1747dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeBackMap& M; 1757dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenekpublic: 1767dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeMapClosure(NodeBackMap *m) : M(*m) {} 1777dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek ~NodeMapClosure() {} 1781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1799c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *getOriginalNode(const ExplodedNode *N) { 1807dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeBackMap::iterator I = M.find(N); 1817dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek return I == M.end() ? 0 : I->second; 1827dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 1837dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek}; 1841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 185ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass PathDiagnosticBuilder : public BugReporterContext { 1867dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek BugReport *R; 187ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *PDC; 1886f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<ParentMap> PM; 1897dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeMapClosure NMC; 1901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic: 19159950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek const LocationContext *LC; 19259950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 1938966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek PathDiagnosticBuilder(GRBugReporter &br, 1941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump BugReport *r, NodeBackMap *Backmap, 195ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *pdc) 1968966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek : BugReporterContext(br), 19759950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek R(r), PDC(pdc), NMC(Backmap), LC(r->getErrorNode()->getLocationContext()) 19859950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek {} 1991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2009c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N); 2011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2029c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os, 2039c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N); 2041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2058e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *getBugReport() { return R; } 2068e6431adab313e283a992698f6fc7afe62420999Anna Zaks 207212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); } 20859950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 20959950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek ParentMap& getParentMap() { return LC->getParentMap(); } 2101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 211c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek const Stmt *getParent(const Stmt *S) { 212c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek return getParentMap().getParent(S); 213c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek } 2141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2158966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek virtual NodeMapClosure& getNodeResolver() { return NMC; } 2167297134f128423fce2e88f92421ed135bded7d4eDouglas Gregor 217d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S); 2181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 219ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const { 220ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive; 2217dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 2227dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek 223babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek bool supportsLogicalOpControlFlow() const { 224babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek return PDC ? PDC->supportsLogicalOpControlFlow() : true; 2251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 226babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek}; 227babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek} // end anonymous namespace 228babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 22900605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 2309c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) { 2315f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetNextStmt(N)) 23259950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek return PathDiagnosticLocation(S, getSourceManager(), LC); 23300605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek 2340cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return PathDiagnosticLocation::createDeclEnd(N->getLocationContext(), 2350cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks getSourceManager()); 236082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek} 2371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 23800605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 2399c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os, 2409c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N) { 241babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 242143ca222583a4a355fdc89af852deef287499300Ted Kremenek // Slow, but probably doesn't matter. 243b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek if (os.str().empty()) 244b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << ' '; 2451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 24600605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek const PathDiagnosticLocation &Loc = ExecutionContinues(N); 2471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 24800605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek if (Loc.asStmt()) 249b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << "Execution continues on line " 250642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << getSourceManager().getExpansionLineNumber(Loc.asLocation()) 2518966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek << '.'; 2524f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 2534f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "Execution jumps to the end of the "; 2544f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek const Decl *D = N->getLocationContext()->getDecl(); 2554f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek if (isa<ObjCMethodDecl>(D)) 2564f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "method"; 2574f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else if (isa<FunctionDecl>(D)) 2584f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "function"; 2594f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 2604f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek assert(isa<BlockDecl>(D)); 2614f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "anonymous block"; 2624f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 2634f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << '.'; 2644f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 2651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 266082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek return Loc; 267143ca222583a4a355fdc89af852deef287499300Ted Kremenek} 268143ca222583a4a355fdc89af852deef287499300Ted Kremenek 269ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenekstatic bool IsNested(const Stmt *S, ParentMap &PM) { 270ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S))) 271ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek return true; 2721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 273ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const Stmt *Parent = PM.getParentIgnoreParens(S); 2741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 275ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (Parent) 276ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek switch (Parent->getStmtClass()) { 277ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::ForStmtClass: 278ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::DoStmtClass: 279ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::WhileStmtClass: 280ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek return true; 281ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek default: 282ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek break; 283ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek } 2841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 286ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek} 287ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek 288d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticLocation 289d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { 2909c378f705405d37f49795d5e915989de774fe11fTed Kremenek assert(S && "Null Stmt *passed to getEnclosingStmtLocation"); 2911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ParentMap &P = getParentMap(); 2928966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek SourceManager &SMgr = getSourceManager(); 293e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 294ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek while (IsNested(S, P)) { 2958c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const Stmt *Parent = P.getParentIgnoreParens(S); 2961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 297af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (!Parent) 298af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 2991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 300af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek switch (Parent->getStmtClass()) { 3015fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek case Stmt::BinaryOperatorClass: { 3025fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const BinaryOperator *B = cast<BinaryOperator>(Parent); 3035fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 304220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 3055fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek break; 3061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 307af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::CompoundStmtClass: 308af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::StmtExprClass: 309220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 3101d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ChooseExprClass: 3111d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // Similar to '?' if we are referring to condition, just have the edge 3121d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // point to the entire choose expression. 3131d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (cast<ChooseExpr>(Parent)->getCond() == S) 314220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 3151d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 316220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 31756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 3181d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ConditionalOperatorClass: 3191d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // For '?', if we are referring to condition, just have the edge point 3201d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // to the entire '?' expression. 32156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (cast<AbstractConditionalOperator>(Parent)->getCond() == S) 322220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 3231d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 324220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 325af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::DoStmtClass: 326220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 327af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ForStmtClass: 328af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ForStmt>(Parent)->getBody() == S) 329220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 3301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump break; 331af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::IfStmtClass: 332af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<IfStmt>(Parent)->getCond() != S) 333220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 3348bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek break; 335af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 336af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S) 337220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 338af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 339af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::WhileStmtClass: 340af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<WhileStmt>(Parent)->getCond() != S) 341220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 342af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 343af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek default: 344af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 345af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek } 346af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek 347d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek S = Parent; 348d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek } 3491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 350d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek assert(S && "Cannot have null Stmt for PathDiagnosticLocation"); 351e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 352e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // Special case: DeclStmts can appear in for statement declarations, in which 353e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // case the ForStmt is the context. 354e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (isa<DeclStmt>(S)) { 355e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (const Stmt *Parent = P.getParent(S)) { 356e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek switch (Parent->getStmtClass()) { 357e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek case Stmt::ForStmtClass: 358e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 359220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 360e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek default: 361e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek break; 3621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 3631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 364e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 365e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek else if (isa<BinaryOperator>(S)) { 366e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // Special case: the binary operator represents the initialization 367e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // code in a for statement (this can happen when the variable being 368e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // initialized is an old variable. 369e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (const ForStmt *FS = 370e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek dyn_cast_or_null<ForStmt>(P.getParentIgnoreParens(S))) { 371e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (FS->getInit() == S) 372220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(FS, SMgr, LC); 373e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 374e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 375e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 376220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 377d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek} 378d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 379cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 3803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// ScanNotableSymbols: closure-like callback for scanning Store bindings. 381cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 382cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 38318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenekstatic const VarDecl* GetMostRecentVarDeclBinding(const ExplodedNode *N, 38418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek ProgramStateManager& VMgr, 38518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek SVal X) { 3861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for ( ; N ; N = N->pred_empty() ? 0 : *N->pred_begin()) { 3881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek ProgramPoint P = N->getLocation(); 3901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!isa<PostStmt>(P)) 3923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 3931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3949c378f705405d37f49795d5e915989de774fe11fTed Kremenek const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(cast<PostStmt>(P).getStmt()); 3951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!DR) 3973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 3981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3995eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal Y = N->getState()->getSVal(DR, N->getLocationContext()); 4001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (X != Y) 4023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 4031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4049c378f705405d37f49795d5e915989de774fe11fTed Kremenek const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); 4051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!VD) 4073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 4081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return VD; 410cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek } 4111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return 0; 413bb77e9b908658b354b058509d3801f3aed052becTed Kremenek} 414bb77e9b908658b354b058509d3801f3aed052becTed Kremenek 4153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremeneknamespace { 416ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NotableSymbolHandler 4173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek: public StoreManager::BindingsHandler { 4181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SymbolRef Sym; 4208bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef PrevSt; 4219c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Stmt *S; 42218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek ProgramStateManager& VMgr; 4239c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *Pred; 4241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump PathDiagnostic& PD; 4253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek BugReporter& BR; 4261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekpublic: 4281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 42918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek NotableSymbolHandler(SymbolRef sym, 4308bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef prevst, 43118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Stmt *s, 43218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek ProgramStateManager& vmgr, 43318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ExplodedNode *pred, 43418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek PathDiagnostic& pd, 43518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek BugReporter& br) 43618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek : Sym(sym), 43718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek PrevSt(prevst), 43818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek S(s), 43918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek VMgr(vmgr), 44018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek Pred(pred), 44118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek PD(pd), 44218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek BR(br) {} 4431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, 4453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SVal V) { 4461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SymbolRef ScanSym = V.getAsSymbol(); 4481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (ScanSym != Sym) 4503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Check if the previous state has this binding. 4531397663af9dbcc24dbf0e11de43931b3dc08fdbbTed Kremenek SVal X = PrevSt->getSVal(loc::MemRegionVal(R)); 4541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (X == V) // Same binding? 4563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Different binding. Only handle assignments for now. We don't pull 4591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // this check out of the loop because we will eventually handle other 4603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // cases. 4611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek VarDecl *VD = 0; 4631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { 4653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!B->isAssignmentOp()) 4663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // What variable did we assign to? 4699c378f705405d37f49795d5e915989de774fe11fTed Kremenek DeclRefExpr *DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenCasts()); 4701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!DR) 4723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek VD = dyn_cast<VarDecl>(DR->getDecl()); 4753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 4769c378f705405d37f49795d5e915989de774fe11fTed Kremenek else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) { 4773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // FIXME: Eventually CFGs won't have DeclStmts. Right now we 4783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // assume that each DeclStmt has a single Decl. This invariant 479fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // holds by construction in the CFG. 4803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek VD = dyn_cast<VarDecl>(*DS->decl_begin()); 4813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 4821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!VD) 4843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // What is the most recently referenced variable with this binding? 4879c378f705405d37f49795d5e915989de774fe11fTed Kremenek const VarDecl *MostRecent = GetMostRecentVarDeclBinding(Pred, VMgr, V); 4881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MostRecent) 4903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the diagnostic. 4937dfc9420babe83e236a47e752f8723bd06070d9dZhanyong Wan if (Loc::isLocType(VD->getType())) { 494f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<64> buf; 4957df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose llvm::raw_svector_ostream os(buf); 496b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer os << '\'' << *VD << "' now aliases '" << *MostRecent << '\''; 497590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation L = 498590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation::createBegin(S, BR.getSourceManager(), 499590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks Pred->getLocationContext()); 5002042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticEventPiece(L, os.str())); 5013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 5021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 5041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 5053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}; 5063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 5073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 5089c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic void HandleNotableSymbol(const ExplodedNode *N, 5099c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Stmt *S, 5103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SymbolRef Sym, BugReporter& BR, 5113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnostic& PD) { 5121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5139c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *Pred = N->pred_empty() ? 0 : *N->pred_begin(); 5148bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef PrevSt = Pred ? Pred->getState() : 0; 5151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!PrevSt) 5173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return; 5181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Look at the region bindings of the current state that map to the 5203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // specified symbol. Are any of them not in the previous state? 52118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek ProgramStateManager& VMgr = cast<GRBugReporter>(BR).getStateManager(); 5223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NotableSymbolHandler H(Sym, PrevSt, S, VMgr, Pred, PD, BR); 5233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek cast<GRBugReporter>(BR).getStateManager().iterBindings(N->getState(), H); 52461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 52561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 5263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremeneknamespace { 527ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ScanNotableSymbols 5283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek: public StoreManager::BindingsHandler { 5291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::SmallSet<SymbolRef, 10> AlreadyProcessed; 5319c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N; 5329c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Stmt *S; 5333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek GRBugReporter& BR; 5343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnostic& PD; 5351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekpublic: 5379c378f705405d37f49795d5e915989de774fe11fTed Kremenek ScanNotableSymbols(const ExplodedNode *n, const Stmt *s, 5385f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek GRBugReporter& br, PathDiagnostic& pd) 5393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek : N(n), S(s), BR(br), PD(pd) {} 5401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek bool HandleBinding(StoreManager& SMgr, Store store, 5423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const MemRegion* R, SVal V) { 5431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SymbolRef ScanSym = V.getAsSymbol(); 5451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!ScanSym) 5473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 5481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!BR.isNotable(ScanSym)) 5503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 5511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (AlreadyProcessed.count(ScanSym)) 5533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 5541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek AlreadyProcessed.insert(ScanSym); 5561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek HandleNotableSymbol(N, S, ScanSym, BR, PD); 5583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 559bb77e9b908658b354b058509d3801f3aed052becTed Kremenek } 5603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}; 5613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} // end anonymous namespace 56250a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek 563cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 5643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// "Minimal" path diagnostic generation algorithm. 565cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 566cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 56777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM); 56814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 5693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekstatic void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, 5703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticBuilder &PDB, 571c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode *N) { 5728966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek 5733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceManager& SMgr = PDB.getSourceManager(); 57459950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek const LocationContext *LC = PDB.LC; 5759c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() 5763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek ? NULL : *(N->pred_begin()); 5773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (NextNode) { 5781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump N = NextNode; 57959950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC = N->getLocationContext(); 5803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NextNode = GetPredecessorNode(N); 5811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 58261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek ProgramPoint P = N->getLocation(); 5832042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek 5842042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek if (const CallExit *CE = dyn_cast<CallExit>(&P)) { 5852042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PathDiagnosticCallPiece *C = 5862042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PathDiagnosticCallPiece::construct(N, *CE, SMgr); 5872042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(C); 5882042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.pushActivePath(&C->path); 5892042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek continue; 5902042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek } 5912042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek 5922042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek if (const CallEnter *CE = dyn_cast<CallEnter>(&P)) { 5932042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.popActivePath(); 5942042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // The current active path should never be empty. Either we 5952042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // just added a bunch of stuff to the top-level path, or 5962042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // we have a previous CallExit. If the front of the active 5972042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // path is not a PathDiagnosticCallPiece, it means that the 5982042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // path terminated within a function call. We must then take the 5992042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // current contents of the active path and place it within 6002042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // a new PathDiagnosticCallPiece. 6012042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek assert(!PD.getActivePath().empty()); 6022042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PathDiagnosticCallPiece *C = 6032042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek dyn_cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 6042042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek if (!C) 6052042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek C = PathDiagnosticCallPiece::construct(PD.getActivePath()); 6062042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek C->setCallee(*CE, SMgr); 6072042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek continue; 6082042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek } 6091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6109c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 6119c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CFGBlock *Src = BE->getSrc(); 6129c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CFGBlock *Dst = BE->getDst(); 6139c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Stmt *T = Src->getTerminator(); 6141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 61561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek if (!T) 61661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek continue; 6171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 618590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation Start = 619590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation::createBegin(T, SMgr, 620590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks N->getLocationContext()); 6211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 62261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek switch (T->getStmtClass()) { 62361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek default: 62461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 6251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 62661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek case Stmt::GotoStmtClass: 6271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::IndirectGotoStmtClass: { 6289c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Stmt *S = GetNextStmt(N); 6291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 63061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek if (!S) 63161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek continue; 6321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 633297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 6341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::raw_string_ostream os(sbuf); 635d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S); 6361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 63700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os << "Control jumps to line " 638642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << End.asLocation().getExpansionLineNumber(); 6392042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 640802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek os.str())); 64161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 64261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 6431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::SwitchStmtClass: { 64561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek // Figure out what case arm we took. 646297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 647297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 6481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6499c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const Stmt *S = Dst->getLabel()) { 650220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(S, SMgr, LC); 6511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6525a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek switch (S->getStmtClass()) { 653082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek default: 654082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "No cases match in the switch statement. " 6553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek "Control jumps to line " 656642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << End.asLocation().getExpansionLineNumber(); 657082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek break; 658082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek case Stmt::DefaultStmtClass: 659082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "Control jumps to the 'default' case at line " 660642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << End.asLocation().getExpansionLineNumber(); 661082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek break; 6621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 663082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek case Stmt::CaseStmtClass: { 6641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump os << "Control jumps to 'case "; 6659c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CaseStmt *Case = cast<CaseStmt>(S); 6669c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Expr *LHS = Case->getLHS()->IgnoreParenCasts(); 6671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Determine if it is an enum. 669082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek bool GetRawInt = true; 6701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6719c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) { 672082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek // FIXME: Maybe this should be an assertion. Are there cases 673082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek // were it is not an EnumConstantDecl? 6749c378f705405d37f49795d5e915989de774fe11fTed Kremenek const EnumConstantDecl *D = 67503509aea098772644bf4662dc1c88634818ceeccZhongxing Xu dyn_cast<EnumConstantDecl>(DR->getDecl()); 6761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 677082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek if (D) { 678082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek GetRawInt = false; 679b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer os << *D; 680082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 6815a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek } 6829ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 6839ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman if (GetRawInt) 684a6b8b2c09610b8bc4330e948ece8b940c2386406Richard Smith os << LHS->EvaluateKnownConstInt(PDB.getASTContext()); 6859ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 68600605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os << ":' at line " 687642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << End.asLocation().getExpansionLineNumber(); 688082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek break; 689082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 69061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 6912042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 69200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os.str())); 69361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 694567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek else { 695c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "'Default' branch taken. "; 6961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N); 6972042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 69800605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os.str())); 699567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek } 7001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 70161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 70261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 7031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7042673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::BreakStmtClass: 7052673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::ContinueStmtClass: { 706297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 707297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 70800605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 7092042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 710082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os.str())); 7112673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek break; 7122673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek } 7131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine control-flow for ternary '?'. 71556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 716706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek case Stmt::ConditionalOperatorClass: { 717297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 718297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 7191d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek os << "'?' condition is "; 7201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 721706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()+1) == Dst) 722082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "false"; 723706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek else 724082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "true"; 7251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 72600605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7281d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (const Stmt *S = End.asStmt()) 7291d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 7301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7312042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 732babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek os.str())); 733babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 734babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 7351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine control-flow for short-circuited '&&' and '||'. 737babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek case Stmt::BinaryOperatorClass: { 738babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek if (!PDB.supportsLogicalOpControlFlow()) 739babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 7401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 74103509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const BinaryOperator *B = cast<BinaryOperator>(T); 742babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek std::string sbuf; 743babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek llvm::raw_string_ostream os(sbuf); 744babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek os << "Left side of '"; 7451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7462de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_LAnd) { 747f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "&&" << "' is "; 7481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 749f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 750f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 751220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 7520cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 7530cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 7542042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 755f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os.str())); 7561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 757f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 758f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 759220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 760f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7612042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 762f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os.str())); 7631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 764babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 765babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek else { 7662de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(B->getOpcode() == BO_LOr); 767f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "||" << "' is "; 7681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 769f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 770f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 771220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 772f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7732042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 7741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump os.str())); 775f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 776f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 777f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 778220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 7790cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 7800cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 7812042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 7821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump os.str())); 783f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 784babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 7851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 786706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek break; 787706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek } 7881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::DoStmtClass: { 790706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()) == Dst) { 791297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 792297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 7931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 794c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "Loop condition is true. "; 795d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 7961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 797d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 798d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 7991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8002042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 801082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os.str())); 802082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 803082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek else { 80400605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 8051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 806d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 807d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 8081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8092042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 8103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek "Loop condition is false. Exiting loop")); 8113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 8143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::WhileStmtClass: 8171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::ForStmtClass: { 8183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) { 8193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::string sbuf; 8203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::raw_string_ostream os(sbuf); 8211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek os << "Loop condition is false. "; 8233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 8243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 8253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 8261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8272042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 8283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek os.str())); 8293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 8313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 8323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 8333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 8341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8352042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 8365fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek "Loop condition is true. Entering loop body")); 8373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 8403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::IfStmtClass: { 8433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 8441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 8463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 8471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) 8492042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 8505fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek "Taking false branch")); 8511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else 8522042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 8535fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek "Taking true branch")); 8541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 8563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 860dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (NextNode) { 8618e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add diagnostic pieces from custom visitors. 8628e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 8638e6431adab313e283a992698f6fc7afe62420999Anna Zaks for (BugReport::visitor_iterator I = R->visitor_begin(), 8648e6431adab313e283a992698f6fc7afe62420999Anna Zaks E = R->visitor_end(); I!=E; ++I) { 8658e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) 8662042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 867dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 8688966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 8691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8709c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const PostStmt *PS = dyn_cast<PostStmt>(&P)) { 8713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Scan the region bindings, and see if a "notable" symbol has a new 8723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // lval binding. 8733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek ScanNotableSymbols SNS(N, PS->getStmt(), PDB.getBugReporter(), PD); 8743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PDB.getStateManager().iterBindings(N->getState(), SNS); 8753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 87814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // After constructing the full PathDiagnostic, do a pass over it to compact 87914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // PathDiagnosticPieces that occur within a macro. 88077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager()); 8813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 8823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 8833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 8845fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek// "Extensive" PathDiagnostic generation. 8855fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 8865fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 8875fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenekstatic bool IsControlFlowExpr(const Stmt *S) { 8885fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const Expr *E = dyn_cast<Expr>(S); 8891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8905fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (!E) 8915fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return false; 8921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump E = E->IgnoreParenCasts(); 8941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 89556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (isa<AbstractConditionalOperator>(E)) 8965fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 8971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8985fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) 8995fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 9005fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 9011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 9035fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek} 9045fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 90514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremeneknamespace { 906ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ContextLocation : public PathDiagnosticLocation { 9078f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsDead; 9088f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekpublic: 9098f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation(const PathDiagnosticLocation &L, bool isdead = false) 9108f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek : PathDiagnosticLocation(L), IsDead(isdead) {} 9111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void markDead() { IsDead = true; } 9138f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool isDead() const { return IsDead; } 9148f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek}; 9151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 916ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass EdgeBuilder { 9178f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek std::vector<ContextLocation> CLocs; 9188f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek typedef std::vector<ContextLocation>::iterator iterator; 91914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnostic &PD; 92014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB; 92114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation PrevLoc; 9221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9238f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsConsumedExpr(const PathDiagnosticLocation &L); 9241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 92514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek bool containsLocation(const PathDiagnosticLocation &Container, 92614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee); 9271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 92814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L); 9291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9309650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L, 9319650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek bool firstCharOnly = false) { 9328c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (const Stmt *S = L.asStmt()) { 9339650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek const Stmt *Original = S; 9348c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek while (1) { 9358c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek // Adjust the location for some expressions that are best referenced 9368c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek // by one of their subexpressions. 9379650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek switch (S->getStmtClass()) { 9389650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek default: 9399650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek break; 9409650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ParenExprClass: 941f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne case Stmt::GenericSelectionExprClass: 942f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne S = cast<Expr>(S)->IgnoreParens(); 9439650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 9449650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 94556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 9469650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ConditionalOperatorClass: 94756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall S = cast<AbstractConditionalOperator>(S)->getCond(); 9489650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 9499650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 9509650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ChooseExprClass: 9519650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek S = cast<ChooseExpr>(S)->getCond(); 9529650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 9539650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 9549650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::BinaryOperatorClass: 9559650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek S = cast<BinaryOperator>(S)->getLHS(); 9569650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 9579650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 9589650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek } 9591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9609650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek break; 9618c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 9621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9639650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek if (S != Original) 96459950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek L = PathDiagnosticLocation(S, L.getManager(), PDB.LC); 9658c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 9661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9679650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek if (firstCharOnly) 9681531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks L = PathDiagnosticLocation::createSingleLocation(L); 9699650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek 9708c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek return L; 9718c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 9721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 97314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void popLocation() { 9748f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) { 9755c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // For contexts, we only one the first character as the range. 97607c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek rawAddEdge(cleanUpLocation(CLocs.back(), true)); 9775c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek } 97814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.pop_back(); 97914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 9801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekpublic: 98214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb) 98314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek : PD(pd), PDB(pdb) { 9841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 985a301a6773db085575ac51e3c966858180390c25bTed Kremenek // If the PathDiagnostic already has pieces, add the enclosing statement 986a301a6773db085575ac51e3c966858180390c25bTed Kremenek // of the first piece as a context as well. 987802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek if (!PD.path.empty()) { 988802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek PrevLoc = (*PD.path.begin())->getLocation(); 9891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 99014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = PrevLoc.asStmt()) 991e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 99214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 99314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 99414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 99514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ~EdgeBuilder() { 99614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) popLocation(); 9970cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 998a301a6773db085575ac51e3c966858180390c25bTed Kremenek // Finally, add an initial edge from the start location of the first 999a301a6773db085575ac51e3c966858180390c25bTed Kremenek // statement (if it doesn't already exist). 10000cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin( 100159950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC, 10020cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PDB.getSourceManager()); 10030cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks if (L.isValid()) 10040cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks rawAddEdge(L); 100514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 100614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 10075de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek void flushLocations() { 10085de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek while (!CLocs.empty()) 10095de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek popLocation(); 10105de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek PrevLoc = PathDiagnosticLocation(); 10115de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek } 10125de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 101314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false); 10141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10158bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek void rawAddEdge(PathDiagnosticLocation NewLoc); 10161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 101714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addContext(const Stmt *S); 1018e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek void addExtendedContext(const Stmt *S); 10191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}; 102014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} // end anonymous namespace 102114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 102214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 102314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekPathDiagnosticLocation 102414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekEdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) { 102514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = L.asStmt()) { 102614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (IsControlFlowExpr(S)) 102714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 10281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return PDB.getEnclosingStmtLocation(S); 103014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 10311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 103214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 103314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 103414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 103514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekbool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container, 103614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee) { 103714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 103814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container == Containee) 103914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 10401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 104114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container.asDecl()) 104214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 10431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 104414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = Containee.asStmt()) 104514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *ContainerS = Container.asStmt()) { 104614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (S) { 104714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (S == ContainerS) 104814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 104914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek S = PDB.getParent(S); 105014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 105114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return false; 105214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 105314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 105414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Less accurate: compare using source ranges. 105514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContainerR = Container.asRange(); 105614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContaineeR = Containee.asRange(); 10571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 105814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceManager &SM = PDB.getSourceManager(); 1059402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin()); 1060402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd()); 1061402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin()); 1062402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd()); 10631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1064642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg); 1065642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd); 1066642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg); 1067642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd); 10681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 106914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek assert(ContainerBegLine <= ContainerEndLine); 10701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(ContaineeBegLine <= ContaineeEndLine); 10711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 107214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return (ContainerBegLine <= ContaineeBegLine && 107314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ContainerEndLine >= ContaineeEndLine && 107414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerBegLine != ContaineeBegLine || 1075a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerRBeg) <= 1076a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContaineeRBeg)) && 107714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerEndLine != ContaineeEndLine || 1078a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerREnd) >= 1079a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerREnd))); 108014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 108114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 108214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) { 108314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!PrevLoc.isValid()) { 108414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PrevLoc = NewLoc; 108514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 108614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 10871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10888c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc); 10898c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc); 10901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10918c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (NewLocClean.asLocation() == PrevLocClean.asLocation()) 109214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 10931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 109414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // FIXME: Ignore intra-macro edges for now. 1095402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth if (NewLocClean.asLocation().getExpansionLoc() == 1096402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth PrevLocClean.asLocation().getExpansionLoc()) 109714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 109814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 10992042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean)); 11008c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek PrevLoc = NewLoc; 110114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 110214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 110314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) { 11041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1105a301a6773db085575ac51e3c966858180390c25bTed Kremenek if (!alwaysAdd && NewLoc.asLocation().isMacroID()) 1106a301a6773db085575ac51e3c966858180390c25bTed Kremenek return; 11071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 110814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc); 110914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 111014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 11118f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation &TopContextLoc = CLocs.back(); 11121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 111314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 111414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == CLoc) { 11158f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 11164c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek if (IsConsumedExpr(TopContextLoc) && 11174c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek !IsControlFlowExpr(TopContextLoc.asStmt())) 11188f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek TopContextLoc.markDead(); 11198f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek 112014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 11218f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 112214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 112314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 112414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 112514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 112614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, CLoc)) { 11278f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 112814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 11291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11304c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek if (IsConsumedExpr(CLoc) && !IsControlFlowExpr(CLoc.asStmt())) { 11318f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek CLocs.push_back(ContextLocation(CLoc, true)); 11328f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return; 11338f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 11348f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 11351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 113614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(CLoc); 11371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 113814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 113914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 114014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 114114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 114214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 11431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11445c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // If we reach here, there is no enclosing context. Just add the edge. 11455c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek rawAddEdge(NewLoc); 114614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 114714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 11488f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekbool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) { 11498f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt())) 11508f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X); 11511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11528f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return false; 11538f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek} 11541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1155e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenekvoid EdgeBuilder::addExtendedContext(const Stmt *S) { 1156e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (!S) 1157e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek return; 11581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const Stmt *Parent = PDB.getParent(S); 1160e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek while (Parent) { 1161e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (isa<CompoundStmt>(Parent)) 1162e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek Parent = PDB.getParent(Parent); 1163e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek else 1164e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1165e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1166e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek 1167e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (Parent) { 1168e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek switch (Parent->getStmtClass()) { 1169e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::DoStmtClass: 1170e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 1171e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(Parent); 1172e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek default: 1173e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1174e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1175e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 11761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1177e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(S); 1178e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek} 11791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 118014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addContext(const Stmt *S) { 118114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!S) 118214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 118314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 118459950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.LC); 11851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 118614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 118714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &TopContextLoc = CLocs.back(); 118814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 118914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 119014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == L) 119114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 119214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 119314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, L)) { 119414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 11951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 119614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 119714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 119814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 119914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 120014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 120114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 120214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 120314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 120414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 120514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekstatic void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, 120614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB, 1207c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode *N) { 120814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder EB(PD, PDB); 12090cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks const SourceManager& SM = PDB.getSourceManager(); 121014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 12119c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); 121214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (NextNode) { 121314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek N = NextNode; 121414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek NextNode = GetPredecessorNode(N); 121514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ProgramPoint P = N->getLocation(); 121614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 1217dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek do { 12185de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek if (const CallExit *CE = dyn_cast<CallExit>(&P)) { 12195de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek const StackFrameContext *LCtx = 12205de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek CE->getLocationContext()->getCurrentStackFrame(); 12215de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek PathDiagnosticLocation Loc(LCtx->getCallSite(), 12225de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek PDB.getSourceManager(), 12235de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek LCtx); 12245de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek EB.addEdge(Loc, true); 12255de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek EB.flushLocations(); 12262042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PathDiagnosticCallPiece *C = 12272042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PathDiagnosticCallPiece::construct(N, *CE, SM); 12282042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(C); 12292042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.pushActivePath(&C->path); 12305de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek break; 12315de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek } 123259950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 123359950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek // Note that is important that we update the LocationContext 123459950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek // after looking at CallExits. CallExit basically adds an 123559950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek // edge in the *caller*, so we don't want to update the LocationContext 123659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek // too soon. 123759950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC = N->getLocationContext(); 123859950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 12392042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // Pop the call hierarchy if we are done walking the contents 12402042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // of a function call. 12412042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek if (const CallEnter *CE = dyn_cast<CallEnter>(&P)) { 12422042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.popActivePath(); 12432042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // The current active path should never be empty. Either we 12442042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // just added a bunch of stuff to the top-level path, or 12452042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // we have a previous CallExit. If the front of the active 12462042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // path is not a PathDiagnosticCallPiece, it means that the 12472042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // path terminated within a function call. We must then take the 12482042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // current contents of the active path and place it within 12492042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // a new PathDiagnosticCallPiece. 12502042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek assert(!PD.getActivePath().empty()); 12512042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PathDiagnosticCallPiece *C = 12522042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek dyn_cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 12532042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek if (!C) 12542042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek C = PathDiagnosticCallPiece::construct(PD.getActivePath()); 12552042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek C->setCallee(*CE, SM); 125659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek EB.flushLocations(); 12572042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek EB.addContext(CE->getCallExpr()); 12582042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek break; 12592042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek } 12605de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 1261dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Block edges. 12625de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 1263dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek const CFGBlock &Blk = *BE->getSrc(); 1264dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek const Stmt *Term = Blk.getTerminator(); 12651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1266dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Are we jumping to the head of a loop? Add a special diagnostic. 1267ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (const Stmt *Loop = BE->getDst()->getLoopTarget()) { 126859950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PathDiagnosticLocation L(Loop, SM, PDB.LC); 1269ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const CompoundStmt *CS = NULL; 12701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1271ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (!Term) { 1272ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) 1273ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek CS = dyn_cast<CompoundStmt>(FS->getBody()); 1274ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) 12751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CS = dyn_cast<CompoundStmt>(WS->getBody()); 1276ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek } 12771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1278dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek PathDiagnosticEventPiece *p = 1279dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek new PathDiagnosticEventPiece(L, 128007c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek "Looping back to the head of the loop"); 12811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1282dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek EB.addEdge(p->getLocation(), true); 12832042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 12841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1285ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (CS) { 12860cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation BL = 12870cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createEndBrace(CS, SM); 128807c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek EB.addEdge(BL); 1289dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 12908bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 12911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1292ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (Term) 1293ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek EB.addContext(Term); 12941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1295dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 12968bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 129714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 12981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) { 12993c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (const CFGStmt *S = BE->getFirstElement().getAs<CFGStmt>()) { 13003c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const Stmt *stmt = S->getStmt(); 13013c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (IsControlFlowExpr(stmt)) { 1302b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu // Add the proper context for '&&', '||', and '?'. 13033c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addContext(stmt); 1304b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 1305b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu else 13063c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt()); 1307dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 1308b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu 1309dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 1310dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 13115de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 13125de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 1313dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } while (0); 13141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1315dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (!NextNode) 131614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek continue; 13171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13188e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add pieces from custom visitors. 13198e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 13208e6431adab313e283a992698f6fc7afe62420999Anna Zaks for (BugReport::visitor_iterator I = R->visitor_begin(), 13218e6431adab313e283a992698f6fc7afe62420999Anna Zaks E = R->visitor_end(); I!=E; ++I) { 13228e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 13238966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek const PathDiagnosticLocation &Loc = p->getLocation(); 13248966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek EB.addEdge(Loc, true); 13252042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 13268966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek if (const Stmt *S = Loc.asStmt()) 13271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 13288966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 13291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 133014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 133114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 133214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 13335fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 13343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugType and subclasses. 13353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 1336404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios KyrtzidisBugType::~BugType() { } 1337404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 13383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugType::FlushReports(BugReporter &BR) {} 13393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 134099ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BuiltinBug::anchor() {} 134199ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 13423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 13433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReport and subclasses. 13443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 1345e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 134699ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BugReport::NodeResolver::anchor() {} 134799ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 13488e6431adab313e283a992698f6fc7afe62420999Anna Zaksvoid BugReport::addVisitor(BugReporterVisitor* visitor) { 13498e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (!visitor) 13508e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 13518e6431adab313e283a992698f6fc7afe62420999Anna Zaks 13528e6431adab313e283a992698f6fc7afe62420999Anna Zaks llvm::FoldingSetNodeID ID; 13538e6431adab313e283a992698f6fc7afe62420999Anna Zaks visitor->Profile(ID); 13548e6431adab313e283a992698f6fc7afe62420999Anna Zaks void *InsertPos; 13558e6431adab313e283a992698f6fc7afe62420999Anna Zaks 13568e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) { 13578e6431adab313e283a992698f6fc7afe62420999Anna Zaks delete visitor; 13588e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 13598e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 13608e6431adab313e283a992698f6fc7afe62420999Anna Zaks 13618e6431adab313e283a992698f6fc7afe62420999Anna Zaks CallbacksSet.InsertNode(visitor, InsertPos); 13628e6431adab313e283a992698f6fc7afe62420999Anna Zaks Callbacks = F.add(visitor, Callbacks); 13638e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 13648e6431adab313e283a992698f6fc7afe62420999Anna Zaks 13658e6431adab313e283a992698f6fc7afe62420999Anna ZaksBugReport::~BugReport() { 13668e6431adab313e283a992698f6fc7afe62420999Anna Zaks for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) { 1367dc757b049796949e4b11646445a6598f0bdabd7aAnna Zaks delete *I; 13688e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 13698e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 1370e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 1371e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaksvoid BugReport::Profile(llvm::FoldingSetNodeID& hash) const { 1372e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddPointer(&BT); 1373e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddString(Description); 1374ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks if (UniqueingLocation.isValid()) { 1375ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks UniqueingLocation.Profile(hash); 1376ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks } else if (Location.isValid()) { 1377590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks Location.Profile(hash); 1378590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } else { 1379590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(ErrorNode); 1380590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode)); 1381590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } 1382e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 1383e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks for (SmallVectorImpl<SourceRange>::const_iterator I = 1384e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks Ranges.begin(), E = Ranges.end(); I != E; ++I) { 1385e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks const SourceRange range = *I; 1386e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!range.isValid()) 1387e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks continue; 1388e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getBegin().getRawEncoding()); 1389e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getEnd().getRawEncoding()); 1390e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 1391e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks} 13923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13939c378f705405d37f49795d5e915989de774fe11fTed Kremenekconst Stmt *BugReport::getStmt() const { 1394e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!ErrorNode) 1395e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return 0; 1396e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 1397212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care ProgramPoint ProgP = ErrorNode->getLocation(); 13985f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek const Stmt *S = NULL; 13991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14009c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (BlockEntrance *BE = dyn_cast<BlockEntrance>(&ProgP)) { 1401fafd3834754d2093e0ad7a1c005860fd527ecb7fZhongxing Xu CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit(); 140250d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu if (BE->getBlock() == &Exit) 1403212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care S = GetPreviousStmt(ErrorNode); 14043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 14055f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (!S) 14061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump S = GetStmt(ProgP); 14071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return S; 14093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 14103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1411640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidisstd::pair<BugReport::ranges_iterator, BugReport::ranges_iterator> 1412e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna ZaksBugReport::getRanges() { 1413e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // If no custom ranges, add the range of the statement corresponding to 1414e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // the error node. 1415e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (Ranges.empty()) { 1416e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (const Expr *E = dyn_cast_or_null<Expr>(getStmt())) 1417e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks addRange(E->getSourceRange()); 1418e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks else 1419e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 1420e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 1421e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 142214924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks // User-specified absence of range info. 142314924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks if (Ranges.size() == 1 && !Ranges.begin()->isValid()) 142414924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 142514924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks 1426e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(Ranges.begin(), Ranges.end()); 14273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 14283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1429590dd8e0959d8df5621827768987c4792b74fc06Anna ZaksPathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const { 1430b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks if (ErrorNode) { 1431590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(!Location.isValid() && 1432b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks "Either Location or ErrorNode should be specified but not both."); 1433b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks 14349c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const Stmt *S = GetCurrentOrPreviousStmt(ErrorNode)) { 1435590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks const LocationContext *LC = ErrorNode->getLocationContext(); 1436590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks 14373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // For member expressions, return the location of the '.' or '->'. 14385b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) 1439590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createMemberLoc(ME, SM); 14405b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek // For binary operators, return the location of the operator. 14415b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) 1442590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createOperatorLoc(B, SM); 14433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1444590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createBegin(S, SM, LC); 14453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1446b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } else { 1447b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks assert(Location.isValid()); 1448b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks return Location; 1449b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } 1450b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks 1451590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation(); 14523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 14533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 14543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 14553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReporter and subclasses. 14563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 14573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 14583106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReportEquivClass::~BugReportEquivClass() { 14598966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek for (iterator I=begin(), E=end(); I!=E; ++I) delete *I; 14603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 14613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1462a2f4ec0df645fc249d2945beef9653f03b175417Zhongxing XuGRBugReporter::~GRBugReporter() { } 14633106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReporterData::~BugReporterData() {} 14643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 146538b02b912e1a55c912f603c4369431264d36a381Zhongxing XuExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); } 14663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 146718c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekProgramStateManager& 14683106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekGRBugReporter::getStateManager() { return Eng.getStateManager(); } 14693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 14703b030a28cda2b953758507769c1d436bec5ec45eAnna ZaksBugReporter::~BugReporter() { 14713b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks FlushReports(); 14723b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks 14733b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks // Free the bug reports we are tracking. 14743b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks typedef std::vector<BugReportEquivClass *> ContTy; 14753b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end(); 14763b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks I != E; ++I) { 14773b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks delete *I; 14783b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks } 14793b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks} 14803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 14813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugReporter::FlushReports() { 14823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (BugTypes.isEmpty()) 14833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return; 14843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 14853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // First flush the warnings for each BugType. This may end up creating new 1486404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // warnings and new BugTypes. 1487404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: Only NSErrorChecker needs BugType's FlushReports. 1488404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // Turn NSErrorChecker into a proper checker and remove this. 14895f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<const BugType*, 16> bugTypes; 14903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) 1491404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis bugTypes.push_back(*I); 14925f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVector<const BugType*, 16>::iterator 1493404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I) 14943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const_cast<BugType*>(*I)->FlushReports(*this); 14953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1496404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis typedef llvm::FoldingSet<BugReportEquivClass> SetTy; 1497404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis for (SetTy::iterator EI=EQClasses.begin(), EE=EQClasses.end(); EI!=EE;++EI){ 1498404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugReportEquivClass& EQ = *EI; 1499404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis FlushReport(EQ); 15003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1502404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // BugReporter owns and deletes only BugTypes created implicitly through 1503404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // EmitBasicReport. 1504404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: There are leaks from checkers that assume that the BugTypes they 1505404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // create will be destroyed by the BugReporter. 1506404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis for (llvm::StringMap<BugType*>::iterator 1507404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I) 1508404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis delete I->second; 1509404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 15103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Remove all references to the BugType objects. 15113baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.getEmptySet(); 15123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 15133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 15143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 15153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnostics generation. 15163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 15173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 151838b02b912e1a55c912f603c4369431264d36a381Zhongxing Xustatic std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, 1519c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::pair<ExplodedNode*, unsigned> > 152038b02b912e1a55c912f603c4369431264d36a381Zhongxing XuMakeReportGraph(const ExplodedGraph* G, 15215f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<const ExplodedNode*> &nodes) { 15221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the trimmed graph. It will contain the shortest paths from the 15241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // error nodes to the root. In the new graph we should only have one 15253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // error node unless there are two or more error nodes with the same minimum 15263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // path length. 152738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu ExplodedGraph* GTrim; 1528c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu InterExplodedGraphMap* NMap; 15293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 15303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*, const void*> InverseMap; 153140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek llvm::tie(GTrim, NMap) = G->Trim(nodes.data(), nodes.data() + nodes.size(), 153240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek &InverseMap); 15331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create owning pointers for GTrim and NMap just to ensure that they are 15353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // released when this function exists. 15366f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<ExplodedGraph> AutoReleaseGTrim(GTrim); 15376f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<InterExplodedGraphMap> AutoReleaseNMap(NMap); 15381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the (first) error node in the trimmed graph. We just need to consult 15403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // the node map (NMap) which maps from nodes in the original graph to nodes 15413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // in the new graph. 1542938332c657390d1e782e0adc03b092993edae962Ted Kremenek 1543c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::queue<const ExplodedNode*> WS; 154438b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu typedef llvm::DenseMap<const ExplodedNode*, unsigned> IndexMapTy; 1545938332c657390d1e782e0adc03b092993edae962Ted Kremenek IndexMapTy IndexMap; 15463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 154740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek for (unsigned nodeIndex = 0 ; nodeIndex < nodes.size(); ++nodeIndex) { 154840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek const ExplodedNode *originalNode = nodes[nodeIndex]; 154940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (const ExplodedNode *N = NMap->getMappedNode(originalNode)) { 1550938332c657390d1e782e0adc03b092993edae962Ted Kremenek WS.push(N); 155140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek IndexMap[originalNode] = nodeIndex; 15523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 155340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 15541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1555938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(!WS.empty() && "No error node found in the trimmed graph."); 15563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 15573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create a new (third!) graph with a single path. This is the graph 15583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // that will be returned to the caller. 1559c77a55126fcad66fb086f8e100a494caa2496a2dZhongxing Xu ExplodedGraph *GNew = new ExplodedGraph(); 15601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Sometimes the trimmed graph can contain a cycle. Perform a reverse BFS 15623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // to the root node, and then construct a new graph that contains only 15633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // a single path. 15643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*,unsigned> Visited; 15651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek unsigned cnt = 0; 15679c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *Root = 0; 15681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!WS.empty()) { 15709c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *Node = WS.front(); 15713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek WS.pop(); 15721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Visited.find(Node) != Visited.end()) 15743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 15751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Visited[Node] = cnt++; 15771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Node->pred_empty()) { 15793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Root = Node; 15803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 15813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1583c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu for (ExplodedNode::const_pred_iterator I=Node->pred_begin(), 15843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek E=Node->pred_end(); I!=E; ++I) 15853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek WS.push(*I); 15863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1588938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(Root); 15891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now walk from the root down the BFS path, always taking the successor 15913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // with the lowest number. 15921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ExplodedNode *Last = 0, *First = 0; 15933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NodeBackMap *BM = new NodeBackMap(); 1594938332c657390d1e782e0adc03b092993edae962Ted Kremenek unsigned NodeIndex = 0; 15951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1596c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu for ( const ExplodedNode *N = Root ;;) { 15973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Lookup the number associated with the current node. 15983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*,unsigned>::iterator I = Visited.find(N); 1599938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(I != Visited.end()); 16001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the equivalent node in the new graph with the same state 16023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // and location. 16039c378f705405d37f49795d5e915989de774fe11fTed Kremenek ExplodedNode *NewN = GNew->getNode(N->getLocation(), N->getState()); 16041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Store the mapping to the original node. 16063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*, const void*>::iterator IMitr=InverseMap.find(N); 16073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(IMitr != InverseMap.end() && "No mapping to original node."); 1608c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu (*BM)[NewN] = (const ExplodedNode*) IMitr->second; 16091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Link up the new node with the previous node. 16113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Last) 16125fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek NewN->addPredecessor(Last, *GNew); 16131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Last = NewN; 16151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Are we at the final node? 1617938332c657390d1e782e0adc03b092993edae962Ted Kremenek IndexMapTy::iterator IMI = 1618c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu IndexMap.find((const ExplodedNode*)(IMitr->second)); 1619938332c657390d1e782e0adc03b092993edae962Ted Kremenek if (IMI != IndexMap.end()) { 16203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek First = NewN; 1621938332c657390d1e782e0adc03b092993edae962Ted Kremenek NodeIndex = IMI->second; 16223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 16233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 16241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the next successor node. We choose the node that is marked 16263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // with the lowest DFS number. 1627c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::const_succ_iterator SI = N->succ_begin(); 1628c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::const_succ_iterator SE = N->succ_end(); 16293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek N = 0; 16301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (unsigned MinVal = 0; SI != SE; ++SI) { 16321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek I = Visited.find(*SI); 16341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (I == Visited.end()) 16363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 16371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!N || I->second < MinVal) { 16393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek N = *SI; 16403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MinVal = I->second; 16413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 16423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 16431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1644938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(N); 16453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 16461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1647938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(First); 1648938332c657390d1e782e0adc03b092993edae962Ted Kremenek 16493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return std::make_pair(std::make_pair(GNew, BM), 16503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::make_pair(First, NodeIndex)); 16513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 1652d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 16533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object 16543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// and collapses PathDiagosticPieces that are expanded by macros. 165577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) { 16562042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek typedef std::vector<std::pair<IntrusiveRefCntPtr<PathDiagnosticMacroPiece>, 16572042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek SourceLocation> > MacroStackTy; 16581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1659c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith typedef std::vector<IntrusiveRefCntPtr<PathDiagnosticPiece> > 16603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy; 16611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStackTy MacroStack; 16633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy Pieces; 16641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 166577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek for (PathPieces::const_iterator I = path.begin(), E = path.end(); 16662042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek I!=E; ++I) { 166777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 166877d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek PathDiagnosticPiece *piece = I->getPtr(); 166977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 167077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek // Recursively compact calls. 167177d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek if (PathDiagnosticCallPiece *call=dyn_cast<PathDiagnosticCallPiece>(piece)){ 167277d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek CompactPathDiagnostic(call->path, SM); 167377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek } 167477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 16753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Get the location of the PathDiagnosticPiece. 167677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek const FullSourceLoc Loc = piece->getLocation().asLocation(); 16771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine the instantiation location, which is the location we group 16793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // related PathDiagnosticPieces. 16801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation InstantiationLoc = Loc.isMacroID() ? 1681402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 16823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 16831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Loc.isFileID()) { 16853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.clear(); 168677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek Pieces.push_back(piece); 16873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 16883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1689706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek 16903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(Loc.isMacroID()); 16911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Is the PathDiagnosticPiece within the same macro group? 16933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) { 169477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek MacroStack.back().first->subPieces.push_back(piece); 16953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 16963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1697d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 16983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // We aren't in the same group. Are we descending into a new macro 16993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // or are part of an old one? 1700c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith IntrusiveRefCntPtr<PathDiagnosticMacroPiece> MacroGroup; 1701d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 17023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ? 1703402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 17043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 17051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Walk the entire macro stack. 17073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!MacroStack.empty()) { 17083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (InstantiationLoc == MacroStack.back().second) { 17093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 17103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 17113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 17121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (ParentInstantiationLoc == MacroStack.back().second) { 17143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 17153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 171661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 17171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.pop_back(); 17196837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek } 17201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) { 17223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create a new macro group and add it to the stack. 1723590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticMacroPiece *NewGroup = 1724590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks new PathDiagnosticMacroPiece( 172577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek PathDiagnosticLocation::createSingleLocation(piece->getLocation())); 17265a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek 17273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (MacroGroup) 1728802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek MacroGroup->subPieces.push_back(NewGroup); 17293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 17303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(InstantiationLoc.isFileID()); 17313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Pieces.push_back(NewGroup); 17323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 17331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = NewGroup; 17353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc)); 17367dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 17373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 17383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Finally, add the PathDiagnosticPiece to the group. 173977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek MacroGroup->subPieces.push_back(piece); 17403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 17411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now take the pieces and construct a new PathDiagnostic. 174377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek path.clear(); 17441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 174577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) 174677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek path.push_back(*I); 174761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 174861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 17493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, 17505f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<BugReport *> &bugReports) { 17511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 175240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek assert(!bugReports.empty()); 17535f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<const ExplodedNode *, 10> errorNodes; 17545f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVectorImpl<BugReport*>::iterator I = bugReports.begin(), 175540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek E = bugReports.end(); I != E; ++I) { 175640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek errorNodes.push_back((*I)->getErrorNode()); 175740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 17581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Construct a new graph that contains only a single path from the error 17601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // node to a root. 176138b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu const std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, 1762c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::pair<ExplodedNode*, unsigned> >& 176340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek GPair = MakeReportGraph(&getGraph(), errorNodes); 17641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the BugReport with the original location. 176640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek assert(GPair.second.second < bugReports.size()); 176740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *R = bugReports[GPair.second.second]; 17683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(R && "No original report found for sliced graph."); 17691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17706f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<ExplodedGraph> ReportGraph(GPair.first.first); 17716f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<NodeBackMap> BackMap(GPair.first.second); 1772c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode *N = GPair.second.first; 17731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Start building the path diagnostic... 1775ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticBuilder PDB(*this, R, BackMap.get(), 1776ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie getPathDiagnosticConsumer()); 17771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17788e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Register additional node visitors. 177950bbc165b063155cc23c360deb7b865502e068e2Anna Zaks R->addVisitor(new NilReceiverBRVisitor()); 178050bbc165b063155cc23c360deb7b865502e068e2Anna Zaks R->addVisitor(new ConditionBRVisitor()); 17811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 178223f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks // Generate the very last diagnostic piece - the piece is visible before 178323f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks // the trace is expanded. 178423f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks PathDiagnosticPiece *LastPiece = 0; 178523f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks for (BugReport::visitor_iterator I = R->visitor_begin(), 178623f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks E = R->visitor_end(); I!=E; ++I) { 178723f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) { 178823f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks assert (!LastPiece && 178923f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks "There can only be one final piece in a diagnostic."); 179023f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks LastPiece = Piece; 179123f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks } 179223f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks } 179323f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks if (!LastPiece) 179423f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R); 179523f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks if (LastPiece) 17962042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_back(LastPiece); 179723f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks else 179823f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks return; 179923f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks 18003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek switch (PDB.getGenerationScheme()) { 1801ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie case PathDiagnosticConsumer::Extensive: 18028966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek GenerateExtensivePathDiagnostic(PD, PDB, N); 18035fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek break; 1804ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie case PathDiagnosticConsumer::Minimal: 18053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek GenerateMinimalPathDiagnostic(PD, PDB, N); 18063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 18073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1808c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 1809c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek // Finally, prune the diagnostic path of uninteresting stuff. 1810c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek bool hasSomethingInteresting = RemoveUneededCalls(PD.getMutablePieces()); 1811c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek assert(hasSomethingInteresting); 1812c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek (void) hasSomethingInteresting; 18133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 18141aa44c7c9198796085b77c6bdd7c90030845a688Ted Kremenek 1815cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::Register(BugType *BT) { 18163baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.add(BugTypes, BT); 181776d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek} 181876d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek 18191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid BugReporter::EmitReport(BugReport* R) { 1820cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // Compute the bug report's hash to determine its equivalence class. 1821cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek llvm::FoldingSetNodeID ID; 1822cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek R->Profile(ID); 18231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Lookup the equivance class. If there isn't one, create it. 1825cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek BugType& BT = R->getBugType(); 1826cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek Register(&BT); 1827cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek void *InsertPos; 1828404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos); 18291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1830cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek if (!EQ) { 1831cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ = new BugReportEquivClass(R); 1832404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis EQClasses.InsertNode(EQ, InsertPos); 18333b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks EQClassesVector.push_back(EQ); 1834cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek } 1835cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek else 1836cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ->AddReport(R); 183761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 183861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 183906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 184006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 184106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek// Emitting reports in equivalence classes. 184206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 184306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 184406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremeneknamespace { 1845ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamstruct FRIEC_WLItem { 184606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *N; 184706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek ExplodedNode::const_succ_iterator I, E; 184806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 184906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek FRIEC_WLItem(const ExplodedNode *n) 185006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek : N(n), I(N->succ_begin()), E(N->succ_end()) {} 185106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek}; 185206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek} 185306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 185461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenekstatic BugReport * 185561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted KremenekFindReportInEquivalenceClass(BugReportEquivClass& EQ, 18565f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<BugReport*> &bugReports) { 185761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 185806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end(); 185906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(I != E); 186006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek BugReport *R = *I; 186106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek BugType& BT = R->getBugType(); 186261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 186340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // If we don't need to suppress any of the nodes because they are 186440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // post-dominated by a sink, simply add all the nodes in the equivalence class 186540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // to 'Nodes'. Any of the reports will serve as a "representative" report. 186661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!BT.isSuppressOnSink()) { 186761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) { 18689c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N = I->getErrorNode(); 186961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (N) { 187061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek R = *I; 187140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek bugReports.push_back(R); 187261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 187361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 187406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek return R; 187561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 187661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 187706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // For bug reports that should be suppressed when all paths are post-dominated 187806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // by a sink node, iterate through the reports in the equivalence class 187906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // until we find one that isn't post-dominated (if one exists). We use a 188006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // DFS traversal of the ExplodedGraph to find a non-sink node. We could write 188106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // this as a recursive function, but we don't want to risk blowing out the 188206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // stack for very long paths. 188340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = 0; 188461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 188506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; I != E; ++I) { 188606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek R = *I; 188740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek const ExplodedNode *errorNode = R->getErrorNode(); 188806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 188940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!errorNode) 189006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 189140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->isSink()) { 1892b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable( 189306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek "BugType::isSuppressSink() should not be 'true' for sink end nodes"); 189406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 189561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // No successors? By definition this nodes isn't post-dominated by a sink. 189640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->succ_empty()) { 189740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek bugReports.push_back(R); 189840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 189940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek exampleReport = R; 190061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek continue; 190161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 190261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 190306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // At this point we know that 'N' is not a sink and it has at least one 190406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // successor. Use a DFS worklist to find a non-sink end-of-path node. 190506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek typedef FRIEC_WLItem WLItem; 19065f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<WLItem, 10> DFSWorkList; 190706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek llvm::DenseMap<const ExplodedNode *, unsigned> Visited; 190806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 190906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek DFSWorkList WL; 191040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek WL.push_back(errorNode); 191140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek Visited[errorNode] = 1; 191206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 191306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek while (!WL.empty()) { 191406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WLItem &WI = WL.back(); 191506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(!WI.N->succ_empty()); 191606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 191706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; WI.I != WI.E; ++WI.I) { 191806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *Succ = *WI.I; 191906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // End-of-path node? 192006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (Succ->succ_empty()) { 192161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // If we found an end-of-path node that is not a sink. 192261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!Succ->isSink()) { 192340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek bugReports.push_back(R); 192440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 192540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek exampleReport = R; 192661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek WL.clear(); 192761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek break; 192861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 192906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Found a sink? Continue on to the next successor. 193006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 193106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 193206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Mark the successor as visited. If it hasn't been explored, 193306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // enqueue it to the DFS worklist. 193406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek unsigned &mark = Visited[Succ]; 193506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (!mark) { 193606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek mark = 1; 193706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.push_back(Succ); 193806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek break; 193906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 194006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 194161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 194261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // The worklist may have been cleared at this point. First 194361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // check if it is empty before checking the last item. 194461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!WL.empty() && &WL.back() == &WI) 194506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.pop_back(); 194606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 194706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 194806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 194961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // ExampleReport will be NULL if all the nodes in the equivalence class 195061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // were post-dominated by sinks. 195140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek return exampleReport; 195261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek} 1953e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1954e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek//===----------------------------------------------------------------------===// 1955e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek// DiagnosticCache. This is a hack to cache analyzer diagnostics. It 1956e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek// uses global state, which eventually should go elsewhere. 1957e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek//===----------------------------------------------------------------------===// 1958e0a58073b76fc016325a35152533b8468df2bf4aTed Kremeneknamespace { 1959ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass DiagCacheItem : public llvm::FoldingSetNode { 1960e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek llvm::FoldingSetNodeID ID; 1961e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenekpublic: 1962e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek DiagCacheItem(BugReport *R, PathDiagnostic *PD) { 19634522e2a9e7fa0313e8e5a388d8f0ab66feccc6afAnna Zaks R->Profile(ID); 19644522e2a9e7fa0313e8e5a388d8f0ab66feccc6afAnna Zaks PD->Profile(ID); 1965e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek } 1966e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1967e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek void Profile(llvm::FoldingSetNodeID &id) { 1968e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek id = ID; 1969e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek } 1970e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1971e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek llvm::FoldingSetNodeID &getID() { return ID; } 1972e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek}; 1973e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek} 1974e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1975e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenekstatic bool IsCachedDiagnostic(BugReport *R, PathDiagnostic *PD) { 1976e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek // FIXME: Eventually this diagnostic cache should reside in something 1977e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek // like AnalysisManager instead of being a static variable. This is 1978e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek // really unsafe in the long term. 1979e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek typedef llvm::FoldingSet<DiagCacheItem> DiagnosticCache; 1980e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek static DiagnosticCache DC; 1981e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1982e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek void *InsertPos; 1983e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek DiagCacheItem *Item = new DiagCacheItem(R, PD); 1984e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1985e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek if (DC.FindNodeOrInsertPos(Item->getID(), InsertPos)) { 1986e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek delete Item; 1987e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek return true; 1988e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek } 1989e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1990e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek DC.InsertNode(Item, InsertPos); 1991e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek return false; 1992e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek} 1993e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1994cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::FlushReport(BugReportEquivClass& EQ) { 19955f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BugReport*, 10> bugReports; 199640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports); 199740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 199806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek return; 199906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 2000ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer* PD = getPathDiagnosticConsumer(); 20011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2002cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // FIXME: Make sure we use the 'R' for the path that was actually used. 20031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Probably doesn't make a difference in practice. 200440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugType& BT = exampleReport->getBugType(); 20051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20066f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<PathDiagnostic> 200740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek D(new PathDiagnostic(exampleReport->getBugType().getName(), 2008da0e8429a3598acfdd0ecf15135d432e4dd3517cTed Kremenek !PD || PD->useVerboseDescription() 200940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek ? exampleReport->getDescription() 201040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek : exampleReport->getShortDescription(), 2011d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek BT.getCategory())); 2012d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek 201340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!bugReports.empty()) 201440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek GeneratePathDiagnostic(*D.get(), bugReports); 20151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 201640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (IsCachedDiagnostic(exampleReport, D.get())) 2017e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek return; 2018e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 2019072192bcbb05a0fee7ec3061750b27e8d2004952Ted Kremenek // Get the meta data. 20207f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks const BugReport::ExtraTextList &Meta = 20217f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks exampleReport->getExtraText(); 20227f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks for (BugReport::ExtraTextList::const_iterator i = Meta.begin(), 20237f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks e = Meta.end(); i != e; ++i) { 20247f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks D->addMeta(*i); 20257f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks } 202675840e1501563fe7c3dcb5600b75965ba1fe1bc4Ted Kremenek 20273148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek // Emit a summary diagnostic to the regular Diagnostics engine. 2028640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis BugReport::ranges_iterator Beg, End; 2029640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis llvm::tie(Beg, End) = exampleReport->getRanges(); 2030d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &Diag = getDiagnostic(); 2031c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek 2032c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek // Search the description for '%', as that will be interpretted as a 2033c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek // format character by FormatDiagnostics. 20345f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef desc = exampleReport->getShortDescription(); 2035c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek unsigned ErrorDiag; 2036c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek { 2037f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<512> TmpStr; 2038c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek llvm::raw_svector_ostream Out(TmpStr); 20395f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I) 2040c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek if (*I == '%') 2041c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek Out << "%%"; 2042c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek else 2043c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek Out << *I; 2044c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek 2045c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek Out.flush(); 2046d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie ErrorDiag = Diag.getCustomDiagID(DiagnosticsEngine::Warning, TmpStr); 2047c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek } 20480a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner 2049b6b7e7bff3101062521de6e79533a3c25e2195d9Argyrios Kyrtzidis { 2050590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks DiagnosticBuilder diagBuilder = Diag.Report( 2051590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks exampleReport->getLocation(getSourceManager()).asLocation(), ErrorDiag); 2052640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis for (BugReport::ranges_iterator I = Beg; I != End; ++I) 2053b6b7e7bff3101062521de6e79533a3c25e2195d9Argyrios Kyrtzidis diagBuilder << *I; 20542f0e89ea96292d2974eb1a7dddc0e9870aa86bb7Ted Kremenek } 20553148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek 2056ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie // Emit a full diagnostic for the path if we have a PathDiagnosticConsumer. 20573148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek if (!PD) 20583148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek return; 20591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2060802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek if (D->path.empty()) { 2061590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticPiece *piece = new PathDiagnosticEventPiece( 2062590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks exampleReport->getLocation(getSourceManager()), 2063590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks exampleReport->getDescription()); 20641fbfd5b9b8b82aea084773b76dd1ec6796a7000cTed Kremenek 20653148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek for ( ; Beg != End; ++Beg) piece->addRange(*Beg); 20662042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek D->getActivePath().push_back(piece); 20673148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek } 20681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20693148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek PD->HandlePathDiagnostic(D.take()); 207061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 207157202071e477530e9348bc76671ee369b2399b92Ted Kremenek 20725f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid BugReporter::EmitBasicReport(StringRef name, StringRef str, 2073590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation Loc, 20748c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek SourceRange* RBeg, unsigned NumRanges) { 20758c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek EmitBasicReport(name, "", str, Loc, RBeg, NumRanges); 20768c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek} 2077cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 20785f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid BugReporter::EmitBasicReport(StringRef name, 20795f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category, 2080590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks StringRef str, PathDiagnosticLocation Loc, 20818c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek SourceRange* RBeg, unsigned NumRanges) { 20821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2083404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // 'BT' is owned by BugReporter. 2084404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = getBugTypeForName(name, category); 2085590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks BugReport *R = new BugReport(*BT, str, Loc); 2086cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg); 2087cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EmitReport(R); 2088cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek} 2089404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 20905f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerBugType *BugReporter::getBugTypeForName(StringRef name, 20915f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category) { 2092f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<136> fullDesc; 2093404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::raw_svector_ostream(fullDesc) << name << ":" << category; 2094404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::StringMapEntry<BugType *> & 2095404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry = StrBugTypes.GetOrCreateValue(fullDesc); 2096404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = entry.getValue(); 2097404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis if (!BT) { 2098404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BT = new BugType(name, category); 2099404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry.setValue(BT); 2100404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis } 2101404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis return BT; 2102404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis} 2103