BugReporter.cpp revision 56ca35d396d8692c384c785f9aeebcf22563fe1e
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" 2061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/AST/Expr.h" 2100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek#include "clang/AST/ParentMap.h" 2216f0049415ec596504891259e2a83e19871c0d52Chris Lattner#include "clang/AST/StmtObjC.h" 2316f0049415ec596504891259e2a83e19871c0d52Chris Lattner#include "clang/Basic/SourceManager.h" 2461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/Analysis/ProgramPoint.h" 259b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 26405674c26c52b05df0d833fae6bae818cd52bc32Chris Lattner#include "llvm/Support/raw_ostream.h" 27331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek#include "llvm/ADT/DenseMap.h" 28cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek#include "llvm/ADT/STLExtras.h" 2900605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek#include "llvm/ADT/OwningPtr.h" 3010aa55410bbecbb658ce14a5f801d50cf06d12dfTed Kremenek#include <queue> 3161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 3261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenekusing namespace clang; 339ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 3461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 358966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed KremenekBugReporterVisitor::~BugReporterVisitor() {} 368966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed KremenekBugReporterContext::~BugReporterContext() { 378966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) 388966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek if ((*I)->isOwnedByReporterContext()) delete *I; 398966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek} 408966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek 411b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenekvoid BugReporterContext::addVisitor(BugReporterVisitor* visitor) { 421b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek if (!visitor) 431b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek return; 441b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek 451b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek llvm::FoldingSetNodeID ID; 461b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek visitor->Profile(ID); 471b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek void *InsertPos; 481b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek 493e0e41c9bba167437072c47a140d51509ebeb73cTed Kremenek if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) { 503e0e41c9bba167437072c47a140d51509ebeb73cTed Kremenek delete visitor; 511b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek return; 523e0e41c9bba167437072c47a140d51509ebeb73cTed Kremenek } 531b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek 541b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek CallbacksSet.InsertNode(visitor, InsertPos); 553baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek Callbacks = F.add(visitor, Callbacks); 561b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek} 571b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek 58cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Helper routines for walking the ExplodedGraph and fetching statements. 60cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 6161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 627f330856b8d5df764f1c91218471c47af9ae2aa5Zhongxing Xustatic inline const Stmt* GetStmt(const ProgramPoint &P) { 63592362b46ad69db0db0988e7f9d8cbe647510bddTed Kremenek if (const StmtPoint* SP = dyn_cast<StmtPoint>(&P)) 64592362b46ad69db0db0988e7f9d8cbe647510bddTed Kremenek return SP->getStmt(); 65b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek else if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) 6661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek return BE->getSrc()->getTerminator(); 671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 68b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return 0; 6961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 7061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 71c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic inline const ExplodedNode* 72c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing XuGetPredecessorNode(const ExplodedNode* N) { 73b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return N->pred_empty() ? NULL : *(N->pred_begin()); 74706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek} 75706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek 76c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic inline const ExplodedNode* 77c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing XuGetSuccessorNode(const ExplodedNode* N) { 78b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return N->succ_empty() ? NULL : *(N->succ_begin()); 79bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek} 802673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek 81c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic const Stmt* GetPreviousStmt(const ExplodedNode* N) { 82b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek for (N = GetPredecessorNode(N); N; N = GetPredecessorNode(N)) 835f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) 84b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 86b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return 0; 87b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek} 88b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek 89c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic const Stmt* GetNextStmt(const ExplodedNode* N) { 90b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek for (N = GetSuccessorNode(N); N; N = GetSuccessorNode(N)) 915f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) { 92f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek // Check if the statement is '?' or '&&'/'||'. These are "merges", 93f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek // not actual statement points. 94f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek switch (S->getStmtClass()) { 95f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek case Stmt::ChooseExprClass: 9656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: continue; 97f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek case Stmt::ConditionalOperatorClass: continue; 98f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek case Stmt::BinaryOperatorClass: { 992de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode(); 1002de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (Op == BO_LAnd || Op == BO_LOr) 101f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek continue; 102f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek break; 103f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 104f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek default: 105f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek break; 106f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 1071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 108b7c515226e91848c7197fd0b9e198fce70ba5893Ted Kremenek // Some expressions don't have locations. 109b7c515226e91848c7197fd0b9e198fce70ba5893Ted Kremenek if (S->getLocStart().isInvalid()) 110b7c515226e91848c7197fd0b9e198fce70ba5893Ted Kremenek continue; 1111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 112b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 113f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 1141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 115b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return 0; 116bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek} 117bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek 1185f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt* 1191eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpGetCurrentOrPreviousStmt(const ExplodedNode* N) { 1205f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) 121b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 1221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 123b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return GetPreviousStmt(N); 124b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek} 1251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1265f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt* 1271eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpGetCurrentOrNextStmt(const ExplodedNode* N) { 1285f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) 129b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 1301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 131b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return GetNextStmt(N); 1323148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek} 1333148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek 134b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 1353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnosticBuilder and its associated routines and helper objects. 136b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 137b479dadea93b93d3f0a335c3518b703f140b3f50Ted Kremenek 138c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xutypedef llvm::DenseMap<const ExplodedNode*, 139c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuconst ExplodedNode*> NodeBackMap; 1407dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek 141babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremeneknamespace { 142ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NodeMapClosure : public BugReport::NodeResolver { 1437dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeBackMap& M; 1447dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenekpublic: 1457dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeMapClosure(NodeBackMap *m) : M(*m) {} 1467dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek ~NodeMapClosure() {} 1471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 148c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode* getOriginalNode(const ExplodedNode* N) { 1497dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeBackMap::iterator I = M.find(N); 1507dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek return I == M.end() ? 0 : I->second; 1517dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 1527dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek}; 1531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 154ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass PathDiagnosticBuilder : public BugReporterContext { 1557dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek BugReport *R; 156babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek PathDiagnosticClient *PDC; 15700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek llvm::OwningPtr<ParentMap> PM; 1587dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeMapClosure NMC; 1591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic: 1608966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek PathDiagnosticBuilder(GRBugReporter &br, 1611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump BugReport *r, NodeBackMap *Backmap, 1628966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek PathDiagnosticClient *pdc) 1638966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek : BugReporterContext(br), 1641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump R(r), PDC(pdc), NMC(Backmap) { 1658966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek addVisitor(R); 1668966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 1671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 168c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu PathDiagnosticLocation ExecutionContinues(const ExplodedNode* N); 1691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17000605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream& os, 171c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode* N); 1721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 173212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); } 174b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu 175212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care ParentMap& getParentMap() { return R->getErrorNode()->getParentMap(); } 1761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 177c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek const Stmt *getParent(const Stmt *S) { 178c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek return getParentMap().getParent(S); 179c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek } 1801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1818966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek virtual NodeMapClosure& getNodeResolver() { return NMC; } 1827297134f128423fce2e88f92421ed135bded7d4eDouglas Gregor 183d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S); 1841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1857dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek PathDiagnosticClient::PathGenerationScheme getGenerationScheme() const { 1867dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek return PDC ? PDC->getGenerationScheme() : PathDiagnosticClient::Extensive; 1877dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 1887dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek 189babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek bool supportsLogicalOpControlFlow() const { 190babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek return PDC ? PDC->supportsLogicalOpControlFlow() : true; 1911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 192babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek}; 193babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek} // end anonymous namespace 194babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 19500605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 196c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing XuPathDiagnosticBuilder::ExecutionContinues(const ExplodedNode* N) { 1975f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetNextStmt(N)) 1988966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek return PathDiagnosticLocation(S, getSourceManager()); 19900605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek 2001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return FullSourceLoc(N->getLocationContext()->getDecl()->getBodyRBrace(), 201f7a50a4ee255b3a624ae64125537a7bdbd1da0efZhongxing Xu getSourceManager()); 202082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek} 2031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20400605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 205babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed KremenekPathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream& os, 206c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode* N) { 207babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 208143ca222583a4a355fdc89af852deef287499300Ted Kremenek // Slow, but probably doesn't matter. 209b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek if (os.str().empty()) 210b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << ' '; 2111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek const PathDiagnosticLocation &Loc = ExecutionContinues(N); 2131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21400605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek if (Loc.asStmt()) 215b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << "Execution continues on line " 2168966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek << getSourceManager().getInstantiationLineNumber(Loc.asLocation()) 2178966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek << '.'; 2184f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 2194f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "Execution jumps to the end of the "; 2204f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek const Decl *D = N->getLocationContext()->getDecl(); 2214f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek if (isa<ObjCMethodDecl>(D)) 2224f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "method"; 2234f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else if (isa<FunctionDecl>(D)) 2244f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "function"; 2254f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 2264f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek assert(isa<BlockDecl>(D)); 2274f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "anonymous block"; 2284f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 2294f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << '.'; 2304f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 2311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 232082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek return Loc; 233143ca222583a4a355fdc89af852deef287499300Ted Kremenek} 234143ca222583a4a355fdc89af852deef287499300Ted Kremenek 235ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenekstatic bool IsNested(const Stmt *S, ParentMap &PM) { 236ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S))) 237ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek return true; 2381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 239ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const Stmt *Parent = PM.getParentIgnoreParens(S); 2401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 241ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (Parent) 242ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek switch (Parent->getStmtClass()) { 243ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::ForStmtClass: 244ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::DoStmtClass: 245ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::WhileStmtClass: 246ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek return true; 247ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek default: 248ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek break; 249ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek } 2501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 252ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek} 253ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek 254d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticLocation 255d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { 256d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek assert(S && "Null Stmt* passed to getEnclosingStmtLocation"); 2571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ParentMap &P = getParentMap(); 2588966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek SourceManager &SMgr = getSourceManager(); 259e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 260ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek while (IsNested(S, P)) { 2618c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const Stmt *Parent = P.getParentIgnoreParens(S); 2621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 263af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (!Parent) 264af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 2651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 266af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek switch (Parent->getStmtClass()) { 2675fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek case Stmt::BinaryOperatorClass: { 2685fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const BinaryOperator *B = cast<BinaryOperator>(Parent); 2695fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 2705fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return PathDiagnosticLocation(S, SMgr); 2715fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek break; 2721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 273af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::CompoundStmtClass: 274af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::StmtExprClass: 2751d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek return PathDiagnosticLocation(S, SMgr); 2761d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ChooseExprClass: 2771d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // Similar to '?' if we are referring to condition, just have the edge 2781d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // point to the entire choose expression. 2791d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (cast<ChooseExpr>(Parent)->getCond() == S) 2801d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek return PathDiagnosticLocation(Parent, SMgr); 2811d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 2821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return PathDiagnosticLocation(S, SMgr); 28356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 2841d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ConditionalOperatorClass: 2851d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // For '?', if we are referring to condition, just have the edge point 2861d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // to the entire '?' expression. 28756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (cast<AbstractConditionalOperator>(Parent)->getCond() == S) 2881d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek return PathDiagnosticLocation(Parent, SMgr); 2891d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 2901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return PathDiagnosticLocation(S, SMgr); 291af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::DoStmtClass: 2921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return PathDiagnosticLocation(S, SMgr); 293af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ForStmtClass: 294af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ForStmt>(Parent)->getBody() == S) 2951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return PathDiagnosticLocation(S, SMgr); 2961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump break; 297af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::IfStmtClass: 298af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<IfStmt>(Parent)->getCond() != S) 299af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek return PathDiagnosticLocation(S, SMgr); 3008bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek break; 301af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 302af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S) 303af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek return PathDiagnosticLocation(S, SMgr); 304af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 305af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::WhileStmtClass: 306af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<WhileStmt>(Parent)->getCond() != S) 307af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek return PathDiagnosticLocation(S, SMgr); 308af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 309af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek default: 310af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 311af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek } 312af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek 313d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek S = Parent; 314d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek } 3151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 316d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek assert(S && "Cannot have null Stmt for PathDiagnosticLocation"); 317e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 318e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // Special case: DeclStmts can appear in for statement declarations, in which 319e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // case the ForStmt is the context. 320e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (isa<DeclStmt>(S)) { 321e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (const Stmt *Parent = P.getParent(S)) { 322e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek switch (Parent->getStmtClass()) { 323e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek case Stmt::ForStmtClass: 324e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 325e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek return PathDiagnosticLocation(Parent, SMgr); 326e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek default: 327e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek break; 3281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 3291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 330e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 331e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek else if (isa<BinaryOperator>(S)) { 332e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // Special case: the binary operator represents the initialization 333e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // code in a for statement (this can happen when the variable being 334e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // initialized is an old variable. 335e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (const ForStmt *FS = 336e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek dyn_cast_or_null<ForStmt>(P.getParentIgnoreParens(S))) { 337e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (FS->getInit() == S) 338e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek return PathDiagnosticLocation(FS, SMgr); 339e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 340e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 341e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 342d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek return PathDiagnosticLocation(S, SMgr); 343d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek} 344d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 345cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 3463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// ScanNotableSymbols: closure-like callback for scanning Store bindings. 347cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 348cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 3493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekstatic const VarDecl* 350c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing XuGetMostRecentVarDeclBinding(const ExplodedNode* N, 3513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek GRStateManager& VMgr, SVal X) { 3521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for ( ; N ; N = N->pred_empty() ? 0 : *N->pred_begin()) { 3541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek ProgramPoint P = N->getLocation(); 3561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!isa<PostStmt>(P)) 3583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 3591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3605f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek const DeclRefExpr* DR = dyn_cast<DeclRefExpr>(cast<PostStmt>(P).getStmt()); 3611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!DR) 3633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 3641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3651397663af9dbcc24dbf0e11de43931b3dc08fdbbTed Kremenek SVal Y = N->getState()->getSVal(DR); 3661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (X != Y) 3683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 3691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3705f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek const VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()); 3711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!VD) 3733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 3741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return VD; 376cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek } 3771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return 0; 379bb77e9b908658b354b058509d3801f3aed052becTed Kremenek} 380bb77e9b908658b354b058509d3801f3aed052becTed Kremenek 3813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremeneknamespace { 382ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NotableSymbolHandler 3833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek: public StoreManager::BindingsHandler { 3841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SymbolRef Sym; 3863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const GRState* PrevSt; 3873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const Stmt* S; 3883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek GRStateManager& VMgr; 389c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode* Pred; 3901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump PathDiagnostic& PD; 3913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek BugReporter& BR; 3921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekpublic: 3941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NotableSymbolHandler(SymbolRef sym, const GRState* prevst, const Stmt* s, 396c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu GRStateManager& vmgr, const ExplodedNode* pred, 3973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnostic& pd, BugReporter& br) 3983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek : Sym(sym), PrevSt(prevst), S(s), VMgr(vmgr), Pred(pred), PD(pd), BR(br) {} 3991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, 4013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SVal V) { 4021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SymbolRef ScanSym = V.getAsSymbol(); 4041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (ScanSym != Sym) 4063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Check if the previous state has this binding. 4091397663af9dbcc24dbf0e11de43931b3dc08fdbbTed Kremenek SVal X = PrevSt->getSVal(loc::MemRegionVal(R)); 4101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (X == V) // Same binding? 4123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Different binding. Only handle assignments for now. We don't pull 4151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // this check out of the loop because we will eventually handle other 4163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // cases. 4171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek VarDecl *VD = 0; 4191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { 4213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!B->isAssignmentOp()) 4223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // What variable did we assign to? 4253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenCasts()); 4261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!DR) 4283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek VD = dyn_cast<VarDecl>(DR->getDecl()); 4313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 4323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else if (const DeclStmt* DS = dyn_cast<DeclStmt>(S)) { 4333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // FIXME: Eventually CFGs won't have DeclStmts. Right now we 4343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // assume that each DeclStmt has a single Decl. This invariant 4353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // holds by contruction in the CFG. 4363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek VD = dyn_cast<VarDecl>(*DS->decl_begin()); 4373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 4381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!VD) 4403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // What is the most recently referenced variable with this binding? 4433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const VarDecl* MostRecent = GetMostRecentVarDeclBinding(Pred, VMgr, V); 4441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MostRecent) 4463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the diagnostic. 4493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek FullSourceLoc L(S->getLocStart(), BR.getSourceManager()); 4501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4517dfc9420babe83e236a47e752f8723bd06070d9dZhanyong Wan if (Loc::isLocType(VD->getType())) { 4523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::string msg = "'" + std::string(VD->getNameAsString()) + 4533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek "' now aliases '" + MostRecent->getNameAsString() + "'"; 4541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PD.push_front(new PathDiagnosticEventPiece(L, msg)); 4563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 4571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 4603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}; 4613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 4623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 463c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic void HandleNotableSymbol(const ExplodedNode* N, 4643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const Stmt* S, 4653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SymbolRef Sym, BugReporter& BR, 4663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnostic& PD) { 4671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 468c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode* Pred = N->pred_empty() ? 0 : *N->pred_begin(); 4693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const GRState* PrevSt = Pred ? Pred->getState() : 0; 4701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!PrevSt) 4723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return; 4731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Look at the region bindings of the current state that map to the 4753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // specified symbol. Are any of them not in the previous state? 4763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek GRStateManager& VMgr = cast<GRBugReporter>(BR).getStateManager(); 4773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NotableSymbolHandler H(Sym, PrevSt, S, VMgr, Pred, PD, BR); 4783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek cast<GRBugReporter>(BR).getStateManager().iterBindings(N->getState(), H); 47961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 48061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 4813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremeneknamespace { 482ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ScanNotableSymbols 4833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek: public StoreManager::BindingsHandler { 4841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::SmallSet<SymbolRef, 10> AlreadyProcessed; 486c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode* N; 4875f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek const Stmt* S; 4883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek GRBugReporter& BR; 4893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnostic& PD; 4901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekpublic: 492c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ScanNotableSymbols(const ExplodedNode* n, const Stmt* s, 4935f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek GRBugReporter& br, PathDiagnostic& pd) 4943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek : N(n), S(s), BR(br), PD(pd) {} 4951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek bool HandleBinding(StoreManager& SMgr, Store store, 4973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const MemRegion* R, SVal V) { 4981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SymbolRef ScanSym = V.getAsSymbol(); 5001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!ScanSym) 5023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 5031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!BR.isNotable(ScanSym)) 5053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 5061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (AlreadyProcessed.count(ScanSym)) 5083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 5091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek AlreadyProcessed.insert(ScanSym); 5111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek HandleNotableSymbol(N, S, ScanSym, BR, PD); 5133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 514bb77e9b908658b354b058509d3801f3aed052becTed Kremenek } 5153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}; 5163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} // end anonymous namespace 51750a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek 518cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 5193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// "Minimal" path diagnostic generation algorithm. 520cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 521cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 52214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekstatic void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM); 52314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 5243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekstatic void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, 5253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticBuilder &PDB, 526c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode *N) { 5278966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek 5283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceManager& SMgr = PDB.getSourceManager(); 5291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const ExplodedNode* NextNode = N->pred_empty() 5303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek ? NULL : *(N->pred_begin()); 5313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (NextNode) { 5321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump N = NextNode; 5333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NextNode = GetPredecessorNode(N); 5341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 53561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek ProgramPoint P = N->getLocation(); 5361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 53761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) { 53803509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const CFGBlock* Src = BE->getSrc(); 53903509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const CFGBlock* Dst = BE->getDst(); 54003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const Stmt* T = Src->getTerminator(); 5411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 54261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek if (!T) 54361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek continue; 5441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 545082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek FullSourceLoc Start(T->getLocStart(), SMgr); 5461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 54761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek switch (T->getStmtClass()) { 54861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek default: 54961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 5501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 55161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek case Stmt::GotoStmtClass: 5521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::IndirectGotoStmtClass: { 5535f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek const Stmt* S = GetNextStmt(N); 5541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 55561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek if (!S) 55661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek continue; 5571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 558297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 5591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::raw_string_ostream os(sbuf); 560d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S); 5611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 56200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os << "Control jumps to line " 5633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek << End.asLocation().getInstantiationLineNumber(); 564082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 565082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os.str())); 56661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 56761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 5681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::SwitchStmtClass: { 57061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek // Figure out what case arm we took. 571297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 572297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 5731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 57403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu if (const Stmt* S = Dst->getLabel()) { 57500605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End(S, SMgr); 5761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5775a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek switch (S->getStmtClass()) { 578082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek default: 579082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "No cases match in the switch statement. " 5803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek "Control jumps to line " 5813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek << End.asLocation().getInstantiationLineNumber(); 582082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek break; 583082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek case Stmt::DefaultStmtClass: 584082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "Control jumps to the 'default' case at line " 5853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek << End.asLocation().getInstantiationLineNumber(); 586082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek break; 5871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 588082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek case Stmt::CaseStmtClass: { 5891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump os << "Control jumps to 'case "; 59003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const CaseStmt* Case = cast<CaseStmt>(S); 59103509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const Expr* LHS = Case->getLHS()->IgnoreParenCasts(); 5921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Determine if it is an enum. 594082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek bool GetRawInt = true; 5951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 59603509aea098772644bf4662dc1c88634818ceeccZhongxing Xu if (const DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) { 597082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek // FIXME: Maybe this should be an assertion. Are there cases 598082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek // were it is not an EnumConstantDecl? 59903509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const EnumConstantDecl* D = 60003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu dyn_cast<EnumConstantDecl>(DR->getDecl()); 6011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 602082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek if (D) { 603082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek GetRawInt = false; 604900fc6388e803868a34b9483510c345e9b49d7ebBenjamin Kramer os << D; 605082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 6065a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek } 6079ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 6089ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman if (GetRawInt) 6098966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek os << LHS->EvaluateAsInt(PDB.getASTContext()); 6109ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 61100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os << ":' at line " 6123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek << End.asLocation().getInstantiationLineNumber(); 613082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek break; 614082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 61561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 61600605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 61700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os.str())); 61861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 619567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek else { 620c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "'Default' branch taken. "; 6211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N); 62200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 62300605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os.str())); 624567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek } 6251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 62661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 62761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 6281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6292673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::BreakStmtClass: 6302673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::ContinueStmtClass: { 631297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 632297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 63300605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 634082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 635082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os.str())); 6362673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek break; 6372673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek } 6381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine control-flow for ternary '?'. 64056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 641706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek case Stmt::ConditionalOperatorClass: { 642297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 643297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 6441d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek os << "'?' condition is "; 6451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 646706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()+1) == Dst) 647082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "false"; 648706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek else 649082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "true"; 6501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 65100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 6521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6531d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (const Stmt *S = End.asStmt()) 6541d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 6551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 656babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 657babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek os.str())); 658babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 659babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 6601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine control-flow for short-circuited '&&' and '||'. 662babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek case Stmt::BinaryOperatorClass: { 663babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek if (!PDB.supportsLogicalOpControlFlow()) 664babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 6651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 66603509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const BinaryOperator *B = cast<BinaryOperator>(T); 667babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek std::string sbuf; 668babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek llvm::raw_string_ostream os(sbuf); 669babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek os << "Left side of '"; 6701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6712de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_LAnd) { 672f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "&&" << "' is "; 6731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 674f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 675f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 676f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End(B->getLHS(), SMgr); 677f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation Start(B->getOperatorLoc(), SMgr); 678f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 679f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os.str())); 6801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 681f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 682f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 683f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation Start(B->getLHS(), SMgr); 684f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 685f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 686f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os.str())); 6871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 688babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 689babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek else { 6902de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(B->getOpcode() == BO_LOr); 691f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "||" << "' is "; 6921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 693f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 694f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 695f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation Start(B->getLHS(), SMgr); 696f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 697f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 6981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump os.str())); 699f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 700f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 701f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 702f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End(B->getLHS(), SMgr); 703f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation Start(B->getOperatorLoc(), SMgr); 704f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 7051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump os.str())); 706f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 707babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 7081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 709706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek break; 710706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek } 7111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::DoStmtClass: { 713706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()) == Dst) { 714297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 715297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 7161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 717c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "Loop condition is true. "; 718d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 7191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 720d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 721d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 7221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 723082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 724082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os.str())); 725082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 726082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek else { 72700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 729d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 730d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 7311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 7333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek "Loop condition is false. Exiting loop")); 7343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 7373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::WhileStmtClass: 7401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::ForStmtClass: { 7413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) { 7423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::string sbuf; 7433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::raw_string_ostream os(sbuf); 7441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek os << "Loop condition is false. "; 7463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 7473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 7483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 7491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 7513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek os.str())); 7523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 7543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 7563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 7571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 7595fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek "Loop condition is true. Entering loop body")); 7603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 7633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::IfStmtClass: { 7663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 7693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 7701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) 7723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 7735fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek "Taking false branch")); 7741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else 7753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 7765fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek "Taking true branch")); 7771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 7793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 783dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (NextNode) { 784dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek for (BugReporterContext::visitor_iterator I = PDB.visitor_begin(), 785dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek E = PDB.visitor_end(); I!=E; ++I) { 786dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (PathDiagnosticPiece* p = (*I)->VisitNode(N, NextNode, PDB)) 787dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek PD.push_front(p); 788dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 7898966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 7901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) { 7923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Scan the region bindings, and see if a "notable" symbol has a new 7933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // lval binding. 7943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek ScanNotableSymbols SNS(N, PS->getStmt(), PDB.getBugReporter(), PD); 7953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PDB.getStateManager().iterBindings(N->getState(), SNS); 7963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 79914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // After constructing the full PathDiagnostic, do a pass over it to compact 80014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // PathDiagnosticPieces that occur within a macro. 80114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CompactPathDiagnostic(PD, PDB.getSourceManager()); 8023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 8033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 8043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 8055fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek// "Extensive" PathDiagnostic generation. 8065fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 8075fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 8085fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenekstatic bool IsControlFlowExpr(const Stmt *S) { 8095fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const Expr *E = dyn_cast<Expr>(S); 8101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8115fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (!E) 8125fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return false; 8131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump E = E->IgnoreParenCasts(); 8151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 81656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (isa<AbstractConditionalOperator>(E)) 8175fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 8181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8195fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) 8205fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 8215fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 8221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 8245fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek} 8255fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 82614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremeneknamespace { 827ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ContextLocation : public PathDiagnosticLocation { 8288f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsDead; 8298f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekpublic: 8308f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation(const PathDiagnosticLocation &L, bool isdead = false) 8318f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek : PathDiagnosticLocation(L), IsDead(isdead) {} 8321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void markDead() { IsDead = true; } 8348f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool isDead() const { return IsDead; } 8358f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek}; 8361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 837ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass EdgeBuilder { 8388f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek std::vector<ContextLocation> CLocs; 8398f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek typedef std::vector<ContextLocation>::iterator iterator; 84014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnostic &PD; 84114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB; 84214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation PrevLoc; 8431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8448f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsConsumedExpr(const PathDiagnosticLocation &L); 8451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 84614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek bool containsLocation(const PathDiagnosticLocation &Container, 84714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee); 8481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 84914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L); 8501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8519650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L, 8529650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek bool firstCharOnly = false) { 8538c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (const Stmt *S = L.asStmt()) { 8549650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek const Stmt *Original = S; 8558c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek while (1) { 8568c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek // Adjust the location for some expressions that are best referenced 8578c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek // by one of their subexpressions. 8589650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek switch (S->getStmtClass()) { 8599650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek default: 8609650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek break; 8619650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ParenExprClass: 8629650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek S = cast<ParenExpr>(S)->IgnoreParens(); 8639650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 8649650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 86556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 8669650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ConditionalOperatorClass: 86756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall S = cast<AbstractConditionalOperator>(S)->getCond(); 8689650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 8699650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 8709650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ChooseExprClass: 8719650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek S = cast<ChooseExpr>(S)->getCond(); 8729650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 8739650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 8749650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::BinaryOperatorClass: 8759650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek S = cast<BinaryOperator>(S)->getLHS(); 8769650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 8779650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 8789650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek } 8791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8809650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek break; 8818c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 8821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8839650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek if (S != Original) 8849650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek L = PathDiagnosticLocation(S, L.getManager()); 8858c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 8861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8879650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek if (firstCharOnly) 8889650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek L = PathDiagnosticLocation(L.asLocation()); 8899650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek 8908c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek return L; 8918c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 8921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 89314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void popLocation() { 8948f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) { 8955c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // For contexts, we only one the first character as the range. 89607c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek rawAddEdge(cleanUpLocation(CLocs.back(), true)); 8975c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek } 89814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.pop_back(); 89914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 9001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 90114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekpublic: 90214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb) 90314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek : PD(pd), PDB(pdb) { 9041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 905a301a6773db085575ac51e3c966858180390c25bTed Kremenek // If the PathDiagnostic already has pieces, add the enclosing statement 906a301a6773db085575ac51e3c966858180390c25bTed Kremenek // of the first piece as a context as well. 90714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!PD.empty()) { 90814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PrevLoc = PD.begin()->getLocation(); 9091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 91014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = PrevLoc.asStmt()) 911e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 91214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 91314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 91414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 91514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ~EdgeBuilder() { 91614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) popLocation(); 9171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 918a301a6773db085575ac51e3c966858180390c25bTed Kremenek // Finally, add an initial edge from the start location of the first 919a301a6773db085575ac51e3c966858180390c25bTed Kremenek // statement (if it doesn't already exist). 920d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl // FIXME: Should handle CXXTryStmt if analyser starts supporting C++. 921d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl if (const CompoundStmt *CS = 9225f1bfc10a12d9759444eb433f52a85d2e0058967Argyrios Kyrtzidis dyn_cast_or_null<CompoundStmt>(PDB.getCodeDecl().getBody())) 923a301a6773db085575ac51e3c966858180390c25bTed Kremenek if (!CS->body_empty()) { 924a301a6773db085575ac51e3c966858180390c25bTed Kremenek SourceLocation Loc = (*CS->body_begin())->getLocStart(); 925a301a6773db085575ac51e3c966858180390c25bTed Kremenek rawAddEdge(PathDiagnosticLocation(Loc, PDB.getSourceManager())); 926a301a6773db085575ac51e3c966858180390c25bTed Kremenek } 9271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 92814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 92914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 93014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false); 9311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9328bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek void rawAddEdge(PathDiagnosticLocation NewLoc); 9331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 93414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addContext(const Stmt *S); 935e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek void addExtendedContext(const Stmt *S); 9361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}; 93714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} // end anonymous namespace 93814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 93914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 94014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekPathDiagnosticLocation 94114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekEdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) { 94214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = L.asStmt()) { 94314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (IsControlFlowExpr(S)) 94414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 9451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return PDB.getEnclosingStmtLocation(S); 94714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 9481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 94914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 95014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 95114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 95214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekbool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container, 95314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee) { 95414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 95514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container == Containee) 95614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 9571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 95814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container.asDecl()) 95914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 9601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 96114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = Containee.asStmt()) 96214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *ContainerS = Container.asStmt()) { 96314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (S) { 96414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (S == ContainerS) 96514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 96614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek S = PDB.getParent(S); 96714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 96814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return false; 96914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 97014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 97114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Less accurate: compare using source ranges. 97214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContainerR = Container.asRange(); 97314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContaineeR = Containee.asRange(); 9741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 97514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceManager &SM = PDB.getSourceManager(); 97614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceLocation ContainerRBeg = SM.getInstantiationLoc(ContainerR.getBegin()); 97714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceLocation ContainerREnd = SM.getInstantiationLoc(ContainerR.getEnd()); 97814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceLocation ContaineeRBeg = SM.getInstantiationLoc(ContaineeR.getBegin()); 97914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceLocation ContaineeREnd = SM.getInstantiationLoc(ContaineeR.getEnd()); 9801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek unsigned ContainerBegLine = SM.getInstantiationLineNumber(ContainerRBeg); 98214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek unsigned ContainerEndLine = SM.getInstantiationLineNumber(ContainerREnd); 98314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek unsigned ContaineeBegLine = SM.getInstantiationLineNumber(ContaineeRBeg); 98414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek unsigned ContaineeEndLine = SM.getInstantiationLineNumber(ContaineeREnd); 9851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek assert(ContainerBegLine <= ContainerEndLine); 9871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(ContaineeBegLine <= ContaineeEndLine); 9881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return (ContainerBegLine <= ContaineeBegLine && 99014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ContainerEndLine >= ContaineeEndLine && 99114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerBegLine != ContaineeBegLine || 9921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SM.getInstantiationColumnNumber(ContainerRBeg) <= 99314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SM.getInstantiationColumnNumber(ContaineeRBeg)) && 99414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerEndLine != ContaineeEndLine || 99514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SM.getInstantiationColumnNumber(ContainerREnd) >= 99614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SM.getInstantiationColumnNumber(ContainerREnd))); 99714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 99814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 99914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) { 100014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!PrevLoc.isValid()) { 100114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PrevLoc = NewLoc; 100214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 100314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 10041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10058c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc); 10068c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc); 10071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10088c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (NewLocClean.asLocation() == PrevLocClean.asLocation()) 100914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 10101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 101114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // FIXME: Ignore intra-macro edges for now. 10128c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (NewLocClean.asLocation().getInstantiationLoc() == 10138c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek PrevLocClean.asLocation().getInstantiationLoc()) 101414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 101514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 10168c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean)); 10178c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek PrevLoc = NewLoc; 101814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 101914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 102014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) { 10211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1022a301a6773db085575ac51e3c966858180390c25bTed Kremenek if (!alwaysAdd && NewLoc.asLocation().isMacroID()) 1023a301a6773db085575ac51e3c966858180390c25bTed Kremenek return; 10241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 102514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc); 102614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 102714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 10288f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation &TopContextLoc = CLocs.back(); 10291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 103014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 103114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == CLoc) { 10328f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 10334c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek if (IsConsumedExpr(TopContextLoc) && 10344c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek !IsControlFlowExpr(TopContextLoc.asStmt())) 10358f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek TopContextLoc.markDead(); 10368f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek 103714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 10388f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 103914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 104014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 104114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 104214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 104314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, CLoc)) { 10448f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 104514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 10461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10474c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek if (IsConsumedExpr(CLoc) && !IsControlFlowExpr(CLoc.asStmt())) { 10488f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek CLocs.push_back(ContextLocation(CLoc, true)); 10498f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return; 10508f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 10518f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 10521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 105314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(CLoc); 10541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 105514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 105614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 105714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 105814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 105914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 10601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10615c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // If we reach here, there is no enclosing context. Just add the edge. 10625c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek rawAddEdge(NewLoc); 106314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 106414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 10658f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekbool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) { 10668f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt())) 10678f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X); 10681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10698f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return false; 10708f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek} 10711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1072e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenekvoid EdgeBuilder::addExtendedContext(const Stmt *S) { 1073e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (!S) 1074e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek return; 10751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const Stmt *Parent = PDB.getParent(S); 1077e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek while (Parent) { 1078e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (isa<CompoundStmt>(Parent)) 1079e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek Parent = PDB.getParent(Parent); 1080e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek else 1081e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1082e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1083e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek 1084e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (Parent) { 1085e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek switch (Parent->getStmtClass()) { 1086e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::DoStmtClass: 1087e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 1088e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(Parent); 1089e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek default: 1090e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1091e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1092e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 10931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1094e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(S); 1095e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek} 10961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 109714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addContext(const Stmt *S) { 109814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!S) 109914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 110014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 110114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation L(S, PDB.getSourceManager()); 11021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 110314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 110414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &TopContextLoc = CLocs.back(); 110514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 110614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 110714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == L) 110814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 110914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 111014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, L)) { 111114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 11121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 111314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 111414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 111514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 111614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 111714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 111814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 111914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 112014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 112114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 112214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekstatic void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, 112314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB, 1124c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode *N) { 112514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder EB(PD, PDB); 112614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 112741ca1347c4b5bfea012f08d7eff8636d355762eaZhongxing Xu const ExplodedNode* NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); 112814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (NextNode) { 112914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek N = NextNode; 113014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek NextNode = GetPredecessorNode(N); 113114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ProgramPoint P = N->getLocation(); 113214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 1133dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek do { 1134dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Block edges. 1135dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 1136dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek const CFGBlock &Blk = *BE->getSrc(); 1137dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek const Stmt *Term = Blk.getTerminator(); 11381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1139dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Are we jumping to the head of a loop? Add a special diagnostic. 1140ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (const Stmt *Loop = BE->getDst()->getLoopTarget()) { 1141dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek PathDiagnosticLocation L(Loop, PDB.getSourceManager()); 1142ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const CompoundStmt *CS = NULL; 11431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1144ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (!Term) { 1145ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) 1146ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek CS = dyn_cast<CompoundStmt>(FS->getBody()); 1147ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) 11481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CS = dyn_cast<CompoundStmt>(WS->getBody()); 1149ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek } 11501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1151dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek PathDiagnosticEventPiece *p = 1152dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek new PathDiagnosticEventPiece(L, 115307c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek "Looping back to the head of the loop"); 11541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1155dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek EB.addEdge(p->getLocation(), true); 1156dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek PD.push_front(p); 11571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1158ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (CS) { 115907c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek PathDiagnosticLocation BL(CS->getRBracLoc(), 116007c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek PDB.getSourceManager()); 116107c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek BL = PathDiagnosticLocation(BL.asLocation()); 116207c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek EB.addEdge(BL); 1163dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 11648bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 11651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1166ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (Term) 1167ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek EB.addContext(Term); 11681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1169dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 11708bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 117114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 11721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) { 1173b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu if (CFGStmt S = BE->getFirstElement().getAs<CFGStmt>()) { 1174b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu if (IsControlFlowExpr(S)) { 1175b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu // Add the proper context for '&&', '||', and '?'. 1176b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu EB.addContext(S); 1177b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 1178b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu else 1179b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 1180dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 1181b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu 1182dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 1183dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 1184dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } while (0); 11851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1186dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (!NextNode) 118714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek continue; 11881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11898966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek for (BugReporterContext::visitor_iterator I = PDB.visitor_begin(), 11908966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek E = PDB.visitor_end(); I!=E; ++I) { 11918966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek if (PathDiagnosticPiece* p = (*I)->VisitNode(N, NextNode, PDB)) { 11928966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek const PathDiagnosticLocation &Loc = p->getLocation(); 11938966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek EB.addEdge(Loc, true); 11948966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek PD.push_front(p); 11958966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek if (const Stmt *S = Loc.asStmt()) 11961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 11978966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 11981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 119914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 120014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 120114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 12025fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 12033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugType and subclasses. 12043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 120590b6acf414327f953aa696cd64a449a4bd4fbb0dTed KremenekBugType::~BugType() { 120690b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek // Free up the equivalence class objects. Observe that we get a pointer to 120790b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek // the object first before incrementing the iterator, as destroying the 120890b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek // node before doing so means we will read from freed memory. 120990b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek for (iterator I = begin(), E = end(); I !=E; ) { 121090b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek BugReportEquivClass *EQ = &*I; 121190b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek ++I; 121290b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek delete EQ; 121390b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek } 121490b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek} 12153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugType::FlushReports(BugReporter &BR) {} 12163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 12173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 12183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReport and subclasses. 12193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 12203106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReport::~BugReport() {} 12213106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekRangedBugReport::~RangedBugReport() {} 12223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 12231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpconst Stmt* BugReport::getStmt() const { 1224212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care ProgramPoint ProgP = ErrorNode->getLocation(); 12255f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek const Stmt *S = NULL; 12261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (BlockEntrance* BE = dyn_cast<BlockEntrance>(&ProgP)) { 1228fafd3834754d2093e0ad7a1c005860fd527ecb7fZhongxing Xu CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit(); 122950d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu if (BE->getBlock() == &Exit) 1230212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care S = GetPreviousStmt(ErrorNode); 12313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 12325f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (!S) 12331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump S = GetStmt(ProgP); 12341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return S; 12363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 12373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 12383106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekPathDiagnosticPiece* 12398966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed KremenekBugReport::getEndPath(BugReporterContext& BRC, 1240c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode* EndPathNode) { 12411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 124250d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu const Stmt* S = getStmt(); 12431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!S) 12453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return NULL; 12463ef538dd1bb1001fa1a1d50594d13f480a8dfa21Ted Kremenek 1247640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis BugReport::ranges_iterator Beg, End; 1248640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis llvm::tie(Beg, End) = getRanges(); 12493ef538dd1bb1001fa1a1d50594d13f480a8dfa21Ted Kremenek PathDiagnosticLocation L(S, BRC.getSourceManager()); 12501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12513ef538dd1bb1001fa1a1d50594d13f480a8dfa21Ted Kremenek // Only add the statement itself as a range if we didn't specify any 12523ef538dd1bb1001fa1a1d50594d13f480a8dfa21Ted Kremenek // special ranges for this report. 12533ef538dd1bb1001fa1a1d50594d13f480a8dfa21Ted Kremenek PathDiagnosticPiece* P = new PathDiagnosticEventPiece(L, getDescription(), 12543ef538dd1bb1001fa1a1d50594d13f480a8dfa21Ted Kremenek Beg == End); 12551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (; Beg != End; ++Beg) 12573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek P->addRange(*Beg); 12581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return P; 12603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 12613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1262640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidisstd::pair<BugReport::ranges_iterator, BugReport::ranges_iterator> 1263640ccf071076e684713cc3c3276bb51982bff607Argyrios KyrtzidisBugReport::getRanges() const { 126450d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu if (const Expr* E = dyn_cast_or_null<Expr>(getStmt())) { 12653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek R = E->getSourceRange(); 12663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(R.isValid()); 1267640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis return std::make_pair(&R, &R+1); 12683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 12693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else 1270640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis return std::make_pair(ranges_iterator(), ranges_iterator()); 12713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 12723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 12731eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpSourceLocation BugReport::getLocation() const { 1274212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care if (ErrorNode) 1275212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care if (const Stmt* S = GetCurrentOrPreviousStmt(ErrorNode)) { 12763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // For member expressions, return the location of the '.' or '->'. 12775b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) 12783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return ME->getMemberLoc(); 12795b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek // For binary operators, return the location of the operator. 12805b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) 12815b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek return B->getOperatorLoc(); 12823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 12833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return S->getLocStart(); 12843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 12853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 12863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return FullSourceLoc(); 12873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 12883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1289c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing XuPathDiagnosticPiece* BugReport::VisitNode(const ExplodedNode* N, 1290c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode* PrevN, 12918966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek BugReporterContext &BRC) { 12923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return NULL; 12933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 12943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 12953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 12963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReporter and subclasses. 12973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 12983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 12993106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReportEquivClass::~BugReportEquivClass() { 13008966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek for (iterator I=begin(), E=end(); I!=E; ++I) delete *I; 13013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 13023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1303a2f4ec0df645fc249d2945beef9653f03b175417Zhongxing XuGRBugReporter::~GRBugReporter() { } 13043106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReporterData::~BugReporterData() {} 13053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 130638b02b912e1a55c912f603c4369431264d36a381Zhongxing XuExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); } 13073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13083106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekGRStateManager& 13093106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekGRBugReporter::getStateManager() { return Eng.getStateManager(); } 13103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13113106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReporter::~BugReporter() { FlushReports(); } 13123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugReporter::FlushReports() { 13143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (BugTypes.isEmpty()) 13153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return; 13163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // First flush the warnings for each BugType. This may end up creating new 13183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // warnings and new BugTypes. Because ImmutableSet is a functional data 13193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // structure, we do not need to worry about the iterators being invalidated. 13203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) 13213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const_cast<BugType*>(*I)->FlushReports(*this); 13223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Iterate through BugTypes a second time. BugTypes may have been updated 13243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // with new BugType objects and new warnings. 13253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) { 13263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek BugType *BT = const_cast<BugType*>(*I); 13273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek typedef llvm::FoldingSet<BugReportEquivClass> SetTy; 13293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SetTy& EQClasses = BT->EQClasses; 13303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (SetTy::iterator EI=EQClasses.begin(), EE=EQClasses.end(); EI!=EE;++EI){ 13323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek BugReportEquivClass& EQ = *EI; 13333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek FlushReport(EQ); 13343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 13351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Delete the BugType object. 13373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek delete BT; 13383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 13393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Remove all references to the BugType objects. 13413baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.getEmptySet(); 13423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 13433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 13453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnostics generation. 13463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 13473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 134838b02b912e1a55c912f603c4369431264d36a381Zhongxing Xustatic std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, 1349c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::pair<ExplodedNode*, unsigned> > 135038b02b912e1a55c912f603c4369431264d36a381Zhongxing XuMakeReportGraph(const ExplodedGraph* G, 135140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek llvm::SmallVectorImpl<const ExplodedNode*> &nodes) { 13521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the trimmed graph. It will contain the shortest paths from the 13541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // error nodes to the root. In the new graph we should only have one 13553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // error node unless there are two or more error nodes with the same minimum 13563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // path length. 135738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu ExplodedGraph* GTrim; 1358c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu InterExplodedGraphMap* NMap; 13593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*, const void*> InverseMap; 136140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek llvm::tie(GTrim, NMap) = G->Trim(nodes.data(), nodes.data() + nodes.size(), 136240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek &InverseMap); 13631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create owning pointers for GTrim and NMap just to ensure that they are 13653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // released when this function exists. 136638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu llvm::OwningPtr<ExplodedGraph> AutoReleaseGTrim(GTrim); 1367c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu llvm::OwningPtr<InterExplodedGraphMap> AutoReleaseNMap(NMap); 13681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the (first) error node in the trimmed graph. We just need to consult 13703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // the node map (NMap) which maps from nodes in the original graph to nodes 13713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // in the new graph. 1372938332c657390d1e782e0adc03b092993edae962Ted Kremenek 1373c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::queue<const ExplodedNode*> WS; 137438b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu typedef llvm::DenseMap<const ExplodedNode*, unsigned> IndexMapTy; 1375938332c657390d1e782e0adc03b092993edae962Ted Kremenek IndexMapTy IndexMap; 13763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 137740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek for (unsigned nodeIndex = 0 ; nodeIndex < nodes.size(); ++nodeIndex) { 137840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek const ExplodedNode *originalNode = nodes[nodeIndex]; 137940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (const ExplodedNode *N = NMap->getMappedNode(originalNode)) { 1380938332c657390d1e782e0adc03b092993edae962Ted Kremenek WS.push(N); 138140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek IndexMap[originalNode] = nodeIndex; 13823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 138340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 13841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1385938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(!WS.empty() && "No error node found in the trimmed graph."); 13863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create a new (third!) graph with a single path. This is the graph 13883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // that will be returned to the caller. 1389c77a55126fcad66fb086f8e100a494caa2496a2dZhongxing Xu ExplodedGraph *GNew = new ExplodedGraph(); 13901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Sometimes the trimmed graph can contain a cycle. Perform a reverse BFS 13923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // to the root node, and then construct a new graph that contains only 13933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // a single path. 13943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*,unsigned> Visited; 13951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek unsigned cnt = 0; 1397c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode* Root = 0; 13981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!WS.empty()) { 1400c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode* Node = WS.front(); 14013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek WS.pop(); 14021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Visited.find(Node) != Visited.end()) 14043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 14051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Visited[Node] = cnt++; 14071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Node->pred_empty()) { 14093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Root = Node; 14103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 14113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 14121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1413c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu for (ExplodedNode::const_pred_iterator I=Node->pred_begin(), 14143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek E=Node->pred_end(); I!=E; ++I) 14153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek WS.push(*I); 14163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 14171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1418938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(Root); 14191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now walk from the root down the BFS path, always taking the successor 14213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // with the lowest number. 14221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ExplodedNode *Last = 0, *First = 0; 14233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NodeBackMap *BM = new NodeBackMap(); 1424938332c657390d1e782e0adc03b092993edae962Ted Kremenek unsigned NodeIndex = 0; 14251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1426c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu for ( const ExplodedNode *N = Root ;;) { 14273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Lookup the number associated with the current node. 14283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*,unsigned>::iterator I = Visited.find(N); 1429938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(I != Visited.end()); 14301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the equivalent node in the new graph with the same state 14323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // and location. 143338b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu ExplodedNode* NewN = GNew->getNode(N->getLocation(), N->getState()); 14341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Store the mapping to the original node. 14363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*, const void*>::iterator IMitr=InverseMap.find(N); 14373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(IMitr != InverseMap.end() && "No mapping to original node."); 1438c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu (*BM)[NewN] = (const ExplodedNode*) IMitr->second; 14391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Link up the new node with the previous node. 14413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Last) 14425fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek NewN->addPredecessor(Last, *GNew); 14431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Last = NewN; 14451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Are we at the final node? 1447938332c657390d1e782e0adc03b092993edae962Ted Kremenek IndexMapTy::iterator IMI = 1448c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu IndexMap.find((const ExplodedNode*)(IMitr->second)); 1449938332c657390d1e782e0adc03b092993edae962Ted Kremenek if (IMI != IndexMap.end()) { 14503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek First = NewN; 1451938332c657390d1e782e0adc03b092993edae962Ted Kremenek NodeIndex = IMI->second; 14523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 14533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 14541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the next successor node. We choose the node that is marked 14563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // with the lowest DFS number. 1457c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::const_succ_iterator SI = N->succ_begin(); 1458c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::const_succ_iterator SE = N->succ_end(); 14593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek N = 0; 14601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (unsigned MinVal = 0; SI != SE; ++SI) { 14621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek I = Visited.find(*SI); 14641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (I == Visited.end()) 14663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 14671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!N || I->second < MinVal) { 14693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek N = *SI; 14703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MinVal = I->second; 14713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 14723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 14731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1474938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(N); 14753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 14761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1477938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(First); 1478938332c657390d1e782e0adc03b092993edae962Ted Kremenek 14793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return std::make_pair(std::make_pair(GNew, BM), 14803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::make_pair(First, NodeIndex)); 14813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 1482d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 14833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object 14843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// and collapses PathDiagosticPieces that are expanded by macros. 14853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekstatic void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) { 14863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek typedef std::vector<std::pair<PathDiagnosticMacroPiece*, SourceLocation> > 14873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStackTy; 14881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek typedef std::vector<PathDiagnosticPiece*> 14903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy; 14911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStackTy MacroStack; 14933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy Pieces; 14941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (PathDiagnostic::iterator I = PD.begin(), E = PD.end(); I!=E; ++I) { 14963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Get the location of the PathDiagnosticPiece. 14971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const FullSourceLoc Loc = I->getLocation().asLocation(); 14981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine the instantiation location, which is the location we group 15003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // related PathDiagnosticPieces. 15011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation InstantiationLoc = Loc.isMacroID() ? 15023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SM.getInstantiationLoc(Loc) : 15033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 15041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Loc.isFileID()) { 15063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.clear(); 15073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Pieces.push_back(&*I); 15083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 15093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1510706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek 15113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(Loc.isMacroID()); 15121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Is the PathDiagnosticPiece within the same macro group? 15143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) { 15153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.back().first->push_back(&*I); 15163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 15173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1518d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 15193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // We aren't in the same group. Are we descending into a new macro 15203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // or are part of an old one? 15213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticMacroPiece *MacroGroup = 0; 1522d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 15233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ? 15243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SM.getInstantiationLoc(Loc) : 15253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 15261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Walk the entire macro stack. 15283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!MacroStack.empty()) { 15293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (InstantiationLoc == MacroStack.back().second) { 15303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 15313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 15323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (ParentInstantiationLoc == MacroStack.back().second) { 15353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 15363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 153761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 15381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.pop_back(); 15406837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek } 15411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) { 15433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create a new macro group and add it to the stack. 15443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticMacroPiece *NewGroup = new PathDiagnosticMacroPiece(Loc); 15455a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek 15463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (MacroGroup) 15473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup->push_back(NewGroup); 15483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 15493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(InstantiationLoc.isFileID()); 15503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Pieces.push_back(NewGroup); 15513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = NewGroup; 15543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc)); 15557dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 15563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 15573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Finally, add the PathDiagnosticPiece to the group. 15583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup->push_back(&*I); 15593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now take the pieces and construct a new PathDiagnostic. 15623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PD.resetPath(false); 15631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) { 15653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (PathDiagnosticMacroPiece *MP=dyn_cast<PathDiagnosticMacroPiece>(*I)) 15663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MP->containsEvent()) { 15673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek delete MP; 15683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 15693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PD.push_back(*I); 157261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 157361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 157461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 15753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, 157640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek llvm::SmallVectorImpl<BugReport *> &bugReports) { 15771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 157840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek assert(!bugReports.empty()); 157940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek llvm::SmallVector<const ExplodedNode *, 10> errorNodes; 158040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek for (llvm::SmallVectorImpl<BugReport*>::iterator I = bugReports.begin(), 158140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek E = bugReports.end(); I != E; ++I) { 158240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek errorNodes.push_back((*I)->getErrorNode()); 158340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 15841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Construct a new graph that contains only a single path from the error 15861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // node to a root. 158738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu const std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, 1588c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::pair<ExplodedNode*, unsigned> >& 158940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek GPair = MakeReportGraph(&getGraph(), errorNodes); 15901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the BugReport with the original location. 159240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek assert(GPair.second.second < bugReports.size()); 159340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *R = bugReports[GPair.second.second]; 15943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(R && "No original report found for sliced graph."); 15951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 159638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu llvm::OwningPtr<ExplodedGraph> ReportGraph(GPair.first.first); 15973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::OwningPtr<NodeBackMap> BackMap(GPair.first.second); 1598c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode *N = GPair.second.first; 15991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Start building the path diagnostic... 16018966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek PathDiagnosticBuilder PDB(*this, R, BackMap.get(), getPathDiagnosticClient()); 16021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16038966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek if (PathDiagnosticPiece* Piece = R->getEndPath(PDB, N)) 16043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PD.push_back(Piece); 16053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else 16063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return; 16071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1608ff7f736211070be873df0a345295fd1453ee7c50Ted Kremenek // Register node visitors. 1609dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek R->registerInitialVisitors(PDB, N); 1610ff7f736211070be873df0a345295fd1453ee7c50Ted Kremenek bugreporter::registerNilReceiverVisitor(PDB); 16111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek switch (PDB.getGenerationScheme()) { 16133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case PathDiagnosticClient::Extensive: 16148966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek GenerateExtensivePathDiagnostic(PD, PDB, N); 16155fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek break; 16163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case PathDiagnosticClient::Minimal: 16173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek GenerateMinimalPathDiagnostic(PD, PDB, N); 16183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 16193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 16203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 16211aa44c7c9198796085b77c6bdd7c90030845a688Ted Kremenek 1622cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::Register(BugType *BT) { 16233baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.add(BugTypes, BT); 162476d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek} 162576d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek 16261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid BugReporter::EmitReport(BugReport* R) { 1627cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // Compute the bug report's hash to determine its equivalence class. 1628cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek llvm::FoldingSetNodeID ID; 1629cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek R->Profile(ID); 16301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Lookup the equivance class. If there isn't one, create it. 1632cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek BugType& BT = R->getBugType(); 1633cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek Register(&BT); 1634cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek void *InsertPos; 16351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump BugReportEquivClass* EQ = BT.EQClasses.FindNodeOrInsertPos(ID, InsertPos); 16361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1637cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek if (!EQ) { 1638cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ = new BugReportEquivClass(R); 1639cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek BT.EQClasses.InsertNode(EQ, InsertPos); 1640cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek } 1641cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek else 1642cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ->AddReport(R); 164361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 164461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 164506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 164606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 164706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek// Emitting reports in equivalence classes. 164806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 164906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 165006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremeneknamespace { 1651ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamstruct FRIEC_WLItem { 165206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *N; 165306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek ExplodedNode::const_succ_iterator I, E; 165406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 165506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek FRIEC_WLItem(const ExplodedNode *n) 165606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek : N(n), I(N->succ_begin()), E(N->succ_end()) {} 165706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek}; 165806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek} 165906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 166061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenekstatic BugReport * 166161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted KremenekFindReportInEquivalenceClass(BugReportEquivClass& EQ, 166240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek llvm::SmallVectorImpl<BugReport*> &bugReports) { 166361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 166406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end(); 166506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(I != E); 166606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek BugReport *R = *I; 166706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek BugType& BT = R->getBugType(); 166861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 166940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // If we don't need to suppress any of the nodes because they are 167040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // post-dominated by a sink, simply add all the nodes in the equivalence class 167140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // to 'Nodes'. Any of the reports will serve as a "representative" report. 167261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!BT.isSuppressOnSink()) { 167361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) { 1674212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care const ExplodedNode* N = I->getErrorNode(); 167561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (N) { 167661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek R = *I; 167740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek bugReports.push_back(R); 167861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 167961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 168006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek return R; 168161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 168261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 168306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // For bug reports that should be suppressed when all paths are post-dominated 168406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // by a sink node, iterate through the reports in the equivalence class 168506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // until we find one that isn't post-dominated (if one exists). We use a 168606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // DFS traversal of the ExplodedGraph to find a non-sink node. We could write 168706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // this as a recursive function, but we don't want to risk blowing out the 168806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // stack for very long paths. 168940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = 0; 169061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 169106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; I != E; ++I) { 169206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek R = *I; 169340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek const ExplodedNode *errorNode = R->getErrorNode(); 169406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 169540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!errorNode) 169606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 169740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->isSink()) { 169806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(false && 169906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek "BugType::isSuppressSink() should not be 'true' for sink end nodes"); 170061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek return 0; 170106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 170261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // No successors? By definition this nodes isn't post-dominated by a sink. 170340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->succ_empty()) { 170440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek bugReports.push_back(R); 170540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 170640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek exampleReport = R; 170761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek continue; 170861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 170961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 171006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // At this point we know that 'N' is not a sink and it has at least one 171106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // successor. Use a DFS worklist to find a non-sink end-of-path node. 171206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek typedef FRIEC_WLItem WLItem; 171306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek typedef llvm::SmallVector<WLItem, 10> DFSWorkList; 171406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek llvm::DenseMap<const ExplodedNode *, unsigned> Visited; 171506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 171606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek DFSWorkList WL; 171740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek WL.push_back(errorNode); 171840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek Visited[errorNode] = 1; 171906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 172006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek while (!WL.empty()) { 172106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WLItem &WI = WL.back(); 172206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(!WI.N->succ_empty()); 172306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 172406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; WI.I != WI.E; ++WI.I) { 172506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *Succ = *WI.I; 172606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // End-of-path node? 172706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (Succ->succ_empty()) { 172861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // If we found an end-of-path node that is not a sink. 172961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!Succ->isSink()) { 173040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek bugReports.push_back(R); 173140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 173240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek exampleReport = R; 173361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek WL.clear(); 173461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek break; 173561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 173606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Found a sink? Continue on to the next successor. 173706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 173806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 173906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Mark the successor as visited. If it hasn't been explored, 174006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // enqueue it to the DFS worklist. 174106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek unsigned &mark = Visited[Succ]; 174206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (!mark) { 174306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek mark = 1; 174406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.push_back(Succ); 174506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek break; 174606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 174706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 174861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 174961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // The worklist may have been cleared at this point. First 175061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // check if it is empty before checking the last item. 175161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!WL.empty() && &WL.back() == &WI) 175206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.pop_back(); 175306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 175406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 175506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 175661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // ExampleReport will be NULL if all the nodes in the equivalence class 175761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // were post-dominated by sinks. 175840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek return exampleReport; 175961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek} 1760e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1761e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek//===----------------------------------------------------------------------===// 1762e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek// DiagnosticCache. This is a hack to cache analyzer diagnostics. It 1763e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek// uses global state, which eventually should go elsewhere. 1764e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek//===----------------------------------------------------------------------===// 1765e0a58073b76fc016325a35152533b8468df2bf4aTed Kremeneknamespace { 1766ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass DiagCacheItem : public llvm::FoldingSetNode { 1767e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek llvm::FoldingSetNodeID ID; 1768e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenekpublic: 1769e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek DiagCacheItem(BugReport *R, PathDiagnostic *PD) { 1770e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek ID.AddString(R->getBugType().getName()); 1771e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek ID.AddString(R->getBugType().getCategory()); 1772e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek ID.AddString(R->getDescription()); 1773e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek ID.AddInteger(R->getLocation().getRawEncoding()); 1774e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek PD->Profile(ID); 1775e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek } 1776e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1777e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek void Profile(llvm::FoldingSetNodeID &id) { 1778e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek id = ID; 1779e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek } 1780e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1781e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek llvm::FoldingSetNodeID &getID() { return ID; } 1782e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek}; 1783e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek} 1784e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1785e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenekstatic bool IsCachedDiagnostic(BugReport *R, PathDiagnostic *PD) { 1786e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek // FIXME: Eventually this diagnostic cache should reside in something 1787e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek // like AnalysisManager instead of being a static variable. This is 1788e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek // really unsafe in the long term. 1789e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek typedef llvm::FoldingSet<DiagCacheItem> DiagnosticCache; 1790e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek static DiagnosticCache DC; 1791e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1792e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek void *InsertPos; 1793e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek DiagCacheItem *Item = new DiagCacheItem(R, PD); 1794e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1795e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek if (DC.FindNodeOrInsertPos(Item->getID(), InsertPos)) { 1796e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek delete Item; 1797e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek return true; 1798e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek } 1799e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1800e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek DC.InsertNode(Item, InsertPos); 1801e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek return false; 1802e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek} 1803e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1804cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::FlushReport(BugReportEquivClass& EQ) { 180540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek llvm::SmallVector<BugReport*, 10> bugReports; 180640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports); 180740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 180806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek return; 180906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 1810d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek PathDiagnosticClient* PD = getPathDiagnosticClient(); 18111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1812cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // FIXME: Make sure we use the 'R' for the path that was actually used. 18131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Probably doesn't make a difference in practice. 181440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugType& BT = exampleReport->getBugType(); 18151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1816d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek llvm::OwningPtr<PathDiagnostic> 181740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek D(new PathDiagnostic(exampleReport->getBugType().getName(), 1818da0e8429a3598acfdd0ecf15135d432e4dd3517cTed Kremenek !PD || PD->useVerboseDescription() 181940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek ? exampleReport->getDescription() 182040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek : exampleReport->getShortDescription(), 1821d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek BT.getCategory())); 1822d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek 182340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!bugReports.empty()) 182440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek GeneratePathDiagnostic(*D.get(), bugReports); 18251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 182640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (IsCachedDiagnostic(exampleReport, D.get())) 1827e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek return; 1828e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1829072192bcbb05a0fee7ec3061750b27e8d2004952Ted Kremenek // Get the meta data. 183040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek std::pair<const char**, const char**> Meta = 183140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek exampleReport->getExtraDescriptiveText(); 183206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (const char** s = Meta.first; s != Meta.second; ++s) 183306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek D->addMeta(*s); 183475840e1501563fe7c3dcb5600b75965ba1fe1bc4Ted Kremenek 18353148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek // Emit a summary diagnostic to the regular Diagnostics engine. 1836640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis BugReport::ranges_iterator Beg, End; 1837640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis llvm::tie(Beg, End) = exampleReport->getRanges(); 183840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek Diagnostic &Diag = getDiagnostic(); 183940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek FullSourceLoc L(exampleReport->getLocation(), getSourceManager()); 1840c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek 1841c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek // Search the description for '%', as that will be interpretted as a 1842c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek // format character by FormatDiagnostics. 184340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek llvm::StringRef desc = exampleReport->getShortDescription(); 1844c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek unsigned ErrorDiag; 1845c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek { 1846c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek llvm::SmallString<512> TmpStr; 1847c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek llvm::raw_svector_ostream Out(TmpStr); 1848c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek for (llvm::StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I) 1849c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek if (*I == '%') 1850c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek Out << "%%"; 1851c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek else 1852c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek Out << *I; 1853c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek 1854c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek Out.flush(); 1855c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, TmpStr); 1856c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek } 18570a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner 1858b6b7e7bff3101062521de6e79533a3c25e2195d9Argyrios Kyrtzidis { 1859b6b7e7bff3101062521de6e79533a3c25e2195d9Argyrios Kyrtzidis DiagnosticBuilder diagBuilder = Diag.Report(L, ErrorDiag); 1860640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis for (BugReport::ranges_iterator I = Beg; I != End; ++I) 1861b6b7e7bff3101062521de6e79533a3c25e2195d9Argyrios Kyrtzidis diagBuilder << *I; 18622f0e89ea96292d2974eb1a7dddc0e9870aa86bb7Ted Kremenek } 18633148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek 18643148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek // Emit a full diagnostic for the path if we have a PathDiagnosticClient. 18653148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek if (!PD) 18663148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek return; 18671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (D->empty()) { 18691fbfd5b9b8b82aea084773b76dd1ec6796a7000cTed Kremenek PathDiagnosticPiece* piece = 187040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek new PathDiagnosticEventPiece(L, exampleReport->getDescription()); 18711fbfd5b9b8b82aea084773b76dd1ec6796a7000cTed Kremenek 18723148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek for ( ; Beg != End; ++Beg) piece->addRange(*Beg); 18733148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek D->push_back(piece); 18743148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek } 18751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18763148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek PD->HandlePathDiagnostic(D.take()); 187761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 187857202071e477530e9348bc76671ee369b2399b92Ted Kremenek 1879f0171732efb4647772ad2a45c0f31978b0e34f71Benjamin Kramervoid BugReporter::EmitBasicReport(llvm::StringRef name, llvm::StringRef str, 18808c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek SourceLocation Loc, 18818c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek SourceRange* RBeg, unsigned NumRanges) { 18828c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek EmitBasicReport(name, "", str, Loc, RBeg, NumRanges); 18838c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek} 1884cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 1885f0171732efb4647772ad2a45c0f31978b0e34f71Benjamin Kramervoid BugReporter::EmitBasicReport(llvm::StringRef name, 1886f0171732efb4647772ad2a45c0f31978b0e34f71Benjamin Kramer llvm::StringRef category, 1887f0171732efb4647772ad2a45c0f31978b0e34f71Benjamin Kramer llvm::StringRef str, SourceLocation Loc, 18888c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek SourceRange* RBeg, unsigned NumRanges) { 18891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1890cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // 'BT' will be owned by BugReporter as soon as we call 'EmitReport'. 1891cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek BugType *BT = new BugType(name, category); 18920a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner FullSourceLoc L = getContext().getFullLoc(Loc); 1893cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek RangedBugReport *R = new DiagBugReport(*BT, str, L); 1894cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg); 1895cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EmitReport(R); 1896cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek} 1897