BugReporter.cpp revision 0b3ade86a1c60cf0c7b56aa238aff458eb7f5974
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. 15176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (event->isPrunable()) 15276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek continue; 15376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek containsSomethingInteresting = true; 154725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 155725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 156725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::ControlFlow: 157725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 158c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek } 159c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 160c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek pieces.push_back(piece); 161c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek } 162c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 163c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek return containsSomethingInteresting; 164c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek} 165c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 166c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek//===----------------------------------------------------------------------===// 1673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnosticBuilder and its associated routines and helper objects. 168b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 169b479dadea93b93d3f0a335c3518b703f140b3f50Ted Kremenek 170c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xutypedef llvm::DenseMap<const ExplodedNode*, 171c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuconst ExplodedNode*> NodeBackMap; 1727dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek 173babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremeneknamespace { 174ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NodeMapClosure : public BugReport::NodeResolver { 1757dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeBackMap& M; 1767dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenekpublic: 1777dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeMapClosure(NodeBackMap *m) : M(*m) {} 1787dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek ~NodeMapClosure() {} 1791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1809c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *getOriginalNode(const ExplodedNode *N) { 1817dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeBackMap::iterator I = M.find(N); 1827dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek return I == M.end() ? 0 : I->second; 1837dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 1847dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek}; 1851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 186ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass PathDiagnosticBuilder : public BugReporterContext { 1877dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek BugReport *R; 188ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *PDC; 1896f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<ParentMap> PM; 1907dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeMapClosure NMC; 1911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic: 19259950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek const LocationContext *LC; 19359950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 1948966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek PathDiagnosticBuilder(GRBugReporter &br, 1951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump BugReport *r, NodeBackMap *Backmap, 196ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *pdc) 1978966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek : BugReporterContext(br), 19859950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek R(r), PDC(pdc), NMC(Backmap), LC(r->getErrorNode()->getLocationContext()) 19959950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek {} 2001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2019c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N); 2021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2039c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os, 2049c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N); 2051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2068e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *getBugReport() { return R; } 2078e6431adab313e283a992698f6fc7afe62420999Anna Zaks 208212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); } 20959950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 21059950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek ParentMap& getParentMap() { return LC->getParentMap(); } 2111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 212c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek const Stmt *getParent(const Stmt *S) { 213c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek return getParentMap().getParent(S); 214c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek } 2151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2168966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek virtual NodeMapClosure& getNodeResolver() { return NMC; } 2177297134f128423fce2e88f92421ed135bded7d4eDouglas Gregor 218d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S); 2191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 220ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const { 221ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive; 2227dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 2237dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek 224babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek bool supportsLogicalOpControlFlow() const { 225babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek return PDC ? PDC->supportsLogicalOpControlFlow() : true; 2261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 227babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek}; 228babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek} // end anonymous namespace 229babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 23000605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 2319c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) { 2325f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetNextStmt(N)) 23359950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek return PathDiagnosticLocation(S, getSourceManager(), LC); 23400605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek 2350cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return PathDiagnosticLocation::createDeclEnd(N->getLocationContext(), 2360cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks getSourceManager()); 237082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek} 2381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 23900605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 2409c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os, 2419c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N) { 242babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 243143ca222583a4a355fdc89af852deef287499300Ted Kremenek // Slow, but probably doesn't matter. 244b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek if (os.str().empty()) 245b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << ' '; 2461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 24700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek const PathDiagnosticLocation &Loc = ExecutionContinues(N); 2481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 24900605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek if (Loc.asStmt()) 250b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << "Execution continues on line " 251642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << getSourceManager().getExpansionLineNumber(Loc.asLocation()) 2528966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek << '.'; 2534f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 2544f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "Execution jumps to the end of the "; 2554f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek const Decl *D = N->getLocationContext()->getDecl(); 2564f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek if (isa<ObjCMethodDecl>(D)) 2574f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "method"; 2584f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else if (isa<FunctionDecl>(D)) 2594f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "function"; 2604f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 2614f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek assert(isa<BlockDecl>(D)); 2624f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "anonymous block"; 2634f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 2644f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << '.'; 2654f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 2661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 267082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek return Loc; 268143ca222583a4a355fdc89af852deef287499300Ted Kremenek} 269143ca222583a4a355fdc89af852deef287499300Ted Kremenek 270ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenekstatic bool IsNested(const Stmt *S, ParentMap &PM) { 271ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S))) 272ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek return true; 2731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 274ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const Stmt *Parent = PM.getParentIgnoreParens(S); 2751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 276ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (Parent) 277ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek switch (Parent->getStmtClass()) { 278ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::ForStmtClass: 279ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::DoStmtClass: 280ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::WhileStmtClass: 281ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek return true; 282ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek default: 283ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek break; 284ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek } 2851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 287ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek} 288ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek 289d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticLocation 290d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { 2919c378f705405d37f49795d5e915989de774fe11fTed Kremenek assert(S && "Null Stmt *passed to getEnclosingStmtLocation"); 2921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ParentMap &P = getParentMap(); 2938966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek SourceManager &SMgr = getSourceManager(); 294e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 295ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek while (IsNested(S, P)) { 2968c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const Stmt *Parent = P.getParentIgnoreParens(S); 2971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 298af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (!Parent) 299af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 3001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 301af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek switch (Parent->getStmtClass()) { 3025fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek case Stmt::BinaryOperatorClass: { 3035fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const BinaryOperator *B = cast<BinaryOperator>(Parent); 3045fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 305220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 3065fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek break; 3071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 308af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::CompoundStmtClass: 309af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::StmtExprClass: 310220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 3111d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ChooseExprClass: 3121d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // Similar to '?' if we are referring to condition, just have the edge 3131d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // point to the entire choose expression. 3141d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (cast<ChooseExpr>(Parent)->getCond() == S) 315220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 3161d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 317220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 31856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 3191d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ConditionalOperatorClass: 3201d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // For '?', if we are referring to condition, just have the edge point 3211d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // to the entire '?' expression. 32256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (cast<AbstractConditionalOperator>(Parent)->getCond() == S) 323220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 3241d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 325220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 326af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::DoStmtClass: 327220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 328af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ForStmtClass: 329af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ForStmt>(Parent)->getBody() == S) 330220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 3311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump break; 332af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::IfStmtClass: 333af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<IfStmt>(Parent)->getCond() != S) 334220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 3358bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek break; 336af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 337af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S) 338220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 339af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 340af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::WhileStmtClass: 341af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<WhileStmt>(Parent)->getCond() != S) 342220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 343af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 344af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek default: 345af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 346af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek } 347af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek 348d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek S = Parent; 349d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek } 3501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 351d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek assert(S && "Cannot have null Stmt for PathDiagnosticLocation"); 352e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 353e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // Special case: DeclStmts can appear in for statement declarations, in which 354e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // case the ForStmt is the context. 355e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (isa<DeclStmt>(S)) { 356e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (const Stmt *Parent = P.getParent(S)) { 357e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek switch (Parent->getStmtClass()) { 358e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek case Stmt::ForStmtClass: 359e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 360220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 361e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek default: 362e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek break; 3631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 3641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 365e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 366e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek else if (isa<BinaryOperator>(S)) { 367e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // Special case: the binary operator represents the initialization 368e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // code in a for statement (this can happen when the variable being 369e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // initialized is an old variable. 370e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (const ForStmt *FS = 371e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek dyn_cast_or_null<ForStmt>(P.getParentIgnoreParens(S))) { 372e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (FS->getInit() == S) 373220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(FS, SMgr, LC); 374e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 375e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 376e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 377220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 378d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek} 379d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 380cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 3813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// "Minimal" path diagnostic generation algorithm. 382cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 38356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zakstypedef std::pair<PathDiagnosticCallPiece*, const ExplodedNode*> StackDiagPair; 38456a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zakstypedef SmallVector<StackDiagPair, 6> StackDiagVector; 38556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 386368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaksstatic void updateStackPiecesWithMessage(PathDiagnosticPiece *P, 38756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector &CallStack) { 388368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // If the piece contains a special message, add it to all the call 389368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // pieces on the active stack. 390368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (PathDiagnosticEventPiece *ep = 391368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks dyn_cast<PathDiagnosticEventPiece>(P)) { 392368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 39356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (ep->hasCallStackHint()) 39456a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks for (StackDiagVector::iterator I = CallStack.begin(), 39556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks E = CallStack.end(); I != E; ++I) { 39656a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks PathDiagnosticCallPiece *CP = I->first; 39756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks const ExplodedNode *N = I->second; 3988fe4525680ce72e90cee3e58b5654e3ae955447fNAKAMURA Takumi std::string stackMsg = ep->getCallStackMessage(N); 39956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 400368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // The last message on the path to final bug is the most important 401368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // one. Since we traverse the path backwards, do not add the message 402368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // if one has been previously added. 40356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (!CP->hasCallStackMessage()) 40456a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks CP->setCallStackMessage(stackMsg); 40556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks } 406368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 407368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks} 408cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 40977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM); 41014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 4113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekstatic void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, 4123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticBuilder &PDB, 4133bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose const ExplodedNode *N, 4143bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ArrayRef<BugReporterVisitor *> visitors) { 4158966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek 4163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceManager& SMgr = PDB.getSourceManager(); 41759950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek const LocationContext *LC = PDB.LC; 4189c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() 4193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek ? NULL : *(N->pred_begin()); 420368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 42156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector CallStack; 422368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 4233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (NextNode) { 4241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump N = NextNode; 42559950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC = N->getLocationContext(); 4263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NextNode = GetPredecessorNode(N); 4271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 42861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek ProgramPoint P = N->getLocation(); 4292042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek 4300b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks if (const CallExitEnd *CE = dyn_cast<CallExitEnd>(&P)) { 4312042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PathDiagnosticCallPiece *C = 4322042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PathDiagnosticCallPiece::construct(N, *CE, SMgr); 4332042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(C); 4342042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.pushActivePath(&C->path); 43556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks CallStack.push_back(StackDiagPair(C, N)); 4362042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek continue; 4372042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek } 4382042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek 4392042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek if (const CallEnter *CE = dyn_cast<CallEnter>(&P)) { 4402042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.popActivePath(); 4412042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // The current active path should never be empty. Either we 4422042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // just added a bunch of stuff to the top-level path, or 4430b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks // we have a previous CallExitEnd. If the front of the active 4442042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // path is not a PathDiagnosticCallPiece, it means that the 4452042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // path terminated within a function call. We must then take the 4462042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // current contents of the active path and place it within 4472042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // a new PathDiagnosticCallPiece. 4482042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek assert(!PD.getActivePath().empty()); 4492042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PathDiagnosticCallPiece *C = 4502042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek dyn_cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 4519373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks if (!C) { 4529373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks const Decl *Caller = CE->getLocationContext()->getDecl(); 4539373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 4549373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks } 4552042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek C->setCallee(*CE, SMgr); 456368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (!CallStack.empty()) { 45756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks assert(CallStack.back().first == C); 458368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks CallStack.pop_back(); 459368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 4602042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek continue; 4612042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek } 4621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4639c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 4649c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CFGBlock *Src = BE->getSrc(); 4659c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CFGBlock *Dst = BE->getDst(); 4669c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Stmt *T = Src->getTerminator(); 4671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 46861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek if (!T) 46961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek continue; 4701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 471590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation Start = 472590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation::createBegin(T, SMgr, 473590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks N->getLocationContext()); 4741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 47561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek switch (T->getStmtClass()) { 47661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek default: 47761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 4781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 47961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek case Stmt::GotoStmtClass: 4801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::IndirectGotoStmtClass: { 4819c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Stmt *S = GetNextStmt(N); 4821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 48361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek if (!S) 48461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek continue; 4851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 486297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 4871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::raw_string_ostream os(sbuf); 488d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S); 4891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 49000605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os << "Control jumps to line " 491642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << End.asLocation().getExpansionLineNumber(); 4922042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 493802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek os.str())); 49461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 49561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 4961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::SwitchStmtClass: { 49861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek // Figure out what case arm we took. 499297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 500297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 5011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5029c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const Stmt *S = Dst->getLabel()) { 503220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(S, SMgr, LC); 5041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5055a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek switch (S->getStmtClass()) { 506082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek default: 507082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "No cases match in the switch statement. " 5083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek "Control jumps to line " 509642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << End.asLocation().getExpansionLineNumber(); 510082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek break; 511082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek case Stmt::DefaultStmtClass: 512082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "Control jumps to the 'default' case at line " 513642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << End.asLocation().getExpansionLineNumber(); 514082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek break; 5151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 516082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek case Stmt::CaseStmtClass: { 5171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump os << "Control jumps to 'case "; 5189c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CaseStmt *Case = cast<CaseStmt>(S); 5199c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Expr *LHS = Case->getLHS()->IgnoreParenCasts(); 5201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Determine if it is an enum. 522082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek bool GetRawInt = true; 5231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5249c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) { 525082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek // FIXME: Maybe this should be an assertion. Are there cases 526082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek // were it is not an EnumConstantDecl? 5279c378f705405d37f49795d5e915989de774fe11fTed Kremenek const EnumConstantDecl *D = 52803509aea098772644bf4662dc1c88634818ceeccZhongxing Xu dyn_cast<EnumConstantDecl>(DR->getDecl()); 5291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 530082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek if (D) { 531082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek GetRawInt = false; 532b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer os << *D; 533082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 5345a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek } 5359ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 5369ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman if (GetRawInt) 537a6b8b2c09610b8bc4330e948ece8b940c2386406Richard Smith os << LHS->EvaluateKnownConstInt(PDB.getASTContext()); 5389ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 53900605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os << ":' at line " 540642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << End.asLocation().getExpansionLineNumber(); 541082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek break; 542082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 54361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 5442042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 54500605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os.str())); 54661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 547567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek else { 548c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "'Default' branch taken. "; 5491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N); 5502042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 55100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os.str())); 552567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek } 5531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 55461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 55561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 5561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5572673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::BreakStmtClass: 5582673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::ContinueStmtClass: { 559297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 560297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 56100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 5622042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 563082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os.str())); 5642673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek break; 5652673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek } 5661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine control-flow for ternary '?'. 56856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 569706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek case Stmt::ConditionalOperatorClass: { 570297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 571297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 5721d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek os << "'?' condition is "; 5731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 574706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()+1) == Dst) 575082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "false"; 576706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek else 577082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "true"; 5781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 57900605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 5801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5811d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (const Stmt *S = End.asStmt()) 5821d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 5831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5842042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 585babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek os.str())); 586babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 587babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 5881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine control-flow for short-circuited '&&' and '||'. 590babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek case Stmt::BinaryOperatorClass: { 591babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek if (!PDB.supportsLogicalOpControlFlow()) 592babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 5931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 59403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const BinaryOperator *B = cast<BinaryOperator>(T); 595babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek std::string sbuf; 596babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek llvm::raw_string_ostream os(sbuf); 597babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek os << "Left side of '"; 5981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5992de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_LAnd) { 600f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "&&" << "' is "; 6011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 602f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 603f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 604220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 6050cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 6060cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 6072042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 608f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os.str())); 6091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 610f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 611f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 612220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 613f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 6142042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 615f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os.str())); 6161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 617babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 618babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek else { 6192de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(B->getOpcode() == BO_LOr); 620f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "||" << "' is "; 6211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 622f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 623f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 624220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 625f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 6262042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 6271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump os.str())); 628f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 629f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 630f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 631220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 6320cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 6330cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 6342042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 6351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump os.str())); 636f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 637babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 6381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 639706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek break; 640706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek } 6411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::DoStmtClass: { 643706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()) == Dst) { 644297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 645297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 6461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 647c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "Loop condition is true. "; 648d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 6491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 650d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 651d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 6521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6532042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 654082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os.str())); 655082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 656082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek else { 65700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 6581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 659d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 660d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 6611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6622042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 6633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek "Loop condition is false. Exiting loop")); 6643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 6651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 6673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 6681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::WhileStmtClass: 6701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::ForStmtClass: { 6713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) { 6723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::string sbuf; 6733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::raw_string_ostream os(sbuf); 6741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek os << "Loop condition is false. "; 6763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 6773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 6783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 6791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6802042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 6813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek os.str())); 6823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 6833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 6843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 6853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 6863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 6871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6882042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 6895fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek "Loop condition is true. Entering loop body")); 6903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 6911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 6933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 6941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::IfStmtClass: { 6963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 6971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 6993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 7001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) 7022042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 7035fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek "Taking false branch")); 7041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else 7052042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(Start, End, 7065fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek "Taking true branch")); 7071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 7093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 713dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (NextNode) { 7148e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add diagnostic pieces from custom visitors. 7158e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 7163bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 7173bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = visitors.end(); 7183bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose I != E; ++I) { 719368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 7202042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 721368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks updateStackPiecesWithMessage(p, CallStack); 722368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 723dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 7248966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 7253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 72714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // After constructing the full PathDiagnostic, do a pass over it to compact 72814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // PathDiagnosticPieces that occur within a macro. 72977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager()); 7303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 7313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 7323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 7335fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek// "Extensive" PathDiagnostic generation. 7345fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 7355fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 7365fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenekstatic bool IsControlFlowExpr(const Stmt *S) { 7375fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const Expr *E = dyn_cast<Expr>(S); 7381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7395fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (!E) 7405fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return false; 7411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump E = E->IgnoreParenCasts(); 7431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 74456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (isa<AbstractConditionalOperator>(E)) 7455fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 7461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7475fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) 7485fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 7495fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 7501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 7525fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek} 7535fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 75414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremeneknamespace { 755ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ContextLocation : public PathDiagnosticLocation { 7568f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsDead; 7578f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekpublic: 7588f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation(const PathDiagnosticLocation &L, bool isdead = false) 7598f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek : PathDiagnosticLocation(L), IsDead(isdead) {} 7601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void markDead() { IsDead = true; } 7628f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool isDead() const { return IsDead; } 7638f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek}; 7641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 765ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass EdgeBuilder { 7668f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek std::vector<ContextLocation> CLocs; 7678f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek typedef std::vector<ContextLocation>::iterator iterator; 76814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnostic &PD; 76914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB; 77014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation PrevLoc; 7711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7728f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsConsumedExpr(const PathDiagnosticLocation &L); 7731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 77414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek bool containsLocation(const PathDiagnosticLocation &Container, 77514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee); 7761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 77714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L); 7781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7799650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L, 7809650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek bool firstCharOnly = false) { 7818c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (const Stmt *S = L.asStmt()) { 7829650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek const Stmt *Original = S; 7838c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek while (1) { 7848c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek // Adjust the location for some expressions that are best referenced 7858c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek // by one of their subexpressions. 7869650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek switch (S->getStmtClass()) { 7879650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek default: 7889650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek break; 7899650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ParenExprClass: 790f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne case Stmt::GenericSelectionExprClass: 791f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne S = cast<Expr>(S)->IgnoreParens(); 7929650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 7939650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 79456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 7959650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ConditionalOperatorClass: 79656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall S = cast<AbstractConditionalOperator>(S)->getCond(); 7979650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 7989650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 7999650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ChooseExprClass: 8009650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek S = cast<ChooseExpr>(S)->getCond(); 8019650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 8029650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 8039650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::BinaryOperatorClass: 8049650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek S = cast<BinaryOperator>(S)->getLHS(); 8059650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 8069650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 8079650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek } 8081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8099650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek break; 8108c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 8111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8129650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek if (S != Original) 81359950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek L = PathDiagnosticLocation(S, L.getManager(), PDB.LC); 8148c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 8151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8169650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek if (firstCharOnly) 8171531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks L = PathDiagnosticLocation::createSingleLocation(L); 8189650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek 8198c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek return L; 8208c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 8211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 82214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void popLocation() { 8238f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) { 8245c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // For contexts, we only one the first character as the range. 82507c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek rawAddEdge(cleanUpLocation(CLocs.back(), true)); 8265c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek } 82714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.pop_back(); 82814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 8291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 83014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekpublic: 83114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb) 83214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek : PD(pd), PDB(pdb) { 8331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 834a301a6773db085575ac51e3c966858180390c25bTed Kremenek // If the PathDiagnostic already has pieces, add the enclosing statement 835a301a6773db085575ac51e3c966858180390c25bTed Kremenek // of the first piece as a context as well. 836802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek if (!PD.path.empty()) { 837802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek PrevLoc = (*PD.path.begin())->getLocation(); 8381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 83914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = PrevLoc.asStmt()) 840e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 84114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 84214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 84314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 84414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ~EdgeBuilder() { 84514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) popLocation(); 8460cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 847a301a6773db085575ac51e3c966858180390c25bTed Kremenek // Finally, add an initial edge from the start location of the first 848a301a6773db085575ac51e3c966858180390c25bTed Kremenek // statement (if it doesn't already exist). 8490cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin( 85059950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC, 8510cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PDB.getSourceManager()); 8520cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks if (L.isValid()) 8530cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks rawAddEdge(L); 85414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 85514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 8565de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek void flushLocations() { 8575de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek while (!CLocs.empty()) 8585de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek popLocation(); 8595de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek PrevLoc = PathDiagnosticLocation(); 8605de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek } 8615de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 86214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false); 8631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8648bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek void rawAddEdge(PathDiagnosticLocation NewLoc); 8651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 86614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addContext(const Stmt *S); 867e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek void addExtendedContext(const Stmt *S); 8681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}; 86914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} // end anonymous namespace 87014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 87114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 87214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekPathDiagnosticLocation 87314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekEdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) { 87414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = L.asStmt()) { 87514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (IsControlFlowExpr(S)) 87614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 8771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return PDB.getEnclosingStmtLocation(S); 87914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 8801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 88114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 88214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 88314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 88414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekbool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container, 88514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee) { 88614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 88714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container == Containee) 88814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 8891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 89014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container.asDecl()) 89114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 8921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 89314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = Containee.asStmt()) 89414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *ContainerS = Container.asStmt()) { 89514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (S) { 89614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (S == ContainerS) 89714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 89814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek S = PDB.getParent(S); 89914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 90014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return false; 90114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 90214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 90314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Less accurate: compare using source ranges. 90414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContainerR = Container.asRange(); 90514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContaineeR = Containee.asRange(); 9061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 90714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceManager &SM = PDB.getSourceManager(); 908402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin()); 909402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd()); 910402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin()); 911402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd()); 9121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 913642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg); 914642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd); 915642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg); 916642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd); 9171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 91814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek assert(ContainerBegLine <= ContainerEndLine); 9191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(ContaineeBegLine <= ContaineeEndLine); 9201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 92114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return (ContainerBegLine <= ContaineeBegLine && 92214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ContainerEndLine >= ContaineeEndLine && 92314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerBegLine != ContaineeBegLine || 924a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerRBeg) <= 925a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContaineeRBeg)) && 92614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerEndLine != ContaineeEndLine || 927a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerREnd) >= 9286488dc31153be6f98b404c7860be6c66bb4ec917Ted Kremenek SM.getExpansionColumnNumber(ContaineeREnd))); 92914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 93014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 93114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) { 93214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!PrevLoc.isValid()) { 93314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PrevLoc = NewLoc; 93414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 93514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 9361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9378c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc); 9388c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc); 9391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9408c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (NewLocClean.asLocation() == PrevLocClean.asLocation()) 94114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 9421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 94314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // FIXME: Ignore intra-macro edges for now. 944402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth if (NewLocClean.asLocation().getExpansionLoc() == 945402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth PrevLocClean.asLocation().getExpansionLoc()) 94614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 94714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 9482042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean)); 9498c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek PrevLoc = NewLoc; 95014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 95114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 95214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) { 9531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 954a301a6773db085575ac51e3c966858180390c25bTed Kremenek if (!alwaysAdd && NewLoc.asLocation().isMacroID()) 955a301a6773db085575ac51e3c966858180390c25bTed Kremenek return; 9561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 95714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc); 95814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 95914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 9608f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation &TopContextLoc = CLocs.back(); 9611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 96214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 96314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == CLoc) { 9648f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 9654c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek if (IsConsumedExpr(TopContextLoc) && 9664c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek !IsControlFlowExpr(TopContextLoc.asStmt())) 9678f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek TopContextLoc.markDead(); 9688f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek 96914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 9708f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 97114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 97214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 97314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 97414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 97514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, CLoc)) { 9768f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 97714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 9781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9794c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek if (IsConsumedExpr(CLoc) && !IsControlFlowExpr(CLoc.asStmt())) { 9808f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek CLocs.push_back(ContextLocation(CLoc, true)); 9818f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return; 9828f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 9838f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 9841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(CLoc); 9861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 98714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 98814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 98914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 99014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 99114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 9921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9935c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // If we reach here, there is no enclosing context. Just add the edge. 9945c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek rawAddEdge(NewLoc); 99514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 99614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 9978f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekbool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) { 9988f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt())) 9998f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X); 10001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10018f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return false; 10028f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek} 10031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1004e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenekvoid EdgeBuilder::addExtendedContext(const Stmt *S) { 1005e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (!S) 1006e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek return; 10071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const Stmt *Parent = PDB.getParent(S); 1009e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek while (Parent) { 1010e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (isa<CompoundStmt>(Parent)) 1011e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek Parent = PDB.getParent(Parent); 1012e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek else 1013e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1014e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1015e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek 1016e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (Parent) { 1017e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek switch (Parent->getStmtClass()) { 1018e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::DoStmtClass: 1019e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 1020e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(Parent); 1021e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek default: 1022e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1023e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1024e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 10251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1026e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(S); 1027e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek} 10281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 102914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addContext(const Stmt *S) { 103014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!S) 103114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 103214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 103359950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.LC); 10341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 103514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 103614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &TopContextLoc = CLocs.back(); 103714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 103814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 103914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == L) 104014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 104114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 104214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, L)) { 104314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 10441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 104514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 104614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 104714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 104814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 104914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 105014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 105114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 105214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 105314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 105414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekstatic void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, 105514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB, 10563bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose const ExplodedNode *N, 10573bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ArrayRef<BugReporterVisitor *> visitors) { 105814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder EB(PD, PDB); 10590cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks const SourceManager& SM = PDB.getSourceManager(); 106056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector CallStack; 106114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 10629c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); 106314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (NextNode) { 106414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek N = NextNode; 106514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek NextNode = GetPredecessorNode(N); 106614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ProgramPoint P = N->getLocation(); 106714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 1068dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek do { 10690b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks if (const CallExitEnd *CE = dyn_cast<CallExitEnd>(&P)) { 10705de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek const StackFrameContext *LCtx = 10715de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek CE->getLocationContext()->getCurrentStackFrame(); 10720b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks PathDiagnosticLocation Loc(CE->getStmt(), 10735de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek PDB.getSourceManager(), 10745de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek LCtx); 10755de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek EB.addEdge(Loc, true); 10765de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek EB.flushLocations(); 10772042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PathDiagnosticCallPiece *C = 10782042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PathDiagnosticCallPiece::construct(N, *CE, SM); 10792042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(C); 10802042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.pushActivePath(&C->path); 108156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks CallStack.push_back(StackDiagPair(C, N)); 10825de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek break; 10835de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek } 10844ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek 10852042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // Pop the call hierarchy if we are done walking the contents 10862042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // of a function call. 10872042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek if (const CallEnter *CE = dyn_cast<CallEnter>(&P)) { 1088097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek // Add an edge to the start of the function. 1089097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek const Decl *D = CE->getCalleeContext()->getDecl(); 1090097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek PathDiagnosticLocation pos = 1091097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek PathDiagnosticLocation::createBegin(D, SM); 1092097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek EB.addEdge(pos); 1093097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek 1094097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek // Flush all locations, and pop the active path. 10954ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek EB.flushLocations(); 10962042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.popActivePath(); 10974ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek assert(!PD.getActivePath().empty()); 10984ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek PDB.LC = N->getLocationContext(); 1099097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek 11002042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // The current active path should never be empty. Either we 11012042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // just added a bunch of stuff to the top-level path, or 11020b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks // we have a previous CallExitEnd. If the front of the active 11032042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // path is not a PathDiagnosticCallPiece, it means that the 11042042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // path terminated within a function call. We must then take the 11052042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // current contents of the active path and place it within 11062042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // a new PathDiagnosticCallPiece. 11074ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek PathDiagnosticCallPiece *C = 11082042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek dyn_cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 11099373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks if (!C) { 11109373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks const Decl * Caller = CE->getLocationContext()->getDecl(); 11119373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 11129373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks } 11132042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek C->setCallee(*CE, SM); 11142042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek EB.addContext(CE->getCallExpr()); 1115368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 1116368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (!CallStack.empty()) { 111756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks assert(CallStack.back().first == C); 1118368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks CallStack.pop_back(); 1119368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 11202042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek break; 11212042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek } 11224ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek 11234ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // Note that is important that we update the LocationContext 11244ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // after looking at CallExits. CallExit basically adds an 11254ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // edge in the *caller*, so we don't want to update the LocationContext 11264ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // too soon. 11274ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek PDB.LC = N->getLocationContext(); 11285de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 1129dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Block edges. 11305de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 1131dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek const CFGBlock &Blk = *BE->getSrc(); 1132dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek const Stmt *Term = Blk.getTerminator(); 11331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1134dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Are we jumping to the head of a loop? Add a special diagnostic. 1135ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (const Stmt *Loop = BE->getDst()->getLoopTarget()) { 113659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PathDiagnosticLocation L(Loop, SM, PDB.LC); 1137ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const CompoundStmt *CS = NULL; 11381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1139ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (!Term) { 1140ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) 1141ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek CS = dyn_cast<CompoundStmt>(FS->getBody()); 1142ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) 11431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CS = dyn_cast<CompoundStmt>(WS->getBody()); 1144ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek } 11451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1146dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek PathDiagnosticEventPiece *p = 1147dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek new PathDiagnosticEventPiece(L, 114807c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek "Looping back to the head of the loop"); 11492dd17abf11ae64339fa6bfaa57d76e13a5fbe5b8Ted Kremenek p->setPrunable(true); 11501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1151dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek EB.addEdge(p->getLocation(), true); 11522042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 11531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1154ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (CS) { 11550cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation BL = 11560cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createEndBrace(CS, SM); 115707c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek EB.addEdge(BL); 1158dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 11598bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 11601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1161ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (Term) 1162ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek EB.addContext(Term); 11631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1164dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 11658bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 116614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 11671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) { 11683c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (const CFGStmt *S = BE->getFirstElement().getAs<CFGStmt>()) { 11693c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const Stmt *stmt = S->getStmt(); 11703c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (IsControlFlowExpr(stmt)) { 1171b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu // Add the proper context for '&&', '||', and '?'. 11723c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addContext(stmt); 1173b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 1174b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu else 11753c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt()); 1176dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 1177b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu 1178dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 1179dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 11805de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 11815de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 1182dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } while (0); 11831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1184dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (!NextNode) 118514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek continue; 11861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11878e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add pieces from custom visitors. 11888e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 11893bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 11903bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = visitors.end(); 11913bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose I != E; ++I) { 11928e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 11938966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek const PathDiagnosticLocation &Loc = p->getLocation(); 11948966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek EB.addEdge(Loc, true); 11952042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 1196368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks updateStackPiecesWithMessage(p, CallStack); 1197368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 11988966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek if (const Stmt *S = Loc.asStmt()) 11991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 12008966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 12011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 120214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 120314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 120414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 12055fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 12063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugType and subclasses. 12073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 1208404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios KyrtzidisBugType::~BugType() { } 1209404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 12103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugType::FlushReports(BugReporter &BR) {} 12113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 121299ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BuiltinBug::anchor() {} 121399ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 12143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 12153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReport and subclasses. 12163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 1217e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 121899ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BugReport::NodeResolver::anchor() {} 121999ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 12208e6431adab313e283a992698f6fc7afe62420999Anna Zaksvoid BugReport::addVisitor(BugReporterVisitor* visitor) { 12218e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (!visitor) 12228e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 12238e6431adab313e283a992698f6fc7afe62420999Anna Zaks 12248e6431adab313e283a992698f6fc7afe62420999Anna Zaks llvm::FoldingSetNodeID ID; 12258e6431adab313e283a992698f6fc7afe62420999Anna Zaks visitor->Profile(ID); 12268e6431adab313e283a992698f6fc7afe62420999Anna Zaks void *InsertPos; 12278e6431adab313e283a992698f6fc7afe62420999Anna Zaks 12288e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) { 12298e6431adab313e283a992698f6fc7afe62420999Anna Zaks delete visitor; 12308e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 12318e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 12328e6431adab313e283a992698f6fc7afe62420999Anna Zaks 12338e6431adab313e283a992698f6fc7afe62420999Anna Zaks CallbacksSet.InsertNode(visitor, InsertPos); 12343bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose Callbacks.push_back(visitor); 12353bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 12368e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 12378e6431adab313e283a992698f6fc7afe62420999Anna Zaks 12388e6431adab313e283a992698f6fc7afe62420999Anna ZaksBugReport::~BugReport() { 12398e6431adab313e283a992698f6fc7afe62420999Anna Zaks for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) { 1240dc757b049796949e4b11646445a6598f0bdabd7aAnna Zaks delete *I; 12418e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 12428e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 1243e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 124407189521a15d9c088216b943649cb9fe231cbb57Ted Kremenekconst Decl *BugReport::getDeclWithIssue() const { 124507189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek if (DeclWithIssue) 124607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return DeclWithIssue; 124707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 124807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek const ExplodedNode *N = getErrorNode(); 124907189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek if (!N) 125007189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return 0; 125107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 125207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek const LocationContext *LC = N->getLocationContext(); 125307189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return LC->getCurrentStackFrame()->getDecl(); 125407189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek} 125507189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 1256e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaksvoid BugReport::Profile(llvm::FoldingSetNodeID& hash) const { 1257e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddPointer(&BT); 1258e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddString(Description); 1259ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks if (UniqueingLocation.isValid()) { 1260ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks UniqueingLocation.Profile(hash); 1261ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks } else if (Location.isValid()) { 1262590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks Location.Profile(hash); 1263590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } else { 1264590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(ErrorNode); 1265590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode)); 1266590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } 1267e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 1268e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks for (SmallVectorImpl<SourceRange>::const_iterator I = 1269e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks Ranges.begin(), E = Ranges.end(); I != E; ++I) { 1270e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks const SourceRange range = *I; 1271e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!range.isValid()) 1272e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks continue; 1273e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getBegin().getRawEncoding()); 1274e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getEnd().getRawEncoding()); 1275e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 1276e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks} 12773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 127876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(SymbolRef sym) { 127976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!sym) 128076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return; 12813bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 12823bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // If the symbol wasn't already in our set, note a configuration change. 12833bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose if (interestingSymbols.insert(sym).second) 12843bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 12858ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose 12868ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose if (const SymbolMetadata *meta = dyn_cast<SymbolMetadata>(sym)) 12878ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose interestingRegions.insert(meta->getRegion()); 128876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 128976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 129076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(const MemRegion *R) { 129176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!R) 129276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return; 12933bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 12943bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // If the base region wasn't already in our set, note a configuration change. 129576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek R = R->getBaseRegion(); 12963bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose if (interestingRegions.insert(R).second) 12973bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 12988ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose 129976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 130076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek interestingSymbols.insert(SR->getSymbol()); 130176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 130276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 130376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(SVal V) { 130476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek markInteresting(V.getAsRegion()); 130576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek markInteresting(V.getAsSymbol()); 130676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 130776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 130876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekbool BugReport::isInteresting(SVal V) const { 130976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return isInteresting(V.getAsRegion()) || isInteresting(V.getAsSymbol()); 131076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 131176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 131276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekbool BugReport::isInteresting(SymbolRef sym) const { 131376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!sym) 131476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 13158ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose // We don't currently consider metadata symbols to be interesting 13168ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose // even if we know their region is interesting. Is that correct behavior? 131776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return interestingSymbols.count(sym); 131876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 131976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 132076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekbool BugReport::isInteresting(const MemRegion *R) const { 132176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!R) 132276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 132376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek R = R->getBaseRegion(); 132476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek bool b = interestingRegions.count(R); 132576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (b) 132676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return true; 132776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 132876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return interestingSymbols.count(SR->getSymbol()); 132976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 133076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 133176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 133276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 13339c378f705405d37f49795d5e915989de774fe11fTed Kremenekconst Stmt *BugReport::getStmt() const { 1334e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!ErrorNode) 1335e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return 0; 1336e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 1337212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care ProgramPoint ProgP = ErrorNode->getLocation(); 13385f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek const Stmt *S = NULL; 13391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13409c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (BlockEntrance *BE = dyn_cast<BlockEntrance>(&ProgP)) { 1341fafd3834754d2093e0ad7a1c005860fd527ecb7fZhongxing Xu CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit(); 134250d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu if (BE->getBlock() == &Exit) 1343212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care S = GetPreviousStmt(ErrorNode); 13443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 13455f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (!S) 13461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump S = GetStmt(ProgP); 13471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return S; 13493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 13503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1351640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidisstd::pair<BugReport::ranges_iterator, BugReport::ranges_iterator> 1352e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna ZaksBugReport::getRanges() { 1353e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // If no custom ranges, add the range of the statement corresponding to 1354e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // the error node. 1355e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (Ranges.empty()) { 1356e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (const Expr *E = dyn_cast_or_null<Expr>(getStmt())) 1357e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks addRange(E->getSourceRange()); 1358e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks else 1359e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 1360e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 1361e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 136214924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks // User-specified absence of range info. 136314924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks if (Ranges.size() == 1 && !Ranges.begin()->isValid()) 136414924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 136514924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks 1366e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(Ranges.begin(), Ranges.end()); 13673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 13683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1369590dd8e0959d8df5621827768987c4792b74fc06Anna ZaksPathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const { 1370b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks if (ErrorNode) { 1371590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(!Location.isValid() && 1372b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks "Either Location or ErrorNode should be specified but not both."); 1373b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks 13749c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const Stmt *S = GetCurrentOrPreviousStmt(ErrorNode)) { 1375590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks const LocationContext *LC = ErrorNode->getLocationContext(); 1376590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks 13773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // For member expressions, return the location of the '.' or '->'. 13785b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) 1379590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createMemberLoc(ME, SM); 13805b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek // For binary operators, return the location of the operator. 13815b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) 1382590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createOperatorLoc(B, SM); 13833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1384590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createBegin(S, SM, LC); 13853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1386b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } else { 1387b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks assert(Location.isValid()); 1388b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks return Location; 1389b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } 1390b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks 1391590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation(); 13923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 13933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 13953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReporter and subclasses. 13963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 13973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13984a5f724538cbc275370c9504e8169ce92503256cBenjamin KramerBugReportEquivClass::~BugReportEquivClass() { } 1399a2f4ec0df645fc249d2945beef9653f03b175417Zhongxing XuGRBugReporter::~GRBugReporter() { } 14003106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReporterData::~BugReporterData() {} 14013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 140238b02b912e1a55c912f603c4369431264d36a381Zhongxing XuExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); } 14033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 140418c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekProgramStateManager& 14053106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekGRBugReporter::getStateManager() { return Eng.getStateManager(); } 14063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 14073b030a28cda2b953758507769c1d436bec5ec45eAnna ZaksBugReporter::~BugReporter() { 14083b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks FlushReports(); 14093b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks 14103b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks // Free the bug reports we are tracking. 14113b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks typedef std::vector<BugReportEquivClass *> ContTy; 14123b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end(); 14133b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks I != E; ++I) { 14143b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks delete *I; 14153b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks } 14163b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks} 14173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 14183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugReporter::FlushReports() { 14193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (BugTypes.isEmpty()) 14203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return; 14213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 14223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // First flush the warnings for each BugType. This may end up creating new 1423404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // warnings and new BugTypes. 1424404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: Only NSErrorChecker needs BugType's FlushReports. 1425404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // Turn NSErrorChecker into a proper checker and remove this. 14265f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<const BugType*, 16> bugTypes; 14273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) 1428404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis bugTypes.push_back(*I); 14295f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVector<const BugType*, 16>::iterator 1430404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I) 14313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const_cast<BugType*>(*I)->FlushReports(*this); 14323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1433404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis typedef llvm::FoldingSet<BugReportEquivClass> SetTy; 1434404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis for (SetTy::iterator EI=EQClasses.begin(), EE=EQClasses.end(); EI!=EE;++EI){ 1435404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugReportEquivClass& EQ = *EI; 1436404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis FlushReport(EQ); 14373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 14383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1439404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // BugReporter owns and deletes only BugTypes created implicitly through 1440404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // EmitBasicReport. 1441404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: There are leaks from checkers that assume that the BugTypes they 1442404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // create will be destroyed by the BugReporter. 1443404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis for (llvm::StringMap<BugType*>::iterator 1444404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I) 1445404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis delete I->second; 1446404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 14473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Remove all references to the BugType objects. 14483baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.getEmptySet(); 14493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 14503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 14513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 14523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnostics generation. 14533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 14543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 145538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xustatic std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, 1456c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::pair<ExplodedNode*, unsigned> > 145738b02b912e1a55c912f603c4369431264d36a381Zhongxing XuMakeReportGraph(const ExplodedGraph* G, 14585f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<const ExplodedNode*> &nodes) { 14591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the trimmed graph. It will contain the shortest paths from the 14611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // error nodes to the root. In the new graph we should only have one 14623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // error node unless there are two or more error nodes with the same minimum 14633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // path length. 146438b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu ExplodedGraph* GTrim; 1465c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu InterExplodedGraphMap* NMap; 14663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 14673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*, const void*> InverseMap; 146840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek llvm::tie(GTrim, NMap) = G->Trim(nodes.data(), nodes.data() + nodes.size(), 146940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek &InverseMap); 14701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create owning pointers for GTrim and NMap just to ensure that they are 14723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // released when this function exists. 14736f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<ExplodedGraph> AutoReleaseGTrim(GTrim); 14746f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<InterExplodedGraphMap> AutoReleaseNMap(NMap); 14751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the (first) error node in the trimmed graph. We just need to consult 14773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // the node map (NMap) which maps from nodes in the original graph to nodes 14783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // in the new graph. 1479938332c657390d1e782e0adc03b092993edae962Ted Kremenek 1480c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::queue<const ExplodedNode*> WS; 148138b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu typedef llvm::DenseMap<const ExplodedNode*, unsigned> IndexMapTy; 1482938332c657390d1e782e0adc03b092993edae962Ted Kremenek IndexMapTy IndexMap; 14833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 148440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek for (unsigned nodeIndex = 0 ; nodeIndex < nodes.size(); ++nodeIndex) { 148540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek const ExplodedNode *originalNode = nodes[nodeIndex]; 148640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (const ExplodedNode *N = NMap->getMappedNode(originalNode)) { 1487938332c657390d1e782e0adc03b092993edae962Ted Kremenek WS.push(N); 148840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek IndexMap[originalNode] = nodeIndex; 14893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 149040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 14911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1492938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(!WS.empty() && "No error node found in the trimmed graph."); 14933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 14943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create a new (third!) graph with a single path. This is the graph 14953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // that will be returned to the caller. 1496c77a55126fcad66fb086f8e100a494caa2496a2dZhongxing Xu ExplodedGraph *GNew = new ExplodedGraph(); 14971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Sometimes the trimmed graph can contain a cycle. Perform a reverse BFS 14993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // to the root node, and then construct a new graph that contains only 15003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // a single path. 15013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*,unsigned> Visited; 15021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek unsigned cnt = 0; 15049c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *Root = 0; 15051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!WS.empty()) { 15079c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *Node = WS.front(); 15083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek WS.pop(); 15091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Visited.find(Node) != Visited.end()) 15113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 15121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Visited[Node] = cnt++; 15141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Node->pred_empty()) { 15163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Root = Node; 15173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 15183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1520c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu for (ExplodedNode::const_pred_iterator I=Node->pred_begin(), 15213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek E=Node->pred_end(); I!=E; ++I) 15223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek WS.push(*I); 15233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1525938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(Root); 15261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now walk from the root down the BFS path, always taking the successor 15283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // with the lowest number. 15291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ExplodedNode *Last = 0, *First = 0; 15303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NodeBackMap *BM = new NodeBackMap(); 1531938332c657390d1e782e0adc03b092993edae962Ted Kremenek unsigned NodeIndex = 0; 15321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1533c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu for ( const ExplodedNode *N = Root ;;) { 15343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Lookup the number associated with the current node. 15353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*,unsigned>::iterator I = Visited.find(N); 1536938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(I != Visited.end()); 15371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the equivalent node in the new graph with the same state 15393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // and location. 15409c378f705405d37f49795d5e915989de774fe11fTed Kremenek ExplodedNode *NewN = GNew->getNode(N->getLocation(), N->getState()); 15411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Store the mapping to the original node. 15433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*, const void*>::iterator IMitr=InverseMap.find(N); 15443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(IMitr != InverseMap.end() && "No mapping to original node."); 1545c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu (*BM)[NewN] = (const ExplodedNode*) IMitr->second; 15461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Link up the new node with the previous node. 15483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Last) 15495fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek NewN->addPredecessor(Last, *GNew); 15501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Last = NewN; 15521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Are we at the final node? 1554938332c657390d1e782e0adc03b092993edae962Ted Kremenek IndexMapTy::iterator IMI = 1555c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu IndexMap.find((const ExplodedNode*)(IMitr->second)); 1556938332c657390d1e782e0adc03b092993edae962Ted Kremenek if (IMI != IndexMap.end()) { 15573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek First = NewN; 1558938332c657390d1e782e0adc03b092993edae962Ted Kremenek NodeIndex = IMI->second; 15593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 15603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the next successor node. We choose the node that is marked 15633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // with the lowest DFS number. 1564c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::const_succ_iterator SI = N->succ_begin(); 1565c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::const_succ_iterator SE = N->succ_end(); 15663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek N = 0; 15671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (unsigned MinVal = 0; SI != SE; ++SI) { 15691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek I = Visited.find(*SI); 15711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (I == Visited.end()) 15733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 15741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!N || I->second < MinVal) { 15763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek N = *SI; 15773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MinVal = I->second; 15783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1581938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(N); 15823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1584938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(First); 1585938332c657390d1e782e0adc03b092993edae962Ted Kremenek 15863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return std::make_pair(std::make_pair(GNew, BM), 15873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::make_pair(First, NodeIndex)); 15883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 1589d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 15903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object 15913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// and collapses PathDiagosticPieces that are expanded by macros. 159277d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) { 15932042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek typedef std::vector<std::pair<IntrusiveRefCntPtr<PathDiagnosticMacroPiece>, 15942042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek SourceLocation> > MacroStackTy; 15951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1596c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith typedef std::vector<IntrusiveRefCntPtr<PathDiagnosticPiece> > 15973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy; 15981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStackTy MacroStack; 16003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy Pieces; 16011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 160277d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek for (PathPieces::const_iterator I = path.begin(), E = path.end(); 16032042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek I!=E; ++I) { 160477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 160577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek PathDiagnosticPiece *piece = I->getPtr(); 160677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 160777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek // Recursively compact calls. 160877d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek if (PathDiagnosticCallPiece *call=dyn_cast<PathDiagnosticCallPiece>(piece)){ 160977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek CompactPathDiagnostic(call->path, SM); 161077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek } 161177d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 16123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Get the location of the PathDiagnosticPiece. 161377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek const FullSourceLoc Loc = piece->getLocation().asLocation(); 16141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine the instantiation location, which is the location we group 16163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // related PathDiagnosticPieces. 16171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation InstantiationLoc = Loc.isMacroID() ? 1618402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 16193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 16201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Loc.isFileID()) { 16223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.clear(); 162377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek Pieces.push_back(piece); 16243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 16253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1626706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek 16273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(Loc.isMacroID()); 16281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Is the PathDiagnosticPiece within the same macro group? 16303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) { 163177d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek MacroStack.back().first->subPieces.push_back(piece); 16323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 16333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1634d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 16353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // We aren't in the same group. Are we descending into a new macro 16363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // or are part of an old one? 1637c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith IntrusiveRefCntPtr<PathDiagnosticMacroPiece> MacroGroup; 1638d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 16393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ? 1640402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 16413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 16421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Walk the entire macro stack. 16443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!MacroStack.empty()) { 16453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (InstantiationLoc == MacroStack.back().second) { 16463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 16473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 16483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 16491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (ParentInstantiationLoc == MacroStack.back().second) { 16513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 16523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 165361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 16541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.pop_back(); 16566837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek } 16571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) { 16593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create a new macro group and add it to the stack. 1660590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticMacroPiece *NewGroup = 1661590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks new PathDiagnosticMacroPiece( 166277d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek PathDiagnosticLocation::createSingleLocation(piece->getLocation())); 16635a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek 16643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (MacroGroup) 1665802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek MacroGroup->subPieces.push_back(NewGroup); 16663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 16673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(InstantiationLoc.isFileID()); 16683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Pieces.push_back(NewGroup); 16693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 16701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = NewGroup; 16723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc)); 16737dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 16743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 16753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Finally, add the PathDiagnosticPiece to the group. 167677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek MacroGroup->subPieces.push_back(piece); 16773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 16781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now take the pieces and construct a new PathDiagnostic. 168077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek path.clear(); 16811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 168277d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) 168377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek path.push_back(*I); 168461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 168561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 16863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, 16875f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<BugReport *> &bugReports) { 16881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 168940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek assert(!bugReports.empty()); 16905f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<const ExplodedNode *, 10> errorNodes; 16915f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVectorImpl<BugReport*>::iterator I = bugReports.begin(), 169240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek E = bugReports.end(); I != E; ++I) { 169340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek errorNodes.push_back((*I)->getErrorNode()); 169440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 16951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Construct a new graph that contains only a single path from the error 16971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // node to a root. 169838b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu const std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, 1699c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::pair<ExplodedNode*, unsigned> >& 170040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek GPair = MakeReportGraph(&getGraph(), errorNodes); 17011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the BugReport with the original location. 170340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek assert(GPair.second.second < bugReports.size()); 170440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *R = bugReports[GPair.second.second]; 17053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(R && "No original report found for sliced graph."); 17061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17076f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<ExplodedGraph> ReportGraph(GPair.first.first); 17086f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<NodeBackMap> BackMap(GPair.first.second); 1709c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode *N = GPair.second.first; 17101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Start building the path diagnostic... 1712ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticBuilder PDB(*this, R, BackMap.get(), 1713ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie getPathDiagnosticConsumer()); 17141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17158e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Register additional node visitors. 171650bbc165b063155cc23c360deb7b865502e068e2Anna Zaks R->addVisitor(new NilReceiverBRVisitor()); 171750bbc165b063155cc23c360deb7b865502e068e2Anna Zaks R->addVisitor(new ConditionBRVisitor()); 17181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17193bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose BugReport::VisitorList visitors; 17203bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose unsigned originalReportConfigToken, finalReportConfigToken; 17213bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 17223bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // While generating diagnostics, it's possible the visitors will decide 17233bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // new symbols and regions are interesting, or add other visitors based on 17243bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // the information they find. If they do, we need to regenerate the path 17253bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // based on our new report configuration. 17263bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose do { 17273bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // Get a clean copy of all the visitors. 17283bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (BugReport::visitor_iterator I = R->visitor_begin(), 17293bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = R->visitor_end(); I != E; ++I) 17303bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose visitors.push_back((*I)->clone()); 17313bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 17323bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // Clear out the active path from any previous work. 17333bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose PD.getActivePath().clear(); 17343bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose originalReportConfigToken = R->getConfigurationChangeToken(); 17353bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 17363bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // Generate the very last diagnostic piece - the piece is visible before 17373bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // the trace is expanded. 17383bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose PathDiagnosticPiece *LastPiece = 0; 17393bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end(); 17403bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose I != E; ++I) { 17413bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) { 17423bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose assert (!LastPiece && 17433bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose "There can only be one final piece in a diagnostic."); 17443bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose LastPiece = Piece; 17453bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose } 174623f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks } 17473bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose if (!LastPiece) 17483bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R); 17493bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose if (LastPiece) 17503bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose PD.getActivePath().push_back(LastPiece); 17513bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose else 17523bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose return; 175323f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks 17543bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose switch (PDB.getGenerationScheme()) { 1755ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie case PathDiagnosticConsumer::Extensive: 17563bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose GenerateExtensivePathDiagnostic(PD, PDB, N, visitors); 17575fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek break; 1758ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie case PathDiagnosticConsumer::Minimal: 17593bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose GenerateMinimalPathDiagnostic(PD, PDB, N, visitors); 17603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 17613bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose } 17623bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 17633bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // Clean up the visitors we used. 17643bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose llvm::DeleteContainerPointers(visitors); 17653bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 17663bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // Did anything change while generating this path? 17673bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose finalReportConfigToken = R->getConfigurationChangeToken(); 17683bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose } while(finalReportConfigToken != originalReportConfigToken); 17693bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 1770c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek // Finally, prune the diagnostic path of uninteresting stuff. 1771c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek bool hasSomethingInteresting = RemoveUneededCalls(PD.getMutablePieces()); 1772c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek assert(hasSomethingInteresting); 1773c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek (void) hasSomethingInteresting; 17743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 17751aa44c7c9198796085b77c6bdd7c90030845a688Ted Kremenek 1776cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::Register(BugType *BT) { 17773baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.add(BugTypes, BT); 177876d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek} 177976d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek 17801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid BugReporter::EmitReport(BugReport* R) { 1781cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // Compute the bug report's hash to determine its equivalence class. 1782cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek llvm::FoldingSetNodeID ID; 1783cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek R->Profile(ID); 17841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Lookup the equivance class. If there isn't one, create it. 1786cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek BugType& BT = R->getBugType(); 1787cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek Register(&BT); 1788cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek void *InsertPos; 1789404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos); 17901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1791cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek if (!EQ) { 1792cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ = new BugReportEquivClass(R); 1793404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis EQClasses.InsertNode(EQ, InsertPos); 17943b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks EQClassesVector.push_back(EQ); 1795cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek } 1796cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek else 1797cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ->AddReport(R); 179861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 179961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 180006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 180106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 180206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek// Emitting reports in equivalence classes. 180306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 180406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 180506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremeneknamespace { 1806ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamstruct FRIEC_WLItem { 180706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *N; 180806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek ExplodedNode::const_succ_iterator I, E; 180906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 181006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek FRIEC_WLItem(const ExplodedNode *n) 181106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek : N(n), I(N->succ_begin()), E(N->succ_end()) {} 181206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek}; 181306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek} 181406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 181561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenekstatic BugReport * 181661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted KremenekFindReportInEquivalenceClass(BugReportEquivClass& EQ, 18175f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<BugReport*> &bugReports) { 181861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 181906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end(); 182006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(I != E); 18214a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer BugType& BT = I->getBugType(); 182261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 182340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // If we don't need to suppress any of the nodes because they are 182440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // post-dominated by a sink, simply add all the nodes in the equivalence class 182540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // to 'Nodes'. Any of the reports will serve as a "representative" report. 182661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!BT.isSuppressOnSink()) { 18274a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer BugReport *R = I; 182861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) { 18299c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N = I->getErrorNode(); 183061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (N) { 18314a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer R = I; 183240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek bugReports.push_back(R); 183361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 183461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 183506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek return R; 183661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 183761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 183806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // For bug reports that should be suppressed when all paths are post-dominated 183906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // by a sink node, iterate through the reports in the equivalence class 184006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // until we find one that isn't post-dominated (if one exists). We use a 184106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // DFS traversal of the ExplodedGraph to find a non-sink node. We could write 184206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // this as a recursive function, but we don't want to risk blowing out the 184306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // stack for very long paths. 184440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = 0; 184561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 184606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; I != E; ++I) { 18474a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer const ExplodedNode *errorNode = I->getErrorNode(); 184806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 184940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!errorNode) 185006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 185140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->isSink()) { 1852b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable( 185306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek "BugType::isSuppressSink() should not be 'true' for sink end nodes"); 185406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 185561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // No successors? By definition this nodes isn't post-dominated by a sink. 185640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->succ_empty()) { 18574a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer bugReports.push_back(I); 185840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 18594a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer exampleReport = I; 186061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek continue; 186161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 186261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 186306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // At this point we know that 'N' is not a sink and it has at least one 186406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // successor. Use a DFS worklist to find a non-sink end-of-path node. 186506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek typedef FRIEC_WLItem WLItem; 18665f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<WLItem, 10> DFSWorkList; 186706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek llvm::DenseMap<const ExplodedNode *, unsigned> Visited; 186806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 186906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek DFSWorkList WL; 187040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek WL.push_back(errorNode); 187140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek Visited[errorNode] = 1; 187206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 187306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek while (!WL.empty()) { 187406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WLItem &WI = WL.back(); 187506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(!WI.N->succ_empty()); 187606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 187706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; WI.I != WI.E; ++WI.I) { 187806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *Succ = *WI.I; 187906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // End-of-path node? 188006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (Succ->succ_empty()) { 188161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // If we found an end-of-path node that is not a sink. 188261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!Succ->isSink()) { 18834a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer bugReports.push_back(I); 188440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 18854a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer exampleReport = I; 188661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek WL.clear(); 188761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek break; 188861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 188906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Found a sink? Continue on to the next successor. 189006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 189106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 189206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Mark the successor as visited. If it hasn't been explored, 189306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // enqueue it to the DFS worklist. 189406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek unsigned &mark = Visited[Succ]; 189506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (!mark) { 189606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek mark = 1; 189706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.push_back(Succ); 189806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek break; 189906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 190006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 190161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 190261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // The worklist may have been cleared at this point. First 190361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // check if it is empty before checking the last item. 190461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!WL.empty() && &WL.back() == &WI) 190506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.pop_back(); 190606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 190706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 190806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 190961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // ExampleReport will be NULL if all the nodes in the equivalence class 191061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // were post-dominated by sinks. 191140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek return exampleReport; 191261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek} 1913e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1914e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek//===----------------------------------------------------------------------===// 1915e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek// DiagnosticCache. This is a hack to cache analyzer diagnostics. It 1916e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek// uses global state, which eventually should go elsewhere. 1917e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek//===----------------------------------------------------------------------===// 1918e0a58073b76fc016325a35152533b8468df2bf4aTed Kremeneknamespace { 1919ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass DiagCacheItem : public llvm::FoldingSetNode { 1920e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek llvm::FoldingSetNodeID ID; 1921e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenekpublic: 1922e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek DiagCacheItem(BugReport *R, PathDiagnostic *PD) { 19234522e2a9e7fa0313e8e5a388d8f0ab66feccc6afAnna Zaks R->Profile(ID); 19244522e2a9e7fa0313e8e5a388d8f0ab66feccc6afAnna Zaks PD->Profile(ID); 1925e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek } 1926e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1927e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek void Profile(llvm::FoldingSetNodeID &id) { 1928e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek id = ID; 1929e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek } 1930e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1931e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek llvm::FoldingSetNodeID &getID() { return ID; } 1932e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek}; 1933e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek} 1934e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1935e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenekstatic bool IsCachedDiagnostic(BugReport *R, PathDiagnostic *PD) { 1936e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek // FIXME: Eventually this diagnostic cache should reside in something 1937e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek // like AnalysisManager instead of being a static variable. This is 1938e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek // really unsafe in the long term. 1939e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek typedef llvm::FoldingSet<DiagCacheItem> DiagnosticCache; 1940e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek static DiagnosticCache DC; 1941e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1942e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek void *InsertPos; 1943e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek DiagCacheItem *Item = new DiagCacheItem(R, PD); 1944e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1945e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek if (DC.FindNodeOrInsertPos(Item->getID(), InsertPos)) { 1946e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek delete Item; 1947e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek return true; 1948e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek } 1949e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1950e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek DC.InsertNode(Item, InsertPos); 1951e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek return false; 1952e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek} 1953e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1954cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::FlushReport(BugReportEquivClass& EQ) { 19555f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BugReport*, 10> bugReports; 195640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports); 195740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 195806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek return; 195906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 1960ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer* PD = getPathDiagnosticConsumer(); 19611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1962cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // FIXME: Make sure we use the 'R' for the path that was actually used. 19631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Probably doesn't make a difference in practice. 196440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugType& BT = exampleReport->getBugType(); 19651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19666f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<PathDiagnostic> 196707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek D(new PathDiagnostic(exampleReport->getDeclWithIssue(), 196807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek exampleReport->getBugType().getName(), 1969da0e8429a3598acfdd0ecf15135d432e4dd3517cTed Kremenek !PD || PD->useVerboseDescription() 197040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek ? exampleReport->getDescription() 197140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek : exampleReport->getShortDescription(), 1972d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek BT.getCategory())); 1973d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek 197440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!bugReports.empty()) 197540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek GeneratePathDiagnostic(*D.get(), bugReports); 1976e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1977072192bcbb05a0fee7ec3061750b27e8d2004952Ted Kremenek // Get the meta data. 19787f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks const BugReport::ExtraTextList &Meta = 19797f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks exampleReport->getExtraText(); 19807f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks for (BugReport::ExtraTextList::const_iterator i = Meta.begin(), 19817f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks e = Meta.end(); i != e; ++i) { 19827f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks D->addMeta(*i); 19837f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks } 198475840e1501563fe7c3dcb5600b75965ba1fe1bc4Ted Kremenek 19853148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek // Emit a summary diagnostic to the regular Diagnostics engine. 1986640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis BugReport::ranges_iterator Beg, End; 1987640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis llvm::tie(Beg, End) = exampleReport->getRanges(); 1988d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &Diag = getDiagnostic(); 1989c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek 199088fc18120ca14b82bef695d6440f51e4c468916cTed Kremenek if (!IsCachedDiagnostic(exampleReport, D.get())) { 199188fc18120ca14b82bef695d6440f51e4c468916cTed Kremenek // Search the description for '%', as that will be interpretted as a 199288fc18120ca14b82bef695d6440f51e4c468916cTed Kremenek // format character by FormatDiagnostics. 199388fc18120ca14b82bef695d6440f51e4c468916cTed Kremenek StringRef desc = exampleReport->getShortDescription(); 199488fc18120ca14b82bef695d6440f51e4c468916cTed Kremenek 1995f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<512> TmpStr; 1996c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek llvm::raw_svector_ostream Out(TmpStr); 199788fc18120ca14b82bef695d6440f51e4c468916cTed Kremenek for (StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I) { 1998c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek if (*I == '%') 1999c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek Out << "%%"; 2000c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek else 2001c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek Out << *I; 200288fc18120ca14b82bef695d6440f51e4c468916cTed Kremenek } 2003c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek 2004c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek Out.flush(); 200588fc18120ca14b82bef695d6440f51e4c468916cTed Kremenek unsigned ErrorDiag = Diag.getCustomDiagID(DiagnosticsEngine::Warning, TmpStr); 20060a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner 2007590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks DiagnosticBuilder diagBuilder = Diag.Report( 2008590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks exampleReport->getLocation(getSourceManager()).asLocation(), ErrorDiag); 2009640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis for (BugReport::ranges_iterator I = Beg; I != End; ++I) 2010b6b7e7bff3101062521de6e79533a3c25e2195d9Argyrios Kyrtzidis diagBuilder << *I; 20112f0e89ea96292d2974eb1a7dddc0e9870aa86bb7Ted Kremenek } 20123148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek 2013ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie // Emit a full diagnostic for the path if we have a PathDiagnosticConsumer. 20143148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek if (!PD) 20153148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek return; 20161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2017802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek if (D->path.empty()) { 2018590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticPiece *piece = new PathDiagnosticEventPiece( 2019590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks exampleReport->getLocation(getSourceManager()), 2020590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks exampleReport->getDescription()); 202107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek for ( ; Beg != End; ++Beg) 202207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek piece->addRange(*Beg); 20231fbfd5b9b8b82aea084773b76dd1ec6796a7000cTed Kremenek 20242042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek D->getActivePath().push_back(piece); 20253148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek } 20261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20273148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek PD->HandlePathDiagnostic(D.take()); 202861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 202957202071e477530e9348bc76671ee369b2399b92Ted Kremenek 203007189521a15d9c088216b943649cb9fe231cbb57Ted Kremenekvoid BugReporter::EmitBasicReport(const Decl *DeclWithIssue, 203107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek StringRef name, 20325f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category, 2033590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks StringRef str, PathDiagnosticLocation Loc, 20348c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek SourceRange* RBeg, unsigned NumRanges) { 20351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2036404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // 'BT' is owned by BugReporter. 2037404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = getBugTypeForName(name, category); 2038590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks BugReport *R = new BugReport(*BT, str, Loc); 203907189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek R->setDeclWithIssue(DeclWithIssue); 2040cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg); 2041cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EmitReport(R); 2042cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek} 2043404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 20445f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerBugType *BugReporter::getBugTypeForName(StringRef name, 20455f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category) { 2046f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<136> fullDesc; 2047404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::raw_svector_ostream(fullDesc) << name << ":" << category; 2048404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::StringMapEntry<BugType *> & 2049404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry = StrBugTypes.GetOrCreateValue(fullDesc); 2050404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = entry.getValue(); 2051404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis if (!BT) { 2052404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BT = new BugType(name, category); 2053404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry.setValue(BT); 2054404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis } 2055404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis return BT; 2056404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis} 2057