BugReporter.cpp revision ef3643fbbbf66247c5e205497fae0f46e240c143
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() {} 361b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek 37cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Helper routines for walking the ExplodedGraph and fetching statements. 39cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 4061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 419c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic inline const Stmt *GetStmt(const ProgramPoint &P) { 42592362b46ad69db0db0988e7f9d8cbe647510bddTed Kremenek if (const StmtPoint* SP = dyn_cast<StmtPoint>(&P)) 43592362b46ad69db0db0988e7f9d8cbe647510bddTed Kremenek return SP->getStmt(); 449c378f705405d37f49795d5e915989de774fe11fTed Kremenek else if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) 4561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek return BE->getSrc()->getTerminator(); 461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 47b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return 0; 4861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 4961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 50c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic inline const ExplodedNode* 519c378f705405d37f49795d5e915989de774fe11fTed KremenekGetPredecessorNode(const ExplodedNode *N) { 52b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return N->pred_empty() ? NULL : *(N->pred_begin()); 53706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek} 54706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek 55c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic inline const ExplodedNode* 569c378f705405d37f49795d5e915989de774fe11fTed KremenekGetSuccessorNode(const ExplodedNode *N) { 57b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return N->succ_empty() ? NULL : *(N->succ_begin()); 58bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek} 592673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek 609c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic const Stmt *GetPreviousStmt(const ExplodedNode *N) { 61b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek for (N = GetPredecessorNode(N); N; N = GetPredecessorNode(N)) 625f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) 63b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 65b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return 0; 66b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek} 67b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek 689c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic const Stmt *GetNextStmt(const ExplodedNode *N) { 69b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek for (N = GetSuccessorNode(N); N; N = GetSuccessorNode(N)) 705f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) { 71f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek // Check if the statement is '?' or '&&'/'||'. These are "merges", 72f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek // not actual statement points. 73f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek switch (S->getStmtClass()) { 74f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek case Stmt::ChooseExprClass: 7556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: continue; 76f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek case Stmt::ConditionalOperatorClass: continue; 77f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek case Stmt::BinaryOperatorClass: { 782de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode(); 792de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (Op == BO_LAnd || Op == BO_LOr) 80f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek continue; 81f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek break; 82f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 83f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek default: 84f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek break; 85f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 86b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 87f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 89b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return 0; 90bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek} 91bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek 925f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt* 939c378f705405d37f49795d5e915989de774fe11fTed KremenekGetCurrentOrPreviousStmt(const ExplodedNode *N) { 945f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) 95b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 97b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return GetPreviousStmt(N); 98b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek} 991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1005f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt* 1019c378f705405d37f49795d5e915989de774fe11fTed KremenekGetCurrentOrNextStmt(const ExplodedNode *N) { 1025f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) 103b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 1041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 105b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return GetNextStmt(N); 1063148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek} 1073148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek 108b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 1093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnosticBuilder and its associated routines and helper objects. 110b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 111b479dadea93b93d3f0a335c3518b703f140b3f50Ted Kremenek 112c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xutypedef llvm::DenseMap<const ExplodedNode*, 113c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuconst ExplodedNode*> NodeBackMap; 1147dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek 115babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremeneknamespace { 116ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NodeMapClosure : public BugReport::NodeResolver { 1177dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeBackMap& M; 1187dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenekpublic: 1197dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeMapClosure(NodeBackMap *m) : M(*m) {} 1207dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek ~NodeMapClosure() {} 1211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1229c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *getOriginalNode(const ExplodedNode *N) { 1237dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeBackMap::iterator I = M.find(N); 1247dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek return I == M.end() ? 0 : I->second; 1257dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 1267dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek}; 1271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 128ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass PathDiagnosticBuilder : public BugReporterContext { 1297dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek BugReport *R; 130ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *PDC; 13100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek llvm::OwningPtr<ParentMap> PM; 1327dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeMapClosure NMC; 1331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic: 1348966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek PathDiagnosticBuilder(GRBugReporter &br, 1351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump BugReport *r, NodeBackMap *Backmap, 136ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *pdc) 1378966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek : BugReporterContext(br), 1388e6431adab313e283a992698f6fc7afe62420999Anna Zaks R(r), PDC(pdc), NMC(Backmap) {} 1391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1409c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N); 1411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1429c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os, 1439c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N); 1441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1458e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *getBugReport() { return R; } 1468e6431adab313e283a992698f6fc7afe62420999Anna Zaks 147212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); } 148b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu 149220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks const LocationContext* getLocationContext() { 150220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return R->getErrorNode()->getLocationContext(); 151220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks } 152220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks 153212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care ParentMap& getParentMap() { return R->getErrorNode()->getParentMap(); } 1541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 155c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek const Stmt *getParent(const Stmt *S) { 156c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek return getParentMap().getParent(S); 157c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek } 1581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1598966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek virtual NodeMapClosure& getNodeResolver() { return NMC; } 1607297134f128423fce2e88f92421ed135bded7d4eDouglas Gregor 161d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S); 1621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 163ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const { 164ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive; 1657dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 1667dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek 167babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek bool supportsLogicalOpControlFlow() const { 168babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek return PDC ? PDC->supportsLogicalOpControlFlow() : true; 1691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 170babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek}; 171babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek} // end anonymous namespace 172babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 17300605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 1749c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) { 1755f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetNextStmt(N)) 176220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, getSourceManager(), getLocationContext()); 17700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek 1780cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return PathDiagnosticLocation::createDeclEnd(N->getLocationContext(), 1790cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks getSourceManager()); 180082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek} 1811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18200605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 1839c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os, 1849c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N) { 185babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 186143ca222583a4a355fdc89af852deef287499300Ted Kremenek // Slow, but probably doesn't matter. 187b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek if (os.str().empty()) 188b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << ' '; 1891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19000605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek const PathDiagnosticLocation &Loc = ExecutionContinues(N); 1911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek if (Loc.asStmt()) 193b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << "Execution continues on line " 194642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << getSourceManager().getExpansionLineNumber(Loc.asLocation()) 1958966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek << '.'; 1964f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 1974f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "Execution jumps to the end of the "; 1984f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek const Decl *D = N->getLocationContext()->getDecl(); 1994f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek if (isa<ObjCMethodDecl>(D)) 2004f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "method"; 2014f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else if (isa<FunctionDecl>(D)) 2024f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "function"; 2034f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 2044f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek assert(isa<BlockDecl>(D)); 2054f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "anonymous block"; 2064f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 2074f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << '.'; 2084f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 2091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 210082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek return Loc; 211143ca222583a4a355fdc89af852deef287499300Ted Kremenek} 212143ca222583a4a355fdc89af852deef287499300Ted Kremenek 213ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenekstatic bool IsNested(const Stmt *S, ParentMap &PM) { 214ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S))) 215ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek return true; 2161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 217ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const Stmt *Parent = PM.getParentIgnoreParens(S); 2181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 219ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (Parent) 220ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek switch (Parent->getStmtClass()) { 221ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::ForStmtClass: 222ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::DoStmtClass: 223ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::WhileStmtClass: 224ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek return true; 225ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek default: 226ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek break; 227ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek } 2281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 230ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek} 231ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek 232d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticLocation 233d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { 2349c378f705405d37f49795d5e915989de774fe11fTed Kremenek assert(S && "Null Stmt *passed to getEnclosingStmtLocation"); 2351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ParentMap &P = getParentMap(); 2368966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek SourceManager &SMgr = getSourceManager(); 237220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks const LocationContext *LC = getLocationContext(); 238e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 239ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek while (IsNested(S, P)) { 2408c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const Stmt *Parent = P.getParentIgnoreParens(S); 2411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 242af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (!Parent) 243af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 2441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 245af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek switch (Parent->getStmtClass()) { 2465fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek case Stmt::BinaryOperatorClass: { 2475fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const BinaryOperator *B = cast<BinaryOperator>(Parent); 2485fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 249220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 2505fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek break; 2511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 252af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::CompoundStmtClass: 253af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::StmtExprClass: 254220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 2551d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ChooseExprClass: 2561d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // Similar to '?' if we are referring to condition, just have the edge 2571d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // point to the entire choose expression. 2581d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (cast<ChooseExpr>(Parent)->getCond() == S) 259220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 2601d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 261220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 26256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 2631d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ConditionalOperatorClass: 2641d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // For '?', if we are referring to condition, just have the edge point 2651d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // to the entire '?' expression. 26656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (cast<AbstractConditionalOperator>(Parent)->getCond() == S) 267220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 2681d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 269220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 270af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::DoStmtClass: 271220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 272af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ForStmtClass: 273af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ForStmt>(Parent)->getBody() == S) 274220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 2751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump break; 276af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::IfStmtClass: 277af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<IfStmt>(Parent)->getCond() != S) 278220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 2798bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek break; 280af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 281af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S) 282220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 283af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 284af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::WhileStmtClass: 285af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<WhileStmt>(Parent)->getCond() != S) 286220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 287af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 288af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek default: 289af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 290af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek } 291af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek 292d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek S = Parent; 293d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek } 2941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 295d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek assert(S && "Cannot have null Stmt for PathDiagnosticLocation"); 296e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 297e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // Special case: DeclStmts can appear in for statement declarations, in which 298e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // case the ForStmt is the context. 299e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (isa<DeclStmt>(S)) { 300e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (const Stmt *Parent = P.getParent(S)) { 301e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek switch (Parent->getStmtClass()) { 302e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek case Stmt::ForStmtClass: 303e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 304220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 305e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek default: 306e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek break; 3071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 3081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 309e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 310e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek else if (isa<BinaryOperator>(S)) { 311e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // Special case: the binary operator represents the initialization 312e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // code in a for statement (this can happen when the variable being 313e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // initialized is an old variable. 314e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (const ForStmt *FS = 315e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek dyn_cast_or_null<ForStmt>(P.getParentIgnoreParens(S))) { 316e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (FS->getInit() == S) 317220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(FS, SMgr, LC); 318e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 319e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 320e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 321220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 322d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek} 323d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 324cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 3253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// ScanNotableSymbols: closure-like callback for scanning Store bindings. 326cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 327cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 32818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenekstatic const VarDecl* GetMostRecentVarDeclBinding(const ExplodedNode *N, 32918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek ProgramStateManager& VMgr, 33018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek SVal X) { 3311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for ( ; N ; N = N->pred_empty() ? 0 : *N->pred_begin()) { 3331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek ProgramPoint P = N->getLocation(); 3351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!isa<PostStmt>(P)) 3373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 3381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3399c378f705405d37f49795d5e915989de774fe11fTed Kremenek const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(cast<PostStmt>(P).getStmt()); 3401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!DR) 3423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 3431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3441397663af9dbcc24dbf0e11de43931b3dc08fdbbTed Kremenek SVal Y = N->getState()->getSVal(DR); 3451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (X != Y) 3473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 3481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3499c378f705405d37f49795d5e915989de774fe11fTed Kremenek const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); 3501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!VD) 3523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 3531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return VD; 355cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek } 3561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return 0; 358bb77e9b908658b354b058509d3801f3aed052becTed Kremenek} 359bb77e9b908658b354b058509d3801f3aed052becTed Kremenek 3603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremeneknamespace { 361ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NotableSymbolHandler 3623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek: public StoreManager::BindingsHandler { 3631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SymbolRef Sym; 36518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *PrevSt; 3669c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Stmt *S; 36718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek ProgramStateManager& VMgr; 3689c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *Pred; 3691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump PathDiagnostic& PD; 3703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek BugReporter& BR; 3711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekpublic: 3731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 37418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek NotableSymbolHandler(SymbolRef sym, 37518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *prevst, 37618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Stmt *s, 37718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek ProgramStateManager& vmgr, 37818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ExplodedNode *pred, 37918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek PathDiagnostic& pd, 38018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek BugReporter& br) 38118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek : Sym(sym), 38218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek PrevSt(prevst), 38318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek S(s), 38418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek VMgr(vmgr), 38518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek Pred(pred), 38618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek PD(pd), 38718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek BR(br) {} 3881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, 3903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SVal V) { 3911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SymbolRef ScanSym = V.getAsSymbol(); 3931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (ScanSym != Sym) 3953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 3961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Check if the previous state has this binding. 3981397663af9dbcc24dbf0e11de43931b3dc08fdbbTed Kremenek SVal X = PrevSt->getSVal(loc::MemRegionVal(R)); 3991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (X == V) // Same binding? 4013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Different binding. Only handle assignments for now. We don't pull 4041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // this check out of the loop because we will eventually handle other 4053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // cases. 4061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek VarDecl *VD = 0; 4081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { 4103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!B->isAssignmentOp()) 4113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // What variable did we assign to? 4149c378f705405d37f49795d5e915989de774fe11fTed Kremenek DeclRefExpr *DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenCasts()); 4151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!DR) 4173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek VD = dyn_cast<VarDecl>(DR->getDecl()); 4203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 4219c378f705405d37f49795d5e915989de774fe11fTed Kremenek else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) { 4223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // FIXME: Eventually CFGs won't have DeclStmts. Right now we 4233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // assume that each DeclStmt has a single Decl. This invariant 424fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // holds by construction in the CFG. 4253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek VD = dyn_cast<VarDecl>(*DS->decl_begin()); 4263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 4271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!VD) 4293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // What is the most recently referenced variable with this binding? 4329c378f705405d37f49795d5e915989de774fe11fTed Kremenek const VarDecl *MostRecent = GetMostRecentVarDeclBinding(Pred, VMgr, V); 4331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MostRecent) 4353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the diagnostic. 4387dfc9420babe83e236a47e752f8723bd06070d9dZhanyong Wan if (Loc::isLocType(VD->getType())) { 4397df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose llvm::SmallString<64> buf; 4407df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose llvm::raw_svector_ostream os(buf); 4417df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose os << '\'' << VD << "' now aliases '" << MostRecent << '\''; 442590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation L = 443590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation::createBegin(S, BR.getSourceManager(), 444590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks Pred->getLocationContext()); 4457df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose PD.push_front(new PathDiagnosticEventPiece(L, os.str())); 4463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 4471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 4503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}; 4513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 4523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 4539c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic void HandleNotableSymbol(const ExplodedNode *N, 4549c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Stmt *S, 4553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SymbolRef Sym, BugReporter& BR, 4563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnostic& PD) { 4571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4589c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *Pred = N->pred_empty() ? 0 : *N->pred_begin(); 45918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *PrevSt = Pred ? Pred->getState() : 0; 4601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!PrevSt) 4623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return; 4631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Look at the region bindings of the current state that map to the 4653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // specified symbol. Are any of them not in the previous state? 46618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek ProgramStateManager& VMgr = cast<GRBugReporter>(BR).getStateManager(); 4673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NotableSymbolHandler H(Sym, PrevSt, S, VMgr, Pred, PD, BR); 4683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek cast<GRBugReporter>(BR).getStateManager().iterBindings(N->getState(), H); 46961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 47061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 4713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremeneknamespace { 472ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ScanNotableSymbols 4733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek: public StoreManager::BindingsHandler { 4741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::SmallSet<SymbolRef, 10> AlreadyProcessed; 4769c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N; 4779c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Stmt *S; 4783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek GRBugReporter& BR; 4793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnostic& PD; 4801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekpublic: 4829c378f705405d37f49795d5e915989de774fe11fTed Kremenek ScanNotableSymbols(const ExplodedNode *n, const Stmt *s, 4835f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek GRBugReporter& br, PathDiagnostic& pd) 4843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek : N(n), S(s), BR(br), PD(pd) {} 4851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek bool HandleBinding(StoreManager& SMgr, Store store, 4873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const MemRegion* R, SVal V) { 4881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SymbolRef ScanSym = V.getAsSymbol(); 4901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!ScanSym) 4923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!BR.isNotable(ScanSym)) 4953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (AlreadyProcessed.count(ScanSym)) 4983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 4991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek AlreadyProcessed.insert(ScanSym); 5011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek HandleNotableSymbol(N, S, ScanSym, BR, PD); 5033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return true; 504bb77e9b908658b354b058509d3801f3aed052becTed Kremenek } 5053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}; 5063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} // end anonymous namespace 50750a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek 508cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 5093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// "Minimal" path diagnostic generation algorithm. 510cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 511cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 51214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekstatic void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM); 51314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 5143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekstatic void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, 5153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticBuilder &PDB, 516c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode *N) { 5178966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek 5183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceManager& SMgr = PDB.getSourceManager(); 519220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks const LocationContext *LC = PDB.getLocationContext(); 5209c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() 5213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek ? NULL : *(N->pred_begin()); 5223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (NextNode) { 5231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump N = NextNode; 5243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NextNode = GetPredecessorNode(N); 5251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 52661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek ProgramPoint P = N->getLocation(); 5271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5289c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 5299c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CFGBlock *Src = BE->getSrc(); 5309c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CFGBlock *Dst = BE->getDst(); 5319c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Stmt *T = Src->getTerminator(); 5321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 53361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek if (!T) 53461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek continue; 5351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 536590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation Start = 537590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation::createBegin(T, SMgr, 538590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks N->getLocationContext()); 5391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 54061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek switch (T->getStmtClass()) { 54161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek default: 54261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 5431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 54461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek case Stmt::GotoStmtClass: 5451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::IndirectGotoStmtClass: { 5469c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Stmt *S = GetNextStmt(N); 5471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 54861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek if (!S) 54961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek continue; 5501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 551297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 5521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::raw_string_ostream os(sbuf); 553d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S); 5541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 55500605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os << "Control jumps to line " 556642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << End.asLocation().getExpansionLineNumber(); 557082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 558082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os.str())); 55961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 56061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 5611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::SwitchStmtClass: { 56361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek // Figure out what case arm we took. 564297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 565297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 5661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5679c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const Stmt *S = Dst->getLabel()) { 568220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(S, SMgr, LC); 5691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5705a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek switch (S->getStmtClass()) { 571082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek default: 572082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "No cases match in the switch statement. " 5733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek "Control jumps to line " 574642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << End.asLocation().getExpansionLineNumber(); 575082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek break; 576082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek case Stmt::DefaultStmtClass: 577082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "Control jumps to the 'default' case at line " 578642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << End.asLocation().getExpansionLineNumber(); 579082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek break; 5801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 581082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek case Stmt::CaseStmtClass: { 5821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump os << "Control jumps to 'case "; 5839c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CaseStmt *Case = cast<CaseStmt>(S); 5849c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Expr *LHS = Case->getLHS()->IgnoreParenCasts(); 5851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Determine if it is an enum. 587082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek bool GetRawInt = true; 5881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5899c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) { 590082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek // FIXME: Maybe this should be an assertion. Are there cases 591082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek // were it is not an EnumConstantDecl? 5929c378f705405d37f49795d5e915989de774fe11fTed Kremenek const EnumConstantDecl *D = 59303509aea098772644bf4662dc1c88634818ceeccZhongxing Xu dyn_cast<EnumConstantDecl>(DR->getDecl()); 5941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 595082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek if (D) { 596082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek GetRawInt = false; 597900fc6388e803868a34b9483510c345e9b49d7ebBenjamin Kramer os << D; 598082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 5995a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek } 6009ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 6019ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman if (GetRawInt) 6028966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek os << LHS->EvaluateAsInt(PDB.getASTContext()); 6039ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 60400605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os << ":' at line " 605642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << End.asLocation().getExpansionLineNumber(); 606082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek break; 607082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 60861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 60900605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 61000605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os.str())); 61161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 612567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek else { 613c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "'Default' branch taken. "; 6141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N); 61500605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 61600605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os.str())); 617567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek } 6181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 61961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 62061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 6211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6222673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::BreakStmtClass: 6232673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::ContinueStmtClass: { 624297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 625297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 62600605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 627082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 628082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os.str())); 6292673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek break; 6302673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek } 6311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine control-flow for ternary '?'. 63356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 634706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek case Stmt::ConditionalOperatorClass: { 635297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 636297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 6371d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek os << "'?' condition is "; 6381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 639706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()+1) == Dst) 640082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "false"; 641706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek else 642082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "true"; 6431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 64400605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 6451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6461d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (const Stmt *S = End.asStmt()) 6471d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 6481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 649babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 650babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek os.str())); 651babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 652babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 6531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine control-flow for short-circuited '&&' and '||'. 655babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek case Stmt::BinaryOperatorClass: { 656babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek if (!PDB.supportsLogicalOpControlFlow()) 657babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 6581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 65903509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const BinaryOperator *B = cast<BinaryOperator>(T); 660babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek std::string sbuf; 661babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek llvm::raw_string_ostream os(sbuf); 662babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek os << "Left side of '"; 6631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6642de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_LAnd) { 665f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "&&" << "' is "; 6661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 667f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 668f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 669220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 6700cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 6710cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 672f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 673f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os.str())); 6741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 675f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 676f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 677220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 678f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 679f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 680f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os.str())); 6811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 682babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 683babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek else { 6842de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(B->getOpcode() == BO_LOr); 685f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "||" << "' is "; 6861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 687f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 688f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 689220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 690f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 691f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 6921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump os.str())); 693f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 694f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 695f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 696220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 6970cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 6980cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 699f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 7001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump os.str())); 701f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 702babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 7031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 704706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek break; 705706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek } 7061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::DoStmtClass: { 708706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()) == Dst) { 709297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 710297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 7111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 712c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "Loop condition is true. "; 713d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 7141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 715d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 716d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 7171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 718082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 719082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os.str())); 720082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 721082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek else { 72200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 724d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 725d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 7261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 7283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek "Loop condition is false. Exiting loop")); 7293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 7323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::WhileStmtClass: 7351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::ForStmtClass: { 7363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) { 7373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::string sbuf; 7383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::raw_string_ostream os(sbuf); 7391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek os << "Loop condition is false. "; 7413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 7423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 7433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 7441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 7463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek os.str())); 7473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 7493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 7513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 7521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 7545fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek "Loop condition is true. Entering loop body")); 7553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 7583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::IfStmtClass: { 7613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 7643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 7651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) 7673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 7685fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek "Taking false branch")); 7691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else 7703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, 7715fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek "Taking true branch")); 7721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 7743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 778dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (NextNode) { 7798e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add diagnostic pieces from custom visitors. 7808e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 7818e6431adab313e283a992698f6fc7afe62420999Anna Zaks for (BugReport::visitor_iterator I = R->visitor_begin(), 7828e6431adab313e283a992698f6fc7afe62420999Anna Zaks E = R->visitor_end(); I!=E; ++I) { 7838e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) 784dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek PD.push_front(p); 785dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 7868966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 7871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7889c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const PostStmt *PS = dyn_cast<PostStmt>(&P)) { 7893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Scan the region bindings, and see if a "notable" symbol has a new 7903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // lval binding. 7913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek ScanNotableSymbols SNS(N, PS->getStmt(), PDB.getBugReporter(), PD); 7923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PDB.getStateManager().iterBindings(N->getState(), SNS); 7933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 79614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // After constructing the full PathDiagnostic, do a pass over it to compact 79714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // PathDiagnosticPieces that occur within a macro. 79814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CompactPathDiagnostic(PD, PDB.getSourceManager()); 7993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 8003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 8013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 8025fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek// "Extensive" PathDiagnostic generation. 8035fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 8045fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 8055fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenekstatic bool IsControlFlowExpr(const Stmt *S) { 8065fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const Expr *E = dyn_cast<Expr>(S); 8071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8085fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (!E) 8095fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return false; 8101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump E = E->IgnoreParenCasts(); 8121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 81356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (isa<AbstractConditionalOperator>(E)) 8145fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 8151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8165fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) 8175fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 8185fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 8191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 8215fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek} 8225fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 82314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremeneknamespace { 824ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ContextLocation : public PathDiagnosticLocation { 8258f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsDead; 8268f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekpublic: 8278f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation(const PathDiagnosticLocation &L, bool isdead = false) 8288f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek : PathDiagnosticLocation(L), IsDead(isdead) {} 8291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void markDead() { IsDead = true; } 8318f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool isDead() const { return IsDead; } 8328f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek}; 8331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 834ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass EdgeBuilder { 8358f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek std::vector<ContextLocation> CLocs; 8368f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek typedef std::vector<ContextLocation>::iterator iterator; 83714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnostic &PD; 83814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB; 83914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation PrevLoc; 8401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8418f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsConsumedExpr(const PathDiagnosticLocation &L); 8421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 84314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek bool containsLocation(const PathDiagnosticLocation &Container, 84414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee); 8451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 84614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L); 8471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8489650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L, 8499650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek bool firstCharOnly = false) { 8508c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (const Stmt *S = L.asStmt()) { 8519650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek const Stmt *Original = S; 8528c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek while (1) { 8538c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek // Adjust the location for some expressions that are best referenced 8548c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek // by one of their subexpressions. 8559650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek switch (S->getStmtClass()) { 8569650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek default: 8579650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek break; 8589650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ParenExprClass: 859f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne case Stmt::GenericSelectionExprClass: 860f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne S = cast<Expr>(S)->IgnoreParens(); 8619650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 8629650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 86356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 8649650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ConditionalOperatorClass: 86556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall S = cast<AbstractConditionalOperator>(S)->getCond(); 8669650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 8679650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 8689650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ChooseExprClass: 8699650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek S = cast<ChooseExpr>(S)->getCond(); 8709650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 8719650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 8729650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::BinaryOperatorClass: 8739650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek S = cast<BinaryOperator>(S)->getLHS(); 8749650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 8759650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 8769650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek } 8771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8789650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek break; 8798c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 8801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8819650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek if (S != Original) 88223803374d8db054192ea6fcb766b87e04f26c8fbAnna Zaks L = PathDiagnosticLocation(S, L.getManager(), PDB.getLocationContext()); 8838c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 8841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8859650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek if (firstCharOnly) 8861531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks L = PathDiagnosticLocation::createSingleLocation(L); 8879650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek 8888c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek return L; 8898c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 8901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 89114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void popLocation() { 8928f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) { 8935c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // For contexts, we only one the first character as the range. 89407c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek rawAddEdge(cleanUpLocation(CLocs.back(), true)); 8955c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek } 89614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.pop_back(); 89714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 8981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 89914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekpublic: 90014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb) 90114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek : PD(pd), PDB(pdb) { 9021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 903a301a6773db085575ac51e3c966858180390c25bTed Kremenek // If the PathDiagnostic already has pieces, add the enclosing statement 904a301a6773db085575ac51e3c966858180390c25bTed Kremenek // of the first piece as a context as well. 90514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!PD.empty()) { 90614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PrevLoc = PD.begin()->getLocation(); 9071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 90814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = PrevLoc.asStmt()) 909e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 91014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 91114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 91214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 91314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ~EdgeBuilder() { 91414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) popLocation(); 9150cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 916a301a6773db085575ac51e3c966858180390c25bTed Kremenek // Finally, add an initial edge from the start location of the first 917a301a6773db085575ac51e3c966858180390c25bTed Kremenek // statement (if it doesn't already exist). 9180cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin( 9190cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PDB.getLocationContext(), 9200cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PDB.getSourceManager()); 9210cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks if (L.isValid()) 9220cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks rawAddEdge(L); 92314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 92414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 92514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false); 9261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9278bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek void rawAddEdge(PathDiagnosticLocation NewLoc); 9281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 92914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addContext(const Stmt *S); 930e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek void addExtendedContext(const Stmt *S); 9311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}; 93214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} // end anonymous namespace 93314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 93414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 93514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekPathDiagnosticLocation 93614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekEdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) { 93714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = L.asStmt()) { 93814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (IsControlFlowExpr(S)) 93914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 9401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return PDB.getEnclosingStmtLocation(S); 94214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 9431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 94414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 94514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 94614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 94714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekbool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container, 94814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee) { 94914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 95014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container == Containee) 95114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 9521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 95314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container.asDecl()) 95414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 9551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 95614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = Containee.asStmt()) 95714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *ContainerS = Container.asStmt()) { 95814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (S) { 95914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (S == ContainerS) 96014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 96114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek S = PDB.getParent(S); 96214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 96314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return false; 96414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 96514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 96614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Less accurate: compare using source ranges. 96714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContainerR = Container.asRange(); 96814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContaineeR = Containee.asRange(); 9691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 97014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceManager &SM = PDB.getSourceManager(); 971402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin()); 972402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd()); 973402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin()); 974402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd()); 9751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 976642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg); 977642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd); 978642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg); 979642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd); 9801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek assert(ContainerBegLine <= ContainerEndLine); 9821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(ContaineeBegLine <= ContaineeEndLine); 9831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return (ContainerBegLine <= ContaineeBegLine && 98514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ContainerEndLine >= ContaineeEndLine && 98614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerBegLine != ContaineeBegLine || 987a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerRBeg) <= 988a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContaineeRBeg)) && 98914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerEndLine != ContaineeEndLine || 990a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerREnd) >= 991a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerREnd))); 99214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 99314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 99414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) { 99514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!PrevLoc.isValid()) { 99614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PrevLoc = NewLoc; 99714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 99814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 9991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10008c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc); 10018c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc); 10021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10038c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (NewLocClean.asLocation() == PrevLocClean.asLocation()) 100414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 10051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 100614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // FIXME: Ignore intra-macro edges for now. 1007402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth if (NewLocClean.asLocation().getExpansionLoc() == 1008402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth PrevLocClean.asLocation().getExpansionLoc()) 100914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 101014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 10118c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek PD.push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean)); 10128c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek PrevLoc = NewLoc; 101314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 101414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 101514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) { 10161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1017a301a6773db085575ac51e3c966858180390c25bTed Kremenek if (!alwaysAdd && NewLoc.asLocation().isMacroID()) 1018a301a6773db085575ac51e3c966858180390c25bTed Kremenek return; 10191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 102014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc); 102114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 102214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 10238f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation &TopContextLoc = CLocs.back(); 10241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 102514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 102614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == CLoc) { 10278f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 10284c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek if (IsConsumedExpr(TopContextLoc) && 10294c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek !IsControlFlowExpr(TopContextLoc.asStmt())) 10308f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek TopContextLoc.markDead(); 10318f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek 103214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 10338f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 103414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 103514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 103614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 103714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 103814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, CLoc)) { 10398f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 104014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 10411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10424c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek if (IsConsumedExpr(CLoc) && !IsControlFlowExpr(CLoc.asStmt())) { 10438f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek CLocs.push_back(ContextLocation(CLoc, true)); 10448f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return; 10458f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 10468f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 10471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 104814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(CLoc); 10491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 105014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 105114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 105214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 105314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 105414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 10551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10565c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // If we reach here, there is no enclosing context. Just add the edge. 10575c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek rawAddEdge(NewLoc); 105814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 105914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 10608f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekbool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) { 10618f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt())) 10628f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X); 10631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10648f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return false; 10658f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek} 10661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1067e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenekvoid EdgeBuilder::addExtendedContext(const Stmt *S) { 1068e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (!S) 1069e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek return; 10701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const Stmt *Parent = PDB.getParent(S); 1072e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek while (Parent) { 1073e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (isa<CompoundStmt>(Parent)) 1074e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek Parent = PDB.getParent(Parent); 1075e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek else 1076e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1077e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1078e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek 1079e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (Parent) { 1080e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek switch (Parent->getStmtClass()) { 1081e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::DoStmtClass: 1082e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 1083e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(Parent); 1084e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek default: 1085e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1086e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1087e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 10881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1089e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(S); 1090e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek} 10911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 109214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addContext(const Stmt *S) { 109314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!S) 109414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 109514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 1096220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.getLocationContext()); 10971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 109814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 109914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &TopContextLoc = CLocs.back(); 110014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 110114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 110214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == L) 110314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 110414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 110514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, L)) { 110614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 11071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 110814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 110914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 111014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 111114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 111214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 111314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 111414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 111514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 111614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 111714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekstatic void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, 111814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB, 1119c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode *N) { 112014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder EB(PD, PDB); 11210cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks const SourceManager& SM = PDB.getSourceManager(); 112214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 11239c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); 112414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (NextNode) { 112514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek N = NextNode; 112614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek NextNode = GetPredecessorNode(N); 112714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ProgramPoint P = N->getLocation(); 112814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 1129dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek do { 1130dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Block edges. 1131dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 1132dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek const CFGBlock &Blk = *BE->getSrc(); 1133dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek const Stmt *Term = Blk.getTerminator(); 11341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1135dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Are we jumping to the head of a loop? Add a special diagnostic. 1136ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (const Stmt *Loop = BE->getDst()->getLoopTarget()) { 11370cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation L(Loop, SM, PDB.getLocationContext()); 1138ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const CompoundStmt *CS = NULL; 11391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1140ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (!Term) { 1141ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) 1142ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek CS = dyn_cast<CompoundStmt>(FS->getBody()); 1143ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) 11441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CS = dyn_cast<CompoundStmt>(WS->getBody()); 1145ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek } 11461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1147dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek PathDiagnosticEventPiece *p = 1148dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek new PathDiagnosticEventPiece(L, 114907c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek "Looping back to the head of the loop"); 11501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1151dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek EB.addEdge(p->getLocation(), true); 1152dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek PD.push_front(p); 11531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1154ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (CS) { 11550cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation BL = 11560cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createEndBrace(CS, SM); 115707c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek EB.addEdge(BL); 1158dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 11598bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 11601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1161ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (Term) 1162ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek EB.addContext(Term); 11631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1164dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 11658bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 116614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 11671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) { 11683c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (const CFGStmt *S = BE->getFirstElement().getAs<CFGStmt>()) { 11693c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const Stmt *stmt = S->getStmt(); 11703c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (IsControlFlowExpr(stmt)) { 1171b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu // Add the proper context for '&&', '||', and '?'. 11723c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addContext(stmt); 1173b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 1174b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu else 11753c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt()); 1176dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 1177b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu 1178dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 1179dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 1180dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } while (0); 11811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1182dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (!NextNode) 118314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek continue; 11841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11858e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add pieces from custom visitors. 11868e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 11878e6431adab313e283a992698f6fc7afe62420999Anna Zaks for (BugReport::visitor_iterator I = R->visitor_begin(), 11888e6431adab313e283a992698f6fc7afe62420999Anna Zaks E = R->visitor_end(); I!=E; ++I) { 11898e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 11908966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek const PathDiagnosticLocation &Loc = p->getLocation(); 11918966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek EB.addEdge(Loc, true); 11928966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek PD.push_front(p); 11938966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek if (const Stmt *S = Loc.asStmt()) 11941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 11958966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 11961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 119714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 119814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 119914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 12005fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 12013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugType and subclasses. 12023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 1203404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios KyrtzidisBugType::~BugType() { } 1204404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 12053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugType::FlushReports(BugReporter &BR) {} 12063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 12073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 12083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReport and subclasses. 12093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 1210e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 12118e6431adab313e283a992698f6fc7afe62420999Anna Zaksvoid BugReport::addVisitor(BugReporterVisitor* visitor) { 12128e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (!visitor) 12138e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 12148e6431adab313e283a992698f6fc7afe62420999Anna Zaks 12158e6431adab313e283a992698f6fc7afe62420999Anna Zaks llvm::FoldingSetNodeID ID; 12168e6431adab313e283a992698f6fc7afe62420999Anna Zaks visitor->Profile(ID); 12178e6431adab313e283a992698f6fc7afe62420999Anna Zaks void *InsertPos; 12188e6431adab313e283a992698f6fc7afe62420999Anna Zaks 12198e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) { 12208e6431adab313e283a992698f6fc7afe62420999Anna Zaks delete visitor; 12218e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 12228e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 12238e6431adab313e283a992698f6fc7afe62420999Anna Zaks 12248e6431adab313e283a992698f6fc7afe62420999Anna Zaks CallbacksSet.InsertNode(visitor, InsertPos); 12258e6431adab313e283a992698f6fc7afe62420999Anna Zaks Callbacks = F.add(visitor, Callbacks); 12268e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 12278e6431adab313e283a992698f6fc7afe62420999Anna Zaks 12288e6431adab313e283a992698f6fc7afe62420999Anna ZaksBugReport::~BugReport() { 12298e6431adab313e283a992698f6fc7afe62420999Anna Zaks for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) { 1230dc757b049796949e4b11646445a6598f0bdabd7aAnna Zaks delete *I; 12318e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 12328e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 1233e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 1234e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaksvoid BugReport::Profile(llvm::FoldingSetNodeID& hash) const { 1235e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddPointer(&BT); 1236e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddString(Description); 1237590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks if (Location.isValid()) { 1238590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks Location.Profile(hash); 1239590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } else { 1240590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(ErrorNode); 1241590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode)); 1242590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } 1243e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 1244e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks for (SmallVectorImpl<SourceRange>::const_iterator I = 1245e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks Ranges.begin(), E = Ranges.end(); I != E; ++I) { 1246e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks const SourceRange range = *I; 1247e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!range.isValid()) 1248e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks continue; 1249e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getBegin().getRawEncoding()); 1250e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getEnd().getRawEncoding()); 1251e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 1252e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks} 12533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 12549c378f705405d37f49795d5e915989de774fe11fTed Kremenekconst Stmt *BugReport::getStmt() const { 1255e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!ErrorNode) 1256e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return 0; 1257e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 1258212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care ProgramPoint ProgP = ErrorNode->getLocation(); 12595f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek const Stmt *S = NULL; 12601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12619c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (BlockEntrance *BE = dyn_cast<BlockEntrance>(&ProgP)) { 1262fafd3834754d2093e0ad7a1c005860fd527ecb7fZhongxing Xu CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit(); 126350d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu if (BE->getBlock() == &Exit) 1264212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care S = GetPreviousStmt(ErrorNode); 12653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 12665f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (!S) 12671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump S = GetStmt(ProgP); 12681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return S; 12703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 12713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1272640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidisstd::pair<BugReport::ranges_iterator, BugReport::ranges_iterator> 1273e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna ZaksBugReport::getRanges() { 1274e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // If no custom ranges, add the range of the statement corresponding to 1275e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // the error node. 1276e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (Ranges.empty()) { 1277e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (const Expr *E = dyn_cast_or_null<Expr>(getStmt())) 1278e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks addRange(E->getSourceRange()); 1279e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks else 1280e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 1281e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 1282e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 128314924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks // User-specified absence of range info. 128414924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks if (Ranges.size() == 1 && !Ranges.begin()->isValid()) 128514924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 128614924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks 1287e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(Ranges.begin(), Ranges.end()); 12883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 12893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1290590dd8e0959d8df5621827768987c4792b74fc06Anna ZaksPathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const { 1291b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks if (ErrorNode) { 1292590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(!Location.isValid() && 1293b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks "Either Location or ErrorNode should be specified but not both."); 1294b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks 12959c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const Stmt *S = GetCurrentOrPreviousStmt(ErrorNode)) { 1296590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks const LocationContext *LC = ErrorNode->getLocationContext(); 1297590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks 12983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // For member expressions, return the location of the '.' or '->'. 12995b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) 1300590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createMemberLoc(ME, SM); 13015b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek // For binary operators, return the location of the operator. 13025b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) 1303590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createOperatorLoc(B, SM); 13043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1305590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createBegin(S, SM, LC); 13063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1307b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } else { 1308b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks assert(Location.isValid()); 1309b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks return Location; 1310b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } 1311b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks 1312590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation(); 13133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 13143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 13163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReporter and subclasses. 13173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 13183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13193106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReportEquivClass::~BugReportEquivClass() { 13208966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek for (iterator I=begin(), E=end(); I!=E; ++I) delete *I; 13213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 13223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1323a2f4ec0df645fc249d2945beef9653f03b175417Zhongxing XuGRBugReporter::~GRBugReporter() { } 13243106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReporterData::~BugReporterData() {} 13253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 132638b02b912e1a55c912f603c4369431264d36a381Zhongxing XuExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); } 13273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 132818c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekProgramStateManager& 13293106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekGRBugReporter::getStateManager() { return Eng.getStateManager(); } 13303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13313b030a28cda2b953758507769c1d436bec5ec45eAnna ZaksBugReporter::~BugReporter() { 13323b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks FlushReports(); 13333b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks 13343b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks // Free the bug reports we are tracking. 13353b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks typedef std::vector<BugReportEquivClass *> ContTy; 13363b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end(); 13373b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks I != E; ++I) { 13383b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks delete *I; 13393b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks } 13403b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks} 13413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugReporter::FlushReports() { 13433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (BugTypes.isEmpty()) 13443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return; 13453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // First flush the warnings for each BugType. This may end up creating new 1347404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // warnings and new BugTypes. 1348404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: Only NSErrorChecker needs BugType's FlushReports. 1349404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // Turn NSErrorChecker into a proper checker and remove this. 13505f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<const BugType*, 16> bugTypes; 13513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) 1352404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis bugTypes.push_back(*I); 13535f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVector<const BugType*, 16>::iterator 1354404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I) 13553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const_cast<BugType*>(*I)->FlushReports(*this); 13563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1357404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis typedef llvm::FoldingSet<BugReportEquivClass> SetTy; 1358404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis for (SetTy::iterator EI=EQClasses.begin(), EE=EQClasses.end(); EI!=EE;++EI){ 1359404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugReportEquivClass& EQ = *EI; 1360404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis FlushReport(EQ); 13613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 13623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1363404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // BugReporter owns and deletes only BugTypes created implicitly through 1364404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // EmitBasicReport. 1365404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: There are leaks from checkers that assume that the BugTypes they 1366404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // create will be destroyed by the BugReporter. 1367404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis for (llvm::StringMap<BugType*>::iterator 1368404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I) 1369404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis delete I->second; 1370404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 13713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Remove all references to the BugType objects. 13723baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.getEmptySet(); 13733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 13743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 13763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnostics generation. 13773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 13783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 137938b02b912e1a55c912f603c4369431264d36a381Zhongxing Xustatic std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, 1380c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::pair<ExplodedNode*, unsigned> > 138138b02b912e1a55c912f603c4369431264d36a381Zhongxing XuMakeReportGraph(const ExplodedGraph* G, 13825f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<const ExplodedNode*> &nodes) { 13831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the trimmed graph. It will contain the shortest paths from the 13851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // error nodes to the root. In the new graph we should only have one 13863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // error node unless there are two or more error nodes with the same minimum 13873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // path length. 138838b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu ExplodedGraph* GTrim; 1389c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu InterExplodedGraphMap* NMap; 13903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 13913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*, const void*> InverseMap; 139240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek llvm::tie(GTrim, NMap) = G->Trim(nodes.data(), nodes.data() + nodes.size(), 139340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek &InverseMap); 13941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create owning pointers for GTrim and NMap just to ensure that they are 13963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // released when this function exists. 139738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu llvm::OwningPtr<ExplodedGraph> AutoReleaseGTrim(GTrim); 1398c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu llvm::OwningPtr<InterExplodedGraphMap> AutoReleaseNMap(NMap); 13991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the (first) error node in the trimmed graph. We just need to consult 14013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // the node map (NMap) which maps from nodes in the original graph to nodes 14023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // in the new graph. 1403938332c657390d1e782e0adc03b092993edae962Ted Kremenek 1404c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::queue<const ExplodedNode*> WS; 140538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu typedef llvm::DenseMap<const ExplodedNode*, unsigned> IndexMapTy; 1406938332c657390d1e782e0adc03b092993edae962Ted Kremenek IndexMapTy IndexMap; 14073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 140840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek for (unsigned nodeIndex = 0 ; nodeIndex < nodes.size(); ++nodeIndex) { 140940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek const ExplodedNode *originalNode = nodes[nodeIndex]; 141040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (const ExplodedNode *N = NMap->getMappedNode(originalNode)) { 1411938332c657390d1e782e0adc03b092993edae962Ted Kremenek WS.push(N); 141240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek IndexMap[originalNode] = nodeIndex; 14133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 141440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 14151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1416938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(!WS.empty() && "No error node found in the trimmed graph."); 14173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 14183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create a new (third!) graph with a single path. This is the graph 14193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // that will be returned to the caller. 1420c77a55126fcad66fb086f8e100a494caa2496a2dZhongxing Xu ExplodedGraph *GNew = new ExplodedGraph(); 14211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Sometimes the trimmed graph can contain a cycle. Perform a reverse BFS 14233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // to the root node, and then construct a new graph that contains only 14243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // a single path. 14253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*,unsigned> Visited; 14261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek unsigned cnt = 0; 14289c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *Root = 0; 14291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!WS.empty()) { 14319c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *Node = WS.front(); 14323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek WS.pop(); 14331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Visited.find(Node) != Visited.end()) 14353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 14361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Visited[Node] = cnt++; 14381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Node->pred_empty()) { 14403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Root = Node; 14413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 14423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 14431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1444c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu for (ExplodedNode::const_pred_iterator I=Node->pred_begin(), 14453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek E=Node->pred_end(); I!=E; ++I) 14463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek WS.push(*I); 14473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 14481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1449938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(Root); 14501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now walk from the root down the BFS path, always taking the successor 14523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // with the lowest number. 14531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ExplodedNode *Last = 0, *First = 0; 14543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NodeBackMap *BM = new NodeBackMap(); 1455938332c657390d1e782e0adc03b092993edae962Ted Kremenek unsigned NodeIndex = 0; 14561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1457c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu for ( const ExplodedNode *N = Root ;;) { 14583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Lookup the number associated with the current node. 14593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*,unsigned>::iterator I = Visited.find(N); 1460938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(I != Visited.end()); 14611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the equivalent node in the new graph with the same state 14633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // and location. 14649c378f705405d37f49795d5e915989de774fe11fTed Kremenek ExplodedNode *NewN = GNew->getNode(N->getLocation(), N->getState()); 14651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Store the mapping to the original node. 14673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::DenseMap<const void*, const void*>::iterator IMitr=InverseMap.find(N); 14683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(IMitr != InverseMap.end() && "No mapping to original node."); 1469c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu (*BM)[NewN] = (const ExplodedNode*) IMitr->second; 14701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Link up the new node with the previous node. 14723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Last) 14735fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek NewN->addPredecessor(Last, *GNew); 14741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Last = NewN; 14761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Are we at the final node? 1478938332c657390d1e782e0adc03b092993edae962Ted Kremenek IndexMapTy::iterator IMI = 1479c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu IndexMap.find((const ExplodedNode*)(IMitr->second)); 1480938332c657390d1e782e0adc03b092993edae962Ted Kremenek if (IMI != IndexMap.end()) { 14813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek First = NewN; 1482938332c657390d1e782e0adc03b092993edae962Ted Kremenek NodeIndex = IMI->second; 14833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 14843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 14851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the next successor node. We choose the node that is marked 14873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // with the lowest DFS number. 1488c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::const_succ_iterator SI = N->succ_begin(); 1489c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::const_succ_iterator SE = N->succ_end(); 14903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek N = 0; 14911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (unsigned MinVal = 0; SI != SE; ++SI) { 14931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek I = Visited.find(*SI); 14951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (I == Visited.end()) 14973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 14981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!N || I->second < MinVal) { 15003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek N = *SI; 15013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MinVal = I->second; 15023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1505938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(N); 15063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1508938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(First); 1509938332c657390d1e782e0adc03b092993edae962Ted Kremenek 15103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return std::make_pair(std::make_pair(GNew, BM), 15113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::make_pair(First, NodeIndex)); 15123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 1513d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 15143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object 15153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// and collapses PathDiagosticPieces that are expanded by macros. 15163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekstatic void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) { 15173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek typedef std::vector<std::pair<PathDiagnosticMacroPiece*, SourceLocation> > 15183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStackTy; 15191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek typedef std::vector<PathDiagnosticPiece*> 15213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy; 15221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStackTy MacroStack; 15243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy Pieces; 15251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (PathDiagnostic::iterator I = PD.begin(), E = PD.end(); I!=E; ++I) { 15273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Get the location of the PathDiagnosticPiece. 15281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const FullSourceLoc Loc = I->getLocation().asLocation(); 15291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine the instantiation location, which is the location we group 15313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // related PathDiagnosticPieces. 15321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation InstantiationLoc = Loc.isMacroID() ? 1533402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 15343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 15351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Loc.isFileID()) { 15373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.clear(); 15383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Pieces.push_back(&*I); 15393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 15403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1541706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek 15423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(Loc.isMacroID()); 15431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Is the PathDiagnosticPiece within the same macro group? 15453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) { 15463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.back().first->push_back(&*I); 15473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 15483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1549d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 15503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // We aren't in the same group. Are we descending into a new macro 15513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // or are part of an old one? 15523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticMacroPiece *MacroGroup = 0; 1553d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 15543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ? 1555402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 15563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 15571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Walk the entire macro stack. 15593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!MacroStack.empty()) { 15603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (InstantiationLoc == MacroStack.back().second) { 15613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 15623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 15633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (ParentInstantiationLoc == MacroStack.back().second) { 15663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 15673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 156861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 15691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.pop_back(); 15716837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek } 15721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) { 15743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create a new macro group and add it to the stack. 1575590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticMacroPiece *NewGroup = 1576590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks new PathDiagnosticMacroPiece( 1577590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation::createSingleLocation(I->getLocation())); 15785a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek 15793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (MacroGroup) 15803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup->push_back(NewGroup); 15813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 15823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(InstantiationLoc.isFileID()); 15833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Pieces.push_back(NewGroup); 15843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = NewGroup; 15873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc)); 15887dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 15893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 15903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Finally, add the PathDiagnosticPiece to the group. 15913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup->push_back(&*I); 15923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 15931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now take the pieces and construct a new PathDiagnostic. 15953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PD.resetPath(false); 15961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) { 15983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (PathDiagnosticMacroPiece *MP=dyn_cast<PathDiagnosticMacroPiece>(*I)) 15993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MP->containsEvent()) { 16003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek delete MP; 16013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 16023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 16031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PD.push_back(*I); 160561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 160661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 160761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 16083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, 16095f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<BugReport *> &bugReports) { 16101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 161140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek assert(!bugReports.empty()); 16125f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<const ExplodedNode *, 10> errorNodes; 16135f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVectorImpl<BugReport*>::iterator I = bugReports.begin(), 161440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek E = bugReports.end(); I != E; ++I) { 161540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek errorNodes.push_back((*I)->getErrorNode()); 161640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 16171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Construct a new graph that contains only a single path from the error 16191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // node to a root. 162038b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu const std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, 1621c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu std::pair<ExplodedNode*, unsigned> >& 162240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek GPair = MakeReportGraph(&getGraph(), errorNodes); 16231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the BugReport with the original location. 162540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek assert(GPair.second.second < bugReports.size()); 162640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *R = bugReports[GPair.second.second]; 16273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(R && "No original report found for sliced graph."); 16281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 162938b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu llvm::OwningPtr<ExplodedGraph> ReportGraph(GPair.first.first); 16303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::OwningPtr<NodeBackMap> BackMap(GPair.first.second); 1631c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const ExplodedNode *N = GPair.second.first; 16321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Start building the path diagnostic... 1634ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticBuilder PDB(*this, R, BackMap.get(), 1635ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie getPathDiagnosticConsumer()); 16361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16378e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Register additional node visitors. 163850bbc165b063155cc23c360deb7b865502e068e2Anna Zaks R->addVisitor(new NilReceiverBRVisitor()); 163950bbc165b063155cc23c360deb7b865502e068e2Anna Zaks R->addVisitor(new ConditionBRVisitor()); 16401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 164123f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks // Generate the very last diagnostic piece - the piece is visible before 164223f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks // the trace is expanded. 164323f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks PathDiagnosticPiece *LastPiece = 0; 164423f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks for (BugReport::visitor_iterator I = R->visitor_begin(), 164523f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks E = R->visitor_end(); I!=E; ++I) { 164623f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) { 164723f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks assert (!LastPiece && 164823f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks "There can only be one final piece in a diagnostic."); 164923f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks LastPiece = Piece; 165023f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks } 165123f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks } 165223f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks if (!LastPiece) 165323f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R); 165423f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks if (LastPiece) 165523f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks PD.push_back(LastPiece); 165623f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks else 165723f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks return; 165823f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks 16593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek switch (PDB.getGenerationScheme()) { 1660ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie case PathDiagnosticConsumer::Extensive: 16618966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek GenerateExtensivePathDiagnostic(PD, PDB, N); 16625fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek break; 1663ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie case PathDiagnosticConsumer::Minimal: 16643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek GenerateMinimalPathDiagnostic(PD, PDB, N); 16653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 16663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 16673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 16681aa44c7c9198796085b77c6bdd7c90030845a688Ted Kremenek 1669cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::Register(BugType *BT) { 16703baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.add(BugTypes, BT); 167176d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek} 167276d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek 16731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid BugReporter::EmitReport(BugReport* R) { 1674cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // Compute the bug report's hash to determine its equivalence class. 1675cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek llvm::FoldingSetNodeID ID; 1676cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek R->Profile(ID); 16771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Lookup the equivance class. If there isn't one, create it. 1679cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek BugType& BT = R->getBugType(); 1680cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek Register(&BT); 1681cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek void *InsertPos; 1682404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos); 16831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1684cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek if (!EQ) { 1685cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ = new BugReportEquivClass(R); 1686404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis EQClasses.InsertNode(EQ, InsertPos); 16873b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks EQClassesVector.push_back(EQ); 1688cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek } 1689cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek else 1690cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ->AddReport(R); 169161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 169261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 169306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 169406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 169506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek// Emitting reports in equivalence classes. 169606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 169706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 169806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremeneknamespace { 1699ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamstruct FRIEC_WLItem { 170006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *N; 170106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek ExplodedNode::const_succ_iterator I, E; 170206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 170306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek FRIEC_WLItem(const ExplodedNode *n) 170406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek : N(n), I(N->succ_begin()), E(N->succ_end()) {} 170506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek}; 170606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek} 170706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 170861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenekstatic BugReport * 170961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted KremenekFindReportInEquivalenceClass(BugReportEquivClass& EQ, 17105f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<BugReport*> &bugReports) { 171161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 171206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end(); 171306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(I != E); 171406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek BugReport *R = *I; 171506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek BugType& BT = R->getBugType(); 171661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 171740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // If we don't need to suppress any of the nodes because they are 171840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // post-dominated by a sink, simply add all the nodes in the equivalence class 171940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // to 'Nodes'. Any of the reports will serve as a "representative" report. 172061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!BT.isSuppressOnSink()) { 172161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) { 17229c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N = I->getErrorNode(); 172361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (N) { 172461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek R = *I; 172540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek bugReports.push_back(R); 172661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 172761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 172806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek return R; 172961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 173061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 173106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // For bug reports that should be suppressed when all paths are post-dominated 173206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // by a sink node, iterate through the reports in the equivalence class 173306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // until we find one that isn't post-dominated (if one exists). We use a 173406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // DFS traversal of the ExplodedGraph to find a non-sink node. We could write 173506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // this as a recursive function, but we don't want to risk blowing out the 173606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // stack for very long paths. 173740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = 0; 173861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 173906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; I != E; ++I) { 174006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek R = *I; 174140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek const ExplodedNode *errorNode = R->getErrorNode(); 174206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 174340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!errorNode) 174406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 174540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->isSink()) { 1746b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable( 174706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek "BugType::isSuppressSink() should not be 'true' for sink end nodes"); 174806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 174961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // No successors? By definition this nodes isn't post-dominated by a sink. 175040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->succ_empty()) { 175140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek bugReports.push_back(R); 175240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 175340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek exampleReport = R; 175461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek continue; 175561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 175661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 175706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // At this point we know that 'N' is not a sink and it has at least one 175806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // successor. Use a DFS worklist to find a non-sink end-of-path node. 175906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek typedef FRIEC_WLItem WLItem; 17605f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<WLItem, 10> DFSWorkList; 176106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek llvm::DenseMap<const ExplodedNode *, unsigned> Visited; 176206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 176306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek DFSWorkList WL; 176440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek WL.push_back(errorNode); 176540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek Visited[errorNode] = 1; 176606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 176706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek while (!WL.empty()) { 176806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WLItem &WI = WL.back(); 176906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(!WI.N->succ_empty()); 177006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 177106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; WI.I != WI.E; ++WI.I) { 177206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *Succ = *WI.I; 177306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // End-of-path node? 177406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (Succ->succ_empty()) { 177561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // If we found an end-of-path node that is not a sink. 177661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!Succ->isSink()) { 177740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek bugReports.push_back(R); 177840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 177940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek exampleReport = R; 178061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek WL.clear(); 178161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek break; 178261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 178306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Found a sink? Continue on to the next successor. 178406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 178506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 178606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Mark the successor as visited. If it hasn't been explored, 178706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // enqueue it to the DFS worklist. 178806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek unsigned &mark = Visited[Succ]; 178906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (!mark) { 179006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek mark = 1; 179106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.push_back(Succ); 179206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek break; 179306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 179406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 179561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 179661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // The worklist may have been cleared at this point. First 179761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // check if it is empty before checking the last item. 179861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!WL.empty() && &WL.back() == &WI) 179906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.pop_back(); 180006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 180106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 180206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 180361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // ExampleReport will be NULL if all the nodes in the equivalence class 180461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // were post-dominated by sinks. 180540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek return exampleReport; 180661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek} 1807e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1808e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek//===----------------------------------------------------------------------===// 1809e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek// DiagnosticCache. This is a hack to cache analyzer diagnostics. It 1810e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek// uses global state, which eventually should go elsewhere. 1811e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek//===----------------------------------------------------------------------===// 1812e0a58073b76fc016325a35152533b8468df2bf4aTed Kremeneknamespace { 1813ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass DiagCacheItem : public llvm::FoldingSetNode { 1814e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek llvm::FoldingSetNodeID ID; 1815e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenekpublic: 1816e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek DiagCacheItem(BugReport *R, PathDiagnostic *PD) { 18174522e2a9e7fa0313e8e5a388d8f0ab66feccc6afAnna Zaks R->Profile(ID); 18184522e2a9e7fa0313e8e5a388d8f0ab66feccc6afAnna Zaks PD->Profile(ID); 1819e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek } 1820e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1821e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek void Profile(llvm::FoldingSetNodeID &id) { 1822e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek id = ID; 1823e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek } 1824e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1825e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek llvm::FoldingSetNodeID &getID() { return ID; } 1826e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek}; 1827e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek} 1828e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1829e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenekstatic bool IsCachedDiagnostic(BugReport *R, PathDiagnostic *PD) { 1830e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek // FIXME: Eventually this diagnostic cache should reside in something 1831e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek // like AnalysisManager instead of being a static variable. This is 1832e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek // really unsafe in the long term. 1833e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek typedef llvm::FoldingSet<DiagCacheItem> DiagnosticCache; 1834e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek static DiagnosticCache DC; 1835e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1836e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek void *InsertPos; 1837e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek DiagCacheItem *Item = new DiagCacheItem(R, PD); 1838e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1839e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek if (DC.FindNodeOrInsertPos(Item->getID(), InsertPos)) { 1840e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek delete Item; 1841e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek return true; 1842e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek } 1843e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1844e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek DC.InsertNode(Item, InsertPos); 1845e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek return false; 1846e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek} 1847e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1848cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::FlushReport(BugReportEquivClass& EQ) { 18495f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BugReport*, 10> bugReports; 185040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports); 185140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 185206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek return; 185306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 1854ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer* PD = getPathDiagnosticConsumer(); 18551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1856cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // FIXME: Make sure we use the 'R' for the path that was actually used. 18571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Probably doesn't make a difference in practice. 185840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugType& BT = exampleReport->getBugType(); 18591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1860d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek llvm::OwningPtr<PathDiagnostic> 186140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek D(new PathDiagnostic(exampleReport->getBugType().getName(), 1862da0e8429a3598acfdd0ecf15135d432e4dd3517cTed Kremenek !PD || PD->useVerboseDescription() 186340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek ? exampleReport->getDescription() 186440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek : exampleReport->getShortDescription(), 1865d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek BT.getCategory())); 1866d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek 186740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!bugReports.empty()) 186840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek GeneratePathDiagnostic(*D.get(), bugReports); 18691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 187040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (IsCachedDiagnostic(exampleReport, D.get())) 1871e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek return; 1872e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 1873072192bcbb05a0fee7ec3061750b27e8d2004952Ted Kremenek // Get the meta data. 18747f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks const BugReport::ExtraTextList &Meta = 18757f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks exampleReport->getExtraText(); 18767f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks for (BugReport::ExtraTextList::const_iterator i = Meta.begin(), 18777f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks e = Meta.end(); i != e; ++i) { 18787f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks D->addMeta(*i); 18797f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks } 188075840e1501563fe7c3dcb5600b75965ba1fe1bc4Ted Kremenek 18813148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek // Emit a summary diagnostic to the regular Diagnostics engine. 1882640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis BugReport::ranges_iterator Beg, End; 1883640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis llvm::tie(Beg, End) = exampleReport->getRanges(); 1884d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &Diag = getDiagnostic(); 1885c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek 1886c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek // Search the description for '%', as that will be interpretted as a 1887c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek // format character by FormatDiagnostics. 18885f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef desc = exampleReport->getShortDescription(); 1889c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek unsigned ErrorDiag; 1890c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek { 1891c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek llvm::SmallString<512> TmpStr; 1892c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek llvm::raw_svector_ostream Out(TmpStr); 18935f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I) 1894c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek if (*I == '%') 1895c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek Out << "%%"; 1896c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek else 1897c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek Out << *I; 1898c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek 1899c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek Out.flush(); 1900d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie ErrorDiag = Diag.getCustomDiagID(DiagnosticsEngine::Warning, TmpStr); 1901c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek } 19020a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner 1903b6b7e7bff3101062521de6e79533a3c25e2195d9Argyrios Kyrtzidis { 1904590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks DiagnosticBuilder diagBuilder = Diag.Report( 1905590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks exampleReport->getLocation(getSourceManager()).asLocation(), ErrorDiag); 1906640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis for (BugReport::ranges_iterator I = Beg; I != End; ++I) 1907b6b7e7bff3101062521de6e79533a3c25e2195d9Argyrios Kyrtzidis diagBuilder << *I; 19082f0e89ea96292d2974eb1a7dddc0e9870aa86bb7Ted Kremenek } 19093148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek 1910ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie // Emit a full diagnostic for the path if we have a PathDiagnosticConsumer. 19113148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek if (!PD) 19123148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek return; 19131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (D->empty()) { 1915590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticPiece *piece = new PathDiagnosticEventPiece( 1916590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks exampleReport->getLocation(getSourceManager()), 1917590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks exampleReport->getDescription()); 19181fbfd5b9b8b82aea084773b76dd1ec6796a7000cTed Kremenek 19193148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek for ( ; Beg != End; ++Beg) piece->addRange(*Beg); 19203148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek D->push_back(piece); 19213148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek } 19221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19233148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek PD->HandlePathDiagnostic(D.take()); 192461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 192557202071e477530e9348bc76671ee369b2399b92Ted Kremenek 19265f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid BugReporter::EmitBasicReport(StringRef name, StringRef str, 1927590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation Loc, 19288c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek SourceRange* RBeg, unsigned NumRanges) { 19298c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek EmitBasicReport(name, "", str, Loc, RBeg, NumRanges); 19308c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek} 1931cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 19325f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid BugReporter::EmitBasicReport(StringRef name, 19335f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category, 1934590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks StringRef str, PathDiagnosticLocation Loc, 19358c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek SourceRange* RBeg, unsigned NumRanges) { 19361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1937404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // 'BT' is owned by BugReporter. 1938404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = getBugTypeForName(name, category); 1939590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks BugReport *R = new BugReport(*BT, str, Loc); 1940cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg); 1941cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EmitReport(R); 1942cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek} 1943404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 19445f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerBugType *BugReporter::getBugTypeForName(StringRef name, 19455f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category) { 1946404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::SmallString<136> fullDesc; 1947404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::raw_svector_ostream(fullDesc) << name << ":" << category; 1948404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::StringMapEntry<BugType *> & 1949404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry = StrBugTypes.GetOrCreateValue(fullDesc); 1950404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = entry.getValue(); 1951404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis if (!BT) { 1952404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BT = new BugType(name, category); 1953404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry.setValue(BT); 1954404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis } 1955404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis return BT; 1956404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis} 1957