BugReporter.cpp revision a5f80b2ea6d30c5055c067530d63bb0dcaf937d0
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 15cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose#define DEBUG_TYPE "BugReporter" 16cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose 179b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 1861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/AST/ASTContext.h" 19c35fb7d67d515659ad2325b4f6ec97c9fe64fb63Benjamin Kramer#include "clang/AST/DeclObjC.h" 2061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/AST/Expr.h" 2100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek#include "clang/AST/ParentMap.h" 2216f0049415ec596504891259e2a83e19871c0d52Chris Lattner#include "clang/AST/StmtObjC.h" 2355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/CFG.h" 2461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/Analysis/ProgramPoint.h" 2555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/SourceManager.h" 2655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 279b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 2855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 29331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek#include "llvm/ADT/DenseMap.h" 30802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek#include "llvm/ADT/IntrusiveRefCntPtr.h" 3155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/OwningPtr.h" 3255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/STLExtras.h" 3355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/SmallString.h" 34cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose#include "llvm/ADT/Statistic.h" 3555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/raw_ostream.h" 3610aa55410bbecbb658ce14a5f801d50cf06d12dfTed Kremenek#include <queue> 3761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 3861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenekusing namespace clang; 399ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 4061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 41cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan RoseSTATISTIC(MaxBugClassSize, 42cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose "The maximum number of bug reports in the same equivalence class"); 43cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan RoseSTATISTIC(MaxValidBugClassSize, 44cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose "The maximum number of bug reports in the same equivalence class " 45cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose "where at least one report is valid (not suppressed)"); 46cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose 478966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed KremenekBugReporterVisitor::~BugReporterVisitor() {} 481b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek 4999ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BugReporterContext::anchor() {} 5099ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 51cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Helper routines for walking the ExplodedGraph and fetching statements. 53cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 5461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 559c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic inline const Stmt *GetStmt(const ProgramPoint &P) { 567a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) 57592362b46ad69db0db0988e7f9d8cbe647510bddTed Kremenek return SP->getStmt(); 587a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) 5961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek return BE->getSrc()->getTerminator(); 607a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallEnter> CE = P.getAs<CallEnter>()) 61852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose return CE->getCallExpr(); 627a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) 63852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose return CEE->getCalleeContext()->getCallSite(); 641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 65b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return 0; 6661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 6761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 68c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic inline const ExplodedNode* 699c378f705405d37f49795d5e915989de774fe11fTed KremenekGetPredecessorNode(const ExplodedNode *N) { 70b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return N->pred_empty() ? NULL : *(N->pred_begin()); 71706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek} 72706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek 73c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic inline const ExplodedNode* 749c378f705405d37f49795d5e915989de774fe11fTed KremenekGetSuccessorNode(const ExplodedNode *N) { 75b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return N->succ_empty() ? NULL : *(N->succ_begin()); 76bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek} 772673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek 789c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic const Stmt *GetPreviousStmt(const ExplodedNode *N) { 79b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek for (N = GetPredecessorNode(N); N; N = GetPredecessorNode(N)) 805f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) 81b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 83b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return 0; 84b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek} 85b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek 869c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic const Stmt *GetNextStmt(const ExplodedNode *N) { 87b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek for (N = GetSuccessorNode(N); N; N = GetSuccessorNode(N)) 885f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) { 89f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek // Check if the statement is '?' or '&&'/'||'. These are "merges", 90f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek // not actual statement points. 91f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek switch (S->getStmtClass()) { 92f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek case Stmt::ChooseExprClass: 9356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: continue; 94f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek case Stmt::ConditionalOperatorClass: continue; 95f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek case Stmt::BinaryOperatorClass: { 962de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode(); 972de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (Op == BO_LAnd || Op == BO_LOr) 98f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek continue; 99f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek break; 100f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 101f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek default: 102f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek break; 103f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 104b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 105f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 1061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 107b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return 0; 108bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek} 109bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek 1105f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt* 1119c378f705405d37f49795d5e915989de774fe11fTed KremenekGetCurrentOrPreviousStmt(const ExplodedNode *N) { 1125f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) 113b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 1141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 115b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return GetPreviousStmt(N); 116b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek} 1171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1185f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt* 1199c378f705405d37f49795d5e915989de774fe11fTed KremenekGetCurrentOrNextStmt(const ExplodedNode *N) { 1205f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetStmt(N->getLocation())) 121b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 1221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 123b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return GetNextStmt(N); 1243148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek} 1253148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek 126b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 127c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek// Diagnostic cleanup. 128c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek//===----------------------------------------------------------------------===// 129c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 130b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenekstatic PathDiagnosticEventPiece * 131b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted KremenekeventsDescribeSameCondition(PathDiagnosticEventPiece *X, 132b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek PathDiagnosticEventPiece *Y) { 133b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // Prefer diagnostics that come from ConditionBRVisitor over 134b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // those that came from TrackConstraintBRVisitor. 135b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek const void *tagPreferred = ConditionBRVisitor::getTag(); 136b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek const void *tagLesser = TrackConstraintBRVisitor::getTag(); 137b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 138b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (X->getLocation() != Y->getLocation()) 139b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return 0; 140b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 141b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (X->getTag() == tagPreferred && Y->getTag() == tagLesser) 142b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return X; 143b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 144b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (Y->getTag() == tagPreferred && X->getTag() == tagLesser) 145b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return Y; 146b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 147b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return 0; 148b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek} 149b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 1503800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// An optimization pass over PathPieces that removes redundant diagnostics 1513800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// generated by both ConditionBRVisitor and TrackConstraintBRVisitor. Both 1523800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// BugReporterVisitors use different methods to generate diagnostics, with 1533800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// one capable of emitting diagnostics in some cases but not in others. This 1543800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// can lead to redundant diagnostic pieces at the same point in a path. 1553800165e56107df7430520aa98afdf7065db2dd2Ted Kremenekstatic void removeRedundantMsgs(PathPieces &path) { 156b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek unsigned N = path.size(); 157b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (N < 2) 158b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return; 1593800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek // NOTE: this loop intentionally is not using an iterator. Instead, we 1603800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek // are streaming the path and modifying it in place. This is done by 1613800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek // grabbing the front, processing it, and if we decide to keep it append 1623800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek // it to the end of the path. The entire path is processed in this way. 163b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek for (unsigned i = 0; i < N; ++i) { 164b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek IntrusiveRefCntPtr<PathDiagnosticPiece> piece(path.front()); 165b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek path.pop_front(); 166b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 167b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek switch (piece->getKind()) { 168b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek case clang::ento::PathDiagnosticPiece::Call: 1693800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek removeRedundantMsgs(cast<PathDiagnosticCallPiece>(piece)->path); 170b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 171b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek case clang::ento::PathDiagnosticPiece::Macro: 1723800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek removeRedundantMsgs(cast<PathDiagnosticMacroPiece>(piece)->subPieces); 173b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 174b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek case clang::ento::PathDiagnosticPiece::ControlFlow: 175b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 176b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek case clang::ento::PathDiagnosticPiece::Event: { 177b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (i == N-1) 178b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 179b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 180b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (PathDiagnosticEventPiece *nextEvent = 181b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek dyn_cast<PathDiagnosticEventPiece>(path.front().getPtr())) { 182b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek PathDiagnosticEventPiece *event = 183b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek cast<PathDiagnosticEventPiece>(piece); 184b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // Check to see if we should keep one of the two pieces. If we 185b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // come up with a preference, record which piece to keep, and consume 186b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // another piece from the path. 187b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (PathDiagnosticEventPiece *pieceToKeep = 188b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek eventsDescribeSameCondition(event, nextEvent)) { 189b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek piece = pieceToKeep; 190b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek path.pop_front(); 191b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek ++i; 192b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 193b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 194b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 195b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 196b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 197b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek path.push_back(piece); 198b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 199b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek} 200b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 201c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// Recursively scan through a path and prune out calls and macros pieces 202c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// that aren't needed. Return true if afterwards the path contains 203afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// "interesting stuff" which means it shouldn't be pruned from the parent path. 204afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rosebool BugReporter::RemoveUnneededCalls(PathPieces &pieces, BugReport *R) { 205c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek bool containsSomethingInteresting = false; 206c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek const unsigned N = pieces.size(); 207c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 208c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek for (unsigned i = 0 ; i < N ; ++i) { 209c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek // Remove the front piece from the path. If it is still something we 210c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek // want to keep once we are done, we will push it back on the end. 211c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek IntrusiveRefCntPtr<PathDiagnosticPiece> piece(pieces.front()); 212c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek pieces.pop_front(); 213c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 214afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose // Throw away pieces with invalid locations. Note that we can't throw away 215afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose // calls just yet because they might have something interesting inside them. 216afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose // If so, their locations will be adjusted as necessary later. 217a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek if (piece->getKind() != PathDiagnosticPiece::Call && 218a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek piece->getLocation().asLocation().isInvalid()) 219a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek continue; 220a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 221725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek switch (piece->getKind()) { 222725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Call: { 223725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticCallPiece *call = cast<PathDiagnosticCallPiece>(piece); 22480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Check if the location context is interesting. 22580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks assert(LocationContextMap.count(call)); 22680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (R->isInteresting(LocationContextMap[call])) { 22780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks containsSomethingInteresting = true; 22880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 22980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 230368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose 231afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose if (!RemoveUnneededCalls(call->path, R)) 232368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose continue; 233a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 234725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek containsSomethingInteresting = true; 235725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 236725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 237725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Macro: { 238725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticMacroPiece *macro = cast<PathDiagnosticMacroPiece>(piece); 239afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose if (!RemoveUnneededCalls(macro->subPieces, R)) 240725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek continue; 241c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek containsSomethingInteresting = true; 242725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 243725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 244725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Event: { 245725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticEventPiece *event = cast<PathDiagnosticEventPiece>(piece); 246a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 247725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // We never throw away an event, but we do throw it away wholesale 248725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // as part of a path if we throw the entire path away. 24922505ef15e32db31a4f834a387cf73a913bc8f66Ted Kremenek containsSomethingInteresting |= !event->isPrunable(); 250725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 251725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 252725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::ControlFlow: 253725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 254c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek } 255c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 256c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek pieces.push_back(piece); 257c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek } 258c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 259c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek return containsSomethingInteresting; 260c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek} 261c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 262afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// Recursively scan through a path and make sure that all call pieces have 263afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// valid locations. Note that all other pieces with invalid locations should 264afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// have already been pruned out. 265afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rosestatic void adjustCallLocations(PathPieces &Pieces, 266afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose PathDiagnosticLocation *LastCallLocation = 0) { 267afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E; ++I) { 268afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose PathDiagnosticCallPiece *Call = dyn_cast<PathDiagnosticCallPiece>(*I); 269afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 270afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose if (!Call) { 271afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose assert((*I)->getLocation().asLocation().isValid()); 272afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose continue; 273afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose } 274afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 275afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose if (LastCallLocation) { 276187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose if (!Call->callEnter.asLocation().isValid() || 277187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose Call->getCaller()->isImplicit()) 278afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose Call->callEnter = *LastCallLocation; 279187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose if (!Call->callReturn.asLocation().isValid() || 280187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose Call->getCaller()->isImplicit()) 281afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose Call->callReturn = *LastCallLocation; 282afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose } 283afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 284afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose // Recursively clean out the subclass. Keep this call around if 285afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose // it contains any informative diagnostics. 286afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose PathDiagnosticLocation *ThisCallLocation; 287187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose if (Call->callEnterWithin.asLocation().isValid() && 288187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose !Call->getCallee()->isImplicit()) 289afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose ThisCallLocation = &Call->callEnterWithin; 290afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose else 291afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose ThisCallLocation = &Call->callEnter; 292afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 293afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose assert(ThisCallLocation && "Outermost call has an invalid location"); 294afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose adjustCallLocations(Call->path, ThisCallLocation); 295afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose } 296afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose} 297afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 298c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek//===----------------------------------------------------------------------===// 2993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnosticBuilder and its associated routines and helper objects. 300b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 301b479dadea93b93d3f0a335c3518b703f140b3f50Ted Kremenek 302babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremeneknamespace { 303ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NodeMapClosure : public BugReport::NodeResolver { 304c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose InterExplodedGraphMap &M; 3057dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenekpublic: 306c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose NodeMapClosure(InterExplodedGraphMap &m) : M(m) {} 3071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3089c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *getOriginalNode(const ExplodedNode *N) { 309c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose return M.lookup(N); 3107dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 3117dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek}; 3121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 313ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass PathDiagnosticBuilder : public BugReporterContext { 3147dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek BugReport *R; 315ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *PDC; 3167dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeMapClosure NMC; 3171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic: 31859950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek const LocationContext *LC; 31959950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 3208966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek PathDiagnosticBuilder(GRBugReporter &br, 321c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose BugReport *r, InterExplodedGraphMap &Backmap, 322ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *pdc) 3238966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek : BugReporterContext(br), 32459950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek R(r), PDC(pdc), NMC(Backmap), LC(r->getErrorNode()->getLocationContext()) 32559950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek {} 3261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3279c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N); 3281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3299c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os, 3309c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N); 3311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3328e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *getBugReport() { return R; } 3338e6431adab313e283a992698f6fc7afe62420999Anna Zaks 334212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); } 33559950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 33659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek ParentMap& getParentMap() { return LC->getParentMap(); } 3371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 338c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek const Stmt *getParent(const Stmt *S) { 339c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek return getParentMap().getParent(S); 340c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek } 3411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3428966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek virtual NodeMapClosure& getNodeResolver() { return NMC; } 3437297134f128423fce2e88f92421ed135bded7d4eDouglas Gregor 344d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S); 3451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 346ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const { 347ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive; 3487dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 3497dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek 350babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek bool supportsLogicalOpControlFlow() const { 351babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek return PDC ? PDC->supportsLogicalOpControlFlow() : true; 3521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 353babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek}; 354babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek} // end anonymous namespace 355babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 35600605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 3579c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) { 3585f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (const Stmt *S = GetNextStmt(N)) 35959950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek return PathDiagnosticLocation(S, getSourceManager(), LC); 36000605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek 3610cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return PathDiagnosticLocation::createDeclEnd(N->getLocationContext(), 3620cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks getSourceManager()); 363082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek} 3641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 36500605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 3669c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os, 3679c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N) { 368babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 369143ca222583a4a355fdc89af852deef287499300Ted Kremenek // Slow, but probably doesn't matter. 370b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek if (os.str().empty()) 371b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << ' '; 3721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 37300605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek const PathDiagnosticLocation &Loc = ExecutionContinues(N); 3741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 37500605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek if (Loc.asStmt()) 376b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << "Execution continues on line " 377642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << getSourceManager().getExpansionLineNumber(Loc.asLocation()) 3788966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek << '.'; 3794f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 3804f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "Execution jumps to the end of the "; 3814f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek const Decl *D = N->getLocationContext()->getDecl(); 3824f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek if (isa<ObjCMethodDecl>(D)) 3834f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "method"; 3844f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else if (isa<FunctionDecl>(D)) 3854f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "function"; 3864f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 3874f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek assert(isa<BlockDecl>(D)); 3884f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "anonymous block"; 3894f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 3904f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << '.'; 3914f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 3921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 393082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek return Loc; 394143ca222583a4a355fdc89af852deef287499300Ted Kremenek} 395143ca222583a4a355fdc89af852deef287499300Ted Kremenek 396ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenekstatic bool IsNested(const Stmt *S, ParentMap &PM) { 397ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S))) 398ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek return true; 3991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 400ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const Stmt *Parent = PM.getParentIgnoreParens(S); 4011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 402ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (Parent) 403ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek switch (Parent->getStmtClass()) { 404ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::ForStmtClass: 405ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::DoStmtClass: 406ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::WhileStmtClass: 407ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek return true; 408ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek default: 409ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek break; 410ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek } 4111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 413ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek} 414ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek 415d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticLocation 416d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { 4179c378f705405d37f49795d5e915989de774fe11fTed Kremenek assert(S && "Null Stmt *passed to getEnclosingStmtLocation"); 4181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ParentMap &P = getParentMap(); 4198966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek SourceManager &SMgr = getSourceManager(); 420e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 421ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek while (IsNested(S, P)) { 4228c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const Stmt *Parent = P.getParentIgnoreParens(S); 4231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 424af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (!Parent) 425af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 4261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 427af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek switch (Parent->getStmtClass()) { 4285fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek case Stmt::BinaryOperatorClass: { 4295fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const BinaryOperator *B = cast<BinaryOperator>(Parent); 4305fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 431220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 4325fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek break; 4331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 434af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::CompoundStmtClass: 435af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::StmtExprClass: 436220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 4371d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ChooseExprClass: 4381d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // Similar to '?' if we are referring to condition, just have the edge 4391d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // point to the entire choose expression. 4401d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (cast<ChooseExpr>(Parent)->getCond() == S) 441220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 4421d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 443220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 44456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 4451d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ConditionalOperatorClass: 4461d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // For '?', if we are referring to condition, just have the edge point 4471d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // to the entire '?' expression. 44856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (cast<AbstractConditionalOperator>(Parent)->getCond() == S) 449220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 4501d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 451220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 452af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::DoStmtClass: 453220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 454af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ForStmtClass: 455af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ForStmt>(Parent)->getBody() == S) 456220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 4571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump break; 458af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::IfStmtClass: 459af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<IfStmt>(Parent)->getCond() != S) 460220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 4618bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek break; 462af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 463af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S) 464220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 465af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 466af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::WhileStmtClass: 467af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<WhileStmt>(Parent)->getCond() != S) 468220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 469af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 470af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek default: 471af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 472af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek } 473af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek 474d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek S = Parent; 475d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek } 4761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 477d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek assert(S && "Cannot have null Stmt for PathDiagnosticLocation"); 478e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 479e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // Special case: DeclStmts can appear in for statement declarations, in which 480e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // case the ForStmt is the context. 481e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (isa<DeclStmt>(S)) { 482e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (const Stmt *Parent = P.getParent(S)) { 483e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek switch (Parent->getStmtClass()) { 484e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek case Stmt::ForStmtClass: 485e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 486220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 487e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek default: 488e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek break; 4891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 4901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 491e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 492e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek else if (isa<BinaryOperator>(S)) { 493e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // Special case: the binary operator represents the initialization 494e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // code in a for statement (this can happen when the variable being 495e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // initialized is an old variable. 496e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (const ForStmt *FS = 497e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek dyn_cast_or_null<ForStmt>(P.getParentIgnoreParens(S))) { 498e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (FS->getInit() == S) 499220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(FS, SMgr, LC); 500e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 501e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 502e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 503220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 504d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek} 505d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 506cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 507d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose// "Visitors only" path diagnostic generation algorithm. 508d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose//===----------------------------------------------------------------------===// 509d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rosestatic bool GenerateVisitorsOnlyPathDiagnostic(PathDiagnostic &PD, 510d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose PathDiagnosticBuilder &PDB, 511d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose const ExplodedNode *N, 512d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose ArrayRef<BugReporterVisitor *> visitors) { 513d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // All path generation skips the very first node (the error node). 514d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // This is because there is special handling for the end-of-path note. 515d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose N = N->getFirstPred(); 516d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!N) 517d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return true; 518d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 519d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose BugReport *R = PDB.getBugReport(); 520d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose while (const ExplodedNode *Pred = N->getFirstPred()) { 521d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 522d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose E = visitors.end(); 523d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose I != E; ++I) { 524d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // Visit all the node pairs, but throw the path pieces away. 525d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose PathDiagnosticPiece *Piece = (*I)->VisitNode(N, Pred, PDB, *R); 526d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose delete Piece; 527d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose } 528d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 529d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose N = Pred; 530d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose } 531d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 532d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return R->isValid(); 533d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose} 534d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 535d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose//===----------------------------------------------------------------------===// 5363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// "Minimal" path diagnostic generation algorithm. 537cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 53856a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zakstypedef std::pair<PathDiagnosticCallPiece*, const ExplodedNode*> StackDiagPair; 53956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zakstypedef SmallVector<StackDiagPair, 6> StackDiagVector; 54056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 541368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaksstatic void updateStackPiecesWithMessage(PathDiagnosticPiece *P, 54256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector &CallStack) { 543368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // If the piece contains a special message, add it to all the call 544368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // pieces on the active stack. 545368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (PathDiagnosticEventPiece *ep = 546368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks dyn_cast<PathDiagnosticEventPiece>(P)) { 547368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 54856a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (ep->hasCallStackHint()) 54956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks for (StackDiagVector::iterator I = CallStack.begin(), 55056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks E = CallStack.end(); I != E; ++I) { 55156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks PathDiagnosticCallPiece *CP = I->first; 55256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks const ExplodedNode *N = I->second; 5538fe4525680ce72e90cee3e58b5654e3ae955447fNAKAMURA Takumi std::string stackMsg = ep->getCallStackMessage(N); 55456a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 555368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // The last message on the path to final bug is the most important 556368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // one. Since we traverse the path backwards, do not add the message 557368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // if one has been previously added. 55856a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (!CP->hasCallStackMessage()) 55956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks CP->setCallStackMessage(stackMsg); 56056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks } 561368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 562368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks} 563cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 56477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM); 56514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 5668347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosestatic bool GenerateMinimalPathDiagnostic(PathDiagnostic& PD, 5673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticBuilder &PDB, 5683bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose const ExplodedNode *N, 5693bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ArrayRef<BugReporterVisitor *> visitors) { 5708966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek 5713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceManager& SMgr = PDB.getSourceManager(); 57259950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek const LocationContext *LC = PDB.LC; 5739c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() 5743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek ? NULL : *(N->pred_begin()); 575368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 57656a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector CallStack; 577368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 5783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (NextNode) { 5791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump N = NextNode; 58059950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC = N->getLocationContext(); 5813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek NextNode = GetPredecessorNode(N); 5821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 58361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek ProgramPoint P = N->getLocation(); 58480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 58580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks do { 5867a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) { 58780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece *C = 58880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece::construct(N, *CE, SMgr); 58980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GRBugReporter& BR = PDB.getBugReporter(); 59080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks BR.addCallPieceLocationContextPair(C, CE->getCalleeContext()); 59180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(C); 59280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.pushActivePath(&C->path); 59380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks CallStack.push_back(StackDiagPair(C, N)); 59480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 5959373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks } 596183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 5977a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallEnter> CE = P.getAs<CallEnter>()) { 59880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Flush all locations, and pop the active path. 59980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks bool VisitedEntireCall = PD.isWithinCall(); 60080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.popActivePath(); 60180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 60280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Either we just added a bunch of stuff to the top-level path, or 60380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // we have a previous CallExitEnd. If the former, it means that the 60480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // path terminated within a function call. We must then take the 60580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // current contents of the active path and place it within 60680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // a new PathDiagnosticCallPiece. 60780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece *C; 60880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (VisitedEntireCall) { 60980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 61080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } else { 61180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Decl *Caller = CE->getLocationContext()->getDecl(); 61280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 61380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GRBugReporter& BR = PDB.getBugReporter(); 61480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks BR.addCallPieceLocationContextPair(C, CE->getCalleeContext()); 61580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 61680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 61780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C->setCallee(*CE, SMgr); 61880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!CallStack.empty()) { 61980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks assert(CallStack.back().first == C); 62080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks CallStack.pop_back(); 62180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 62280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 623368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 6241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6257a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { 62680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CFGBlock *Src = BE->getSrc(); 62780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CFGBlock *Dst = BE->getDst(); 62880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Stmt *T = Src->getTerminator(); 6291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 63080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!T) 63180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 6321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 63380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation Start = 63480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createBegin(T, SMgr, 63580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks N->getLocationContext()); 6361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 63780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks switch (T->getStmtClass()) { 63861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek default: 63961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 6401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 64161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek case Stmt::GotoStmtClass: 6421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::IndirectGotoStmtClass: { 6439c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Stmt *S = GetNextStmt(N); 6441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 64561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek if (!S) 64680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 6471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 648297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 6491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::raw_string_ostream os(sbuf); 650d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S); 6511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 65200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os << "Control jumps to line " 65380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 65480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 65580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 65661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 65761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 6581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::SwitchStmtClass: { 66061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek // Figure out what case arm we took. 661297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 662297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 6631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6649c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const Stmt *S = Dst->getLabel()) { 665220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(S, SMgr, LC); 6661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6675a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek switch (S->getStmtClass()) { 66880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks default: 66980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "No cases match in the switch statement. " 67080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks "Control jumps to line " 67180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 67280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 67380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks case Stmt::DefaultStmtClass: 67480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "Control jumps to the 'default' case at line " 67580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 67680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 67780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 67880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks case Stmt::CaseStmtClass: { 67980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "Control jumps to 'case "; 68080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CaseStmt *Case = cast<CaseStmt>(S); 68180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Expr *LHS = Case->getLHS()->IgnoreParenCasts(); 68280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 68380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine if it is an enum. 68480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks bool GetRawInt = true; 68580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 68680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) { 68780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // FIXME: Maybe this should be an assertion. Are there cases 68880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // were it is not an EnumConstantDecl? 68980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const EnumConstantDecl *D = 69003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu dyn_cast<EnumConstantDecl>(DR->getDecl()); 6911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 69280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (D) { 69380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GetRawInt = false; 69480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << *D; 6955a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek } 69680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 6979ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 69880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (GetRawInt) 69980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << LHS->EvaluateKnownConstInt(PDB.getASTContext()); 7009ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 70180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << ":' at line " 70280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 70380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 70461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 70580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 70680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 70780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 70861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 709567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek else { 710c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "'Default' branch taken. "; 7111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N); 71280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 71380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 714567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek } 7151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 71661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 71761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 7181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7192673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::BreakStmtClass: 7202673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::ContinueStmtClass: { 721297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 722297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 72300605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 72480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 72580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 7262673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek break; 7272673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek } 7281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 72980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine control-flow for ternary '?'. 73056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 731706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek case Stmt::ConditionalOperatorClass: { 732297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 733297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 7341d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek os << "'?' condition is "; 7351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 736706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()+1) == Dst) 737082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "false"; 738706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek else 739082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "true"; 7401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 74100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7431d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (const Stmt *S = End.asStmt()) 7441d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 7451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 74680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 74780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 748babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 749babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 7501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 75180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine control-flow for short-circuited '&&' and '||'. 752babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek case Stmt::BinaryOperatorClass: { 753babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek if (!PDB.supportsLogicalOpControlFlow()) 754babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 7551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 75603509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const BinaryOperator *B = cast<BinaryOperator>(T); 757babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek std::string sbuf; 758babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek llvm::raw_string_ostream os(sbuf); 759babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek os << "Left side of '"; 7601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7612de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_LAnd) { 762f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "&&" << "' is "; 7631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 764f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 765f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 766220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 7670cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 76880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 76980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 77080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 7711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 772f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 773f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 774220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 775f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 77680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 77780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 7781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 779babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 780babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek else { 7812de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(B->getOpcode() == BO_LOr); 782f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "||" << "' is "; 7831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 784f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 785f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 786220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 787f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 78880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 78980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 790f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 791f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 792f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 793220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 7940cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 79580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 79680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 79780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 798f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 799babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 8001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 801706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek break; 802706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek } 8031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::DoStmtClass: { 805706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()) == Dst) { 806297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 807297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 8081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 809c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "Loop condition is true. "; 810d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 8111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 812d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 813d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 8141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 81580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 81680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 817082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 818082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek else { 81900605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 8201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 821d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 822d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 8231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 82480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 82580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Loop condition is false. Exiting loop")); 8263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 8293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::WhileStmtClass: 8321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::ForStmtClass: { 8333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) { 8343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::string sbuf; 8353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::raw_string_ostream os(sbuf); 8361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek os << "Loop condition is false. "; 8383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 8393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 8403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 8411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 84280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 84380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 8443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 8463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 8473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 8483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 8491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 85080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 85180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Loop condition is true. Entering loop body")); 8523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 8553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::IfStmtClass: { 8583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 8591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 8613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 8621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) 86480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 86580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Taking false branch")); 8661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else 86780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 86880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Taking true branch")); 8691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 8713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 87280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 8733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 87480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } while(0); 8751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 876dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (NextNode) { 8778e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add diagnostic pieces from custom visitors. 8788e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 8793bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 8803bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = visitors.end(); 8813bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose I != E; ++I) { 882368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 8832042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 884368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks updateStackPiecesWithMessage(p, CallStack); 885368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 886dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 8878966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 8883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8908347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose if (!PDB.getBugReport()->isValid()) 8918347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return false; 8928347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 89314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // After constructing the full PathDiagnostic, do a pass over it to compact 89414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // PathDiagnosticPieces that occur within a macro. 89577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager()); 8968347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return true; 8973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 8983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 8993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 9005fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek// "Extensive" PathDiagnostic generation. 9015fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 9025fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 9035fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenekstatic bool IsControlFlowExpr(const Stmt *S) { 9045fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const Expr *E = dyn_cast<Expr>(S); 9051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9065fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (!E) 9075fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return false; 9081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump E = E->IgnoreParenCasts(); 9101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 91156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (isa<AbstractConditionalOperator>(E)) 9125fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 9131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9145fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) 9155fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 9165fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 9171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 9195fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek} 9205fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 92114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremeneknamespace { 922ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ContextLocation : public PathDiagnosticLocation { 9238f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsDead; 9248f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekpublic: 9258f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation(const PathDiagnosticLocation &L, bool isdead = false) 9268f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek : PathDiagnosticLocation(L), IsDead(isdead) {} 9271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void markDead() { IsDead = true; } 9298f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool isDead() const { return IsDead; } 9308f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek}; 9311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 932ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass EdgeBuilder { 9338f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek std::vector<ContextLocation> CLocs; 9348f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek typedef std::vector<ContextLocation>::iterator iterator; 93514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnostic &PD; 93614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB; 93714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation PrevLoc; 9381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9398f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsConsumedExpr(const PathDiagnosticLocation &L); 9401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 94114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek bool containsLocation(const PathDiagnosticLocation &Container, 94214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee); 9431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 94414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L); 9451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9469650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L, 9479650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek bool firstCharOnly = false) { 9488c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (const Stmt *S = L.asStmt()) { 9499650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek const Stmt *Original = S; 9508c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek while (1) { 9518c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek // Adjust the location for some expressions that are best referenced 9528c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek // by one of their subexpressions. 9539650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek switch (S->getStmtClass()) { 9549650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek default: 9559650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek break; 9569650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ParenExprClass: 957f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne case Stmt::GenericSelectionExprClass: 958f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne S = cast<Expr>(S)->IgnoreParens(); 9599650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 9609650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 96156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 9629650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ConditionalOperatorClass: 96356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall S = cast<AbstractConditionalOperator>(S)->getCond(); 9649650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 9659650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 9669650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::ChooseExprClass: 9679650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek S = cast<ChooseExpr>(S)->getCond(); 9689650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 9699650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 9709650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek case Stmt::BinaryOperatorClass: 9719650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek S = cast<BinaryOperator>(S)->getLHS(); 9729650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek firstCharOnly = true; 9739650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek continue; 9749650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek } 9751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9769650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek break; 9778c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 9781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9799650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek if (S != Original) 98059950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek L = PathDiagnosticLocation(S, L.getManager(), PDB.LC); 9818c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 9821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9839650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek if (firstCharOnly) 9841531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks L = PathDiagnosticLocation::createSingleLocation(L); 9859650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek 9868c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek return L; 9878c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek } 9881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void popLocation() { 9908f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) { 9915c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // For contexts, we only one the first character as the range. 99207c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek rawAddEdge(cleanUpLocation(CLocs.back(), true)); 9935c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek } 99414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.pop_back(); 99514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 9961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 99714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekpublic: 99814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb) 99914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek : PD(pd), PDB(pdb) { 10001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1001a301a6773db085575ac51e3c966858180390c25bTed Kremenek // If the PathDiagnostic already has pieces, add the enclosing statement 1002a301a6773db085575ac51e3c966858180390c25bTed Kremenek // of the first piece as a context as well. 1003802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek if (!PD.path.empty()) { 1004802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek PrevLoc = (*PD.path.begin())->getLocation(); 10051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 100614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = PrevLoc.asStmt()) 1007e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 100814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 100914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 101014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 101114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ~EdgeBuilder() { 101214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) popLocation(); 10130cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 1014a301a6773db085575ac51e3c966858180390c25bTed Kremenek // Finally, add an initial edge from the start location of the first 1015a301a6773db085575ac51e3c966858180390c25bTed Kremenek // statement (if it doesn't already exist). 10160cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin( 101759950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC, 10180cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PDB.getSourceManager()); 10190cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks if (L.isValid()) 10200cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks rawAddEdge(L); 102114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 102214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 10235de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek void flushLocations() { 10245de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek while (!CLocs.empty()) 10255de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek popLocation(); 10265de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek PrevLoc = PathDiagnosticLocation(); 10275de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek } 10285de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 102914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false); 10301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10318bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek void rawAddEdge(PathDiagnosticLocation NewLoc); 10321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 103314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addContext(const Stmt *S); 1034183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose void addContext(const PathDiagnosticLocation &L); 1035e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek void addExtendedContext(const Stmt *S); 10361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}; 103714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} // end anonymous namespace 103814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 103914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 104014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekPathDiagnosticLocation 104114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekEdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) { 104214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = L.asStmt()) { 104314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (IsControlFlowExpr(S)) 104414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 10451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return PDB.getEnclosingStmtLocation(S); 104714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 10481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 104914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 105014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 105114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 105214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekbool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container, 105314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee) { 105414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 105514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container == Containee) 105614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 10571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 105814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container.asDecl()) 105914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 10601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 106114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = Containee.asStmt()) 106214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *ContainerS = Container.asStmt()) { 106314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (S) { 106414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (S == ContainerS) 106514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 106614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek S = PDB.getParent(S); 106714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 106814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return false; 106914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 107014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 107114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Less accurate: compare using source ranges. 107214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContainerR = Container.asRange(); 107314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContaineeR = Containee.asRange(); 10741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 107514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceManager &SM = PDB.getSourceManager(); 1076402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin()); 1077402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd()); 1078402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin()); 1079402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd()); 10801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1081642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg); 1082642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd); 1083642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg); 1084642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd); 10851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 108614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek assert(ContainerBegLine <= ContainerEndLine); 10871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(ContaineeBegLine <= ContaineeEndLine); 10881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 108914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return (ContainerBegLine <= ContaineeBegLine && 109014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ContainerEndLine >= ContaineeEndLine && 109114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerBegLine != ContaineeBegLine || 1092a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerRBeg) <= 1093a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContaineeRBeg)) && 109414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerEndLine != ContaineeEndLine || 1095a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerREnd) >= 10966488dc31153be6f98b404c7860be6c66bb4ec917Ted Kremenek SM.getExpansionColumnNumber(ContaineeREnd))); 109714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 109814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 109914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) { 110014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!PrevLoc.isValid()) { 110114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PrevLoc = NewLoc; 110214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 110314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 11041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11058c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc); 11068c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc); 11071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1108a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek if (PrevLocClean.asLocation().isInvalid()) { 1109a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek PrevLoc = NewLoc; 1110a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek return; 1111a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek } 1112a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 11138c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (NewLocClean.asLocation() == PrevLocClean.asLocation()) 111414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 11151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 111614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // FIXME: Ignore intra-macro edges for now. 1117402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth if (NewLocClean.asLocation().getExpansionLoc() == 1118402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth PrevLocClean.asLocation().getExpansionLoc()) 111914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 112014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 11212042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean)); 11228c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek PrevLoc = NewLoc; 112314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 112414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 112514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) { 11261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1127a301a6773db085575ac51e3c966858180390c25bTed Kremenek if (!alwaysAdd && NewLoc.asLocation().isMacroID()) 1128a301a6773db085575ac51e3c966858180390c25bTed Kremenek return; 11291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 113014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc); 113114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 113214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 11338f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation &TopContextLoc = CLocs.back(); 11341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 113514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 113614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == CLoc) { 11378f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 11384c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek if (IsConsumedExpr(TopContextLoc) && 11394c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek !IsControlFlowExpr(TopContextLoc.asStmt())) 11408f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek TopContextLoc.markDead(); 11418f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek 114214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 11438f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 114414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 114514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 114614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 114714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 114814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, CLoc)) { 11498f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 115014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 11511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11524c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek if (IsConsumedExpr(CLoc) && !IsControlFlowExpr(CLoc.asStmt())) { 11538f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek CLocs.push_back(ContextLocation(CLoc, true)); 11548f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return; 11558f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 11568f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 11571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 115814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(CLoc); 11591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 116014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 116114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 116214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 116314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 116414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 11651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11665c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // If we reach here, there is no enclosing context. Just add the edge. 11675c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek rawAddEdge(NewLoc); 116814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 116914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 11708f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekbool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) { 11718f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt())) 11728f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X); 11731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11748f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return false; 11758f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek} 11761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1177e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenekvoid EdgeBuilder::addExtendedContext(const Stmt *S) { 1178e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (!S) 1179e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek return; 11801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const Stmt *Parent = PDB.getParent(S); 1182e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek while (Parent) { 1183e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (isa<CompoundStmt>(Parent)) 1184e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek Parent = PDB.getParent(Parent); 1185e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek else 1186e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1187e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1188e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek 1189e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (Parent) { 1190e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek switch (Parent->getStmtClass()) { 1191e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::DoStmtClass: 1192e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 1193e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(Parent); 1194e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek default: 1195e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1196e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1197e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 11981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1199e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(S); 1200e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek} 12011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 120214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addContext(const Stmt *S) { 120314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!S) 120414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 120514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 120659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.LC); 1207183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose addContext(L); 1208183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose} 12091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1210183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rosevoid EdgeBuilder::addContext(const PathDiagnosticLocation &L) { 121114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 121214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &TopContextLoc = CLocs.back(); 121314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 121414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 121514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == L) 121614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 121714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 121814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, L)) { 121914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 12201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 122114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 122214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 122314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 122414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 122514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 122614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 122714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 122814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 122914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 123011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// Cone-of-influence: support the reverse propagation of "interesting" symbols 123111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// and values by tracing interesting calculations backwards through evaluated 123211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// expressions along a path. This is probably overly complicated, but the idea 123311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// is that if an expression computed an "interesting" value, the child 123411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// expressions are are also likely to be "interesting" as well (which then 123511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// propagates to the values they in turn compute). This reverse propagation 123611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// is needed to track interesting correlations across function call boundaries, 123711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// where formal arguments bind to actual arguments, etc. This is also needed 123811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// because the constraint solver sometimes simplifies certain symbolic values 123911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// into constants when appropriate, and this complicates reasoning about 124011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// interesting values. 124111abcecc8c919673237cf37384290a1ef1943976Ted Kremenektypedef llvm::DenseSet<const Expr *> InterestingExprs; 124211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 124311abcecc8c919673237cf37384290a1ef1943976Ted Kremenekstatic void reversePropagateIntererstingSymbols(BugReport &R, 124411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs &IE, 124511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const ProgramState *State, 124611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const Expr *Ex, 124711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *LCtx) { 124811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek SVal V = State->getSVal(Ex, LCtx); 124911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (!(R.isInteresting(V) || IE.count(Ex))) 125011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek return; 125111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 125211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek switch (Ex->getStmtClass()) { 125311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek default: 125411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (!isa<CastExpr>(Ex)) 125511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek break; 125611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // Fall through. 125711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek case Stmt::BinaryOperatorClass: 125811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek case Stmt::UnaryOperatorClass: { 125911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek for (Stmt::const_child_iterator CI = Ex->child_begin(), 126011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CE = Ex->child_end(); 126111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CI != CE; ++CI) { 126211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *child = dyn_cast_or_null<Expr>(*CI)) { 126311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek IE.insert(child); 126411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek SVal ChildV = State->getSVal(child, LCtx); 126511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek R.markInteresting(ChildV); 126611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 126711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek break; 126811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 126911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 127011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 127111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 127211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek R.markInteresting(V); 127311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek} 127411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 127511abcecc8c919673237cf37384290a1ef1943976Ted Kremenekstatic void reversePropagateInterestingSymbols(BugReport &R, 127611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs &IE, 127711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const ProgramState *State, 127811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CalleeCtx, 127911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CallerCtx) 128011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek{ 1281852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose // FIXME: Handle non-CallExpr-based CallEvents. 128211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const StackFrameContext *Callee = CalleeCtx->getCurrentStackFrame(); 128311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const Stmt *CallSite = Callee->getCallSite(); 1284852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite)) { 128511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) { 128611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek FunctionDecl::param_const_iterator PI = FD->param_begin(), 128711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek PE = FD->param_end(); 128811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end(); 128911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek for (; AI != AE && PI != PE; ++AI, ++PI) { 129011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *ArgE = *AI) { 129111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const ParmVarDecl *PD = *PI) { 129211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek Loc LV = State->getLValue(PD, CalleeCtx); 129311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (R.isInteresting(LV) || R.isInteresting(State->getRawSVal(LV))) 129411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek IE.insert(ArgE); 129511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 129611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 129711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 129811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 129911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 130011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek} 13018185674528423e2504a1fae35c28c24104846510Ted Kremenek 1302b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===// 1303b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek// Functions for determining if a loop was executed 0 times. 1304b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===// 1305b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 13068185674528423e2504a1fae35c28c24104846510Ted Kremenek/// Return true if the terminator is a loop and the destination is the 13078185674528423e2504a1fae35c28c24104846510Ted Kremenek/// false branch. 13088185674528423e2504a1fae35c28c24104846510Ted Kremenekstatic bool isLoopJumpPastBody(const Stmt *Term, const BlockEdge *BE) { 13098185674528423e2504a1fae35c28c24104846510Ted Kremenek switch (Term->getStmtClass()) { 13108185674528423e2504a1fae35c28c24104846510Ted Kremenek case Stmt::ForStmtClass: 13118185674528423e2504a1fae35c28c24104846510Ted Kremenek case Stmt::WhileStmtClass: 1312c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 13138185674528423e2504a1fae35c28c24104846510Ted Kremenek break; 13148185674528423e2504a1fae35c28c24104846510Ted Kremenek default: 13158185674528423e2504a1fae35c28c24104846510Ted Kremenek // Note that we intentionally do not include do..while here. 13168185674528423e2504a1fae35c28c24104846510Ted Kremenek return false; 13178185674528423e2504a1fae35c28c24104846510Ted Kremenek } 13188185674528423e2504a1fae35c28c24104846510Ted Kremenek 13198185674528423e2504a1fae35c28c24104846510Ted Kremenek // Did we take the false branch? 13208185674528423e2504a1fae35c28c24104846510Ted Kremenek const CFGBlock *Src = BE->getSrc(); 13218185674528423e2504a1fae35c28c24104846510Ted Kremenek assert(Src->succ_size() == 2); 13228185674528423e2504a1fae35c28c24104846510Ted Kremenek return (*(Src->succ_begin()+1) == BE->getDst()); 13238185674528423e2504a1fae35c28c24104846510Ted Kremenek} 13248185674528423e2504a1fae35c28c24104846510Ted Kremenek 1325b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenekstatic bool isContainedByStmt(ParentMap &PM, const Stmt *S, const Stmt *SubS) { 1326b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek while (SubS) { 1327b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (SubS == S) 1328b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return true; 1329b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek SubS = PM.getParent(SubS); 1330b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 1331b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return false; 1332b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek} 1333b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1334b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenekstatic const Stmt *getStmtBeforeCond(ParentMap &PM, const Stmt *Term, 1335b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const ExplodedNode *N) { 1336b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek while (N) { 1337b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek Optional<StmtPoint> SP = N->getLocation().getAs<StmtPoint>(); 1338b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (SP) { 1339b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const Stmt *S = SP->getStmt(); 1340b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (!isContainedByStmt(PM, Term, S)) 1341b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return S; 1342b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 1343b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek N = GetPredecessorNode(N); 1344b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 1345b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return 0; 1346b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek} 1347b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1348b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenekstatic bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) { 1349b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const Stmt *LoopBody = 0; 1350b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek switch (Term->getStmtClass()) { 1351b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek case Stmt::ForStmtClass: { 1352b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const ForStmt *FS = cast<ForStmt>(Term); 1353b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (isContainedByStmt(PM, FS->getInc(), S)) 1354b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return true; 1355b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek LoopBody = FS->getBody(); 1356b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek break; 1357b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 1358c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: { 1359c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek const ObjCForCollectionStmt *FC = cast<ObjCForCollectionStmt>(Term); 1360c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek LoopBody = FC->getBody(); 1361c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek break; 1362c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek } 1363b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek case Stmt::WhileStmtClass: 1364b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek LoopBody = cast<WhileStmt>(Term)->getBody(); 1365b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek break; 1366b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek default: 1367b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return false; 1368b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 1369b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return isContainedByStmt(PM, LoopBody, S); 1370b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek} 1371b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1372b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===// 1373b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek// Top-level logic for generating extensive path diagnostics. 1374b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===// 1375b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 13768347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosestatic bool GenerateExtensivePathDiagnostic(PathDiagnostic& PD, 137714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB, 13783bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose const ExplodedNode *N, 13793bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ArrayRef<BugReporterVisitor *> visitors) { 138014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder EB(PD, PDB); 13810cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks const SourceManager& SM = PDB.getSourceManager(); 138256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector CallStack; 138311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs IE; 138414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 13859c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); 138614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (NextNode) { 138714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek N = NextNode; 138814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek NextNode = GetPredecessorNode(N); 138914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ProgramPoint P = N->getLocation(); 139014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 1391dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek do { 13927a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<PostStmt> PS = P.getAs<PostStmt>()) { 139311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *Ex = PS->getStmtAs<Expr>()) 139411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 139511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek N->getState().getPtr(), Ex, 139611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek N->getLocationContext()); 139711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 139811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 13997a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) { 1400183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose const Stmt *S = CE->getCalleeContext()->getCallSite(); 1401183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) { 1402852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 1403852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose N->getState().getPtr(), Ex, 1404852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose N->getLocationContext()); 1405852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose } 1406183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 1407183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece *C = 1408183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece::construct(N, *CE, SM); 140980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GRBugReporter& BR = PDB.getBugReporter(); 141080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks BR.addCallPieceLocationContextPair(C, CE->getCalleeContext()); 1411183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 1412183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose EB.addEdge(C->callReturn, true); 1413183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose EB.flushLocations(); 1414183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 1415183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PD.getActivePath().push_front(C); 1416183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PD.pushActivePath(&C->path); 1417183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose CallStack.push_back(StackDiagPair(C, N)); 14185de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek break; 14195de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek } 14204ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek 14212042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // Pop the call hierarchy if we are done walking the contents 14222042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // of a function call. 14237a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallEnter> CE = P.getAs<CallEnter>()) { 1424097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek // Add an edge to the start of the function. 1425097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek const Decl *D = CE->getCalleeContext()->getDecl(); 1426097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek PathDiagnosticLocation pos = 1427097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek PathDiagnosticLocation::createBegin(D, SM); 1428097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek EB.addEdge(pos); 1429097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek 1430097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek // Flush all locations, and pop the active path. 1431183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose bool VisitedEntireCall = PD.isWithinCall(); 14324ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek EB.flushLocations(); 14332042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.popActivePath(); 14344ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek PDB.LC = N->getLocationContext(); 1435097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek 1436183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose // Either we just added a bunch of stuff to the top-level path, or 1437183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose // we have a previous CallExitEnd. If the former, it means that the 14382042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // path terminated within a function call. We must then take the 14392042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // current contents of the active path and place it within 14402042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // a new PathDiagnosticCallPiece. 1441183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece *C; 1442183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose if (VisitedEntireCall) { 1443183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 1444183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose } else { 1445183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose const Decl *Caller = CE->getLocationContext()->getDecl(); 14469373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 144780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GRBugReporter& BR = PDB.getBugReporter(); 144880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks BR.addCallPieceLocationContextPair(C, CE->getCalleeContext()); 14499373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks } 1450852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose 1451183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose C->setCallee(*CE, SM); 1452183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose EB.addContext(C->getLocation()); 1453368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 1454368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (!CallStack.empty()) { 145556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks assert(CallStack.back().first == C); 1456368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks CallStack.pop_back(); 1457368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 14582042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek break; 14592042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek } 14604ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek 14614ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // Note that is important that we update the LocationContext 14624ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // after looking at CallExits. CallExit basically adds an 14634ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // edge in the *caller*, so we don't want to update the LocationContext 14644ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // too soon. 14654ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek PDB.LC = N->getLocationContext(); 14665de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 1467dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Block edges. 14687a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { 146911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // Does this represent entering a call? If so, look at propagating 147011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // interesting symbols across call boundaries. 147111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (NextNode) { 147211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CallerCtx = NextNode->getLocationContext(); 147311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CalleeCtx = PDB.LC; 147411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (CallerCtx != CalleeCtx) { 147511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek reversePropagateInterestingSymbols(*PDB.getBugReport(), IE, 147611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek N->getState().getPtr(), 147711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CalleeCtx, CallerCtx); 147811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 147911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 148011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 1481dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Are we jumping to the head of a loop? Add a special diagnostic. 1482f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) { 148359950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PathDiagnosticLocation L(Loop, SM, PDB.LC); 1484ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const CompoundStmt *CS = NULL; 14851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1486f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) 1487f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek CS = dyn_cast<CompoundStmt>(FS->getBody()); 1488f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) 1489f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek CS = dyn_cast<CompoundStmt>(WS->getBody()); 14901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1491dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek PathDiagnosticEventPiece *p = 1492dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek new PathDiagnosticEventPiece(L, 149307c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek "Looping back to the head of the loop"); 14942dd17abf11ae64339fa6bfaa57d76e13a5fbe5b8Ted Kremenek p->setPrunable(true); 14951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1496dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek EB.addEdge(p->getLocation(), true); 14972042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 14981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1499ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (CS) { 15000cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation BL = 15010cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createEndBrace(CS, SM); 150207c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek EB.addEdge(BL); 1503dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 15048bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 15058185674528423e2504a1fae35c28c24104846510Ted Kremenek 1506b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const CFGBlock *BSrc = BE->getSrc(); 1507b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek ParentMap &PM = PDB.getParentMap(); 1508b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1509b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (const Stmt *Term = BSrc->getTerminator()) { 15108185674528423e2504a1fae35c28c24104846510Ted Kremenek // Are we jumping past the loop body without ever executing the 15118185674528423e2504a1fae35c28c24104846510Ted Kremenek // loop (because the condition was false)? 15127a95de68c093991047ed8d339479ccad51b88663David Blaikie if (isLoopJumpPastBody(Term, &*BE) && 1513b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek !isInLoopBody(PM, 1514b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek getStmtBeforeCond(PM, 1515b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek BSrc->getTerminatorCondition(), 1516b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek N), 1517b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek Term)) { 15188185674528423e2504a1fae35c28c24104846510Ted Kremenek PathDiagnosticLocation L(Term, SM, PDB.LC); 15198185674528423e2504a1fae35c28c24104846510Ted Kremenek PathDiagnosticEventPiece *PE = 1520b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek new PathDiagnosticEventPiece(L, "Loop body executed 0 times"); 15218185674528423e2504a1fae35c28c24104846510Ted Kremenek PE->setPrunable(true); 15228185674528423e2504a1fae35c28c24104846510Ted Kremenek 15238185674528423e2504a1fae35c28c24104846510Ted Kremenek EB.addEdge(PE->getLocation(), true); 15248185674528423e2504a1fae35c28c24104846510Ted Kremenek PD.getActivePath().push_front(PE); 15258185674528423e2504a1fae35c28c24104846510Ted Kremenek } 15268185674528423e2504a1fae35c28c24104846510Ted Kremenek 1527b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek // In any case, add the terminator as the current statement 1528b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek // context for control edges. 1529ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek EB.addContext(Term); 15308185674528423e2504a1fae35c28c24104846510Ted Kremenek } 15311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1532dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 15338bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 153414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 15357a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) { 1536b07805485c603be3d8011f72611465324c9e664bDavid Blaikie Optional<CFGElement> First = BE->getFirstElement(); 1537b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (Optional<CFGStmt> S = First ? First->getAs<CFGStmt>() : None) { 1538b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const Stmt *stmt = S->getStmt(); 15393c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (IsControlFlowExpr(stmt)) { 1540b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu // Add the proper context for '&&', '||', and '?'. 15413c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addContext(stmt); 1542b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 1543b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu else 15443c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt()); 1545dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 1546b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu 1547dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 1548dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 15495de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 15505de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 1551dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } while (0); 15521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1553dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (!NextNode) 155414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek continue; 15551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15568e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add pieces from custom visitors. 15578e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 15583bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 15593bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = visitors.end(); 15603bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose I != E; ++I) { 15618e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 15628966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek const PathDiagnosticLocation &Loc = p->getLocation(); 15638966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek EB.addEdge(Loc, true); 15642042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 1565368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks updateStackPiecesWithMessage(p, CallStack); 1566368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 15678966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek if (const Stmt *S = Loc.asStmt()) 15681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 15698966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 15701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 157114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 15728347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 15738347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return PDB.getBugReport()->isValid(); 157414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 157514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 15765fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 15773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugType and subclasses. 15783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 1579404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios KyrtzidisBugType::~BugType() { } 1580404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 15813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugType::FlushReports(BugReporter &BR) {} 15823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 158399ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BuiltinBug::anchor() {} 158499ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 15853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 15863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReport and subclasses. 15873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 1588e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 158999ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BugReport::NodeResolver::anchor() {} 159099ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 15918e6431adab313e283a992698f6fc7afe62420999Anna Zaksvoid BugReport::addVisitor(BugReporterVisitor* visitor) { 15928e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (!visitor) 15938e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 15948e6431adab313e283a992698f6fc7afe62420999Anna Zaks 15958e6431adab313e283a992698f6fc7afe62420999Anna Zaks llvm::FoldingSetNodeID ID; 15968e6431adab313e283a992698f6fc7afe62420999Anna Zaks visitor->Profile(ID); 15978e6431adab313e283a992698f6fc7afe62420999Anna Zaks void *InsertPos; 15988e6431adab313e283a992698f6fc7afe62420999Anna Zaks 15998e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) { 16008e6431adab313e283a992698f6fc7afe62420999Anna Zaks delete visitor; 16018e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 16028e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 16038e6431adab313e283a992698f6fc7afe62420999Anna Zaks 16048e6431adab313e283a992698f6fc7afe62420999Anna Zaks CallbacksSet.InsertNode(visitor, InsertPos); 16053bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose Callbacks.push_back(visitor); 16063bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 16078e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 16088e6431adab313e283a992698f6fc7afe62420999Anna Zaks 16098e6431adab313e283a992698f6fc7afe62420999Anna ZaksBugReport::~BugReport() { 16108e6431adab313e283a992698f6fc7afe62420999Anna Zaks for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) { 1611dc757b049796949e4b11646445a6598f0bdabd7aAnna Zaks delete *I; 16128e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 1613c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek while (!interestingSymbols.empty()) { 1614c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek popInterestingSymbolsAndRegions(); 1615c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 16168e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 1617e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 161807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenekconst Decl *BugReport::getDeclWithIssue() const { 161907189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek if (DeclWithIssue) 162007189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return DeclWithIssue; 162107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 162207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek const ExplodedNode *N = getErrorNode(); 162307189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek if (!N) 162407189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return 0; 162507189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 162607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek const LocationContext *LC = N->getLocationContext(); 162707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return LC->getCurrentStackFrame()->getDecl(); 162807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek} 162907189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 1630e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaksvoid BugReport::Profile(llvm::FoldingSetNodeID& hash) const { 1631e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddPointer(&BT); 1632e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddString(Description); 163397bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks PathDiagnosticLocation UL = getUniqueingLocation(); 163497bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks if (UL.isValid()) { 163597bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks UL.Profile(hash); 1636ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks } else if (Location.isValid()) { 1637590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks Location.Profile(hash); 1638590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } else { 1639590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(ErrorNode); 1640590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode)); 1641590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } 1642e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 1643e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks for (SmallVectorImpl<SourceRange>::const_iterator I = 1644e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks Ranges.begin(), E = Ranges.end(); I != E; ++I) { 1645e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks const SourceRange range = *I; 1646e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!range.isValid()) 1647e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks continue; 1648e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getBegin().getRawEncoding()); 1649e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getEnd().getRawEncoding()); 1650e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 1651e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks} 16523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 165376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(SymbolRef sym) { 165476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!sym) 165576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return; 16563bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 16573bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // If the symbol wasn't already in our set, note a configuration change. 1658c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (getInterestingSymbols().insert(sym).second) 16593bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 16608ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose 16618ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose if (const SymbolMetadata *meta = dyn_cast<SymbolMetadata>(sym)) 1662c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek getInterestingRegions().insert(meta->getRegion()); 166376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 166476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 166576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(const MemRegion *R) { 166676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!R) 166776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return; 16683bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 16693bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // If the base region wasn't already in our set, note a configuration change. 167076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek R = R->getBaseRegion(); 1671c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (getInterestingRegions().insert(R).second) 16723bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 16738ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose 167476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 1675c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek getInterestingSymbols().insert(SR->getSymbol()); 167676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 167776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 167876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(SVal V) { 167976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek markInteresting(V.getAsRegion()); 168076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek markInteresting(V.getAsSymbol()); 168176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 168276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 168380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaksvoid BugReport::markInteresting(const LocationContext *LC) { 168480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!LC) 168580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return; 168680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks InterestingLocationContexts.insert(LC); 168780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks} 168880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 1689c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(SVal V) { 169076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return isInteresting(V.getAsRegion()) || isInteresting(V.getAsSymbol()); 169176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 169276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 1693c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(SymbolRef sym) { 169476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!sym) 169576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 16968ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose // We don't currently consider metadata symbols to be interesting 16978ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose // even if we know their region is interesting. Is that correct behavior? 1698c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return getInterestingSymbols().count(sym); 169976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 170076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 1701c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(const MemRegion *R) { 170276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!R) 170376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 170476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek R = R->getBaseRegion(); 1705c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek bool b = getInterestingRegions().count(R); 170676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (b) 170776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return true; 170876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 1709c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return getInterestingSymbols().count(SR->getSymbol()); 171076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 171176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 1712c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 171380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaksbool BugReport::isInteresting(const LocationContext *LC) { 171480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!LC) 171580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return false; 171680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return InterestingLocationContexts.count(LC); 171780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks} 171880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 1719c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::lazyInitializeInterestingSets() { 1720c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (interestingSymbols.empty()) { 1721c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.push_back(new Symbols()); 1722c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.push_back(new Regions()); 1723c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 1724c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 1725c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 1726c4bac8e376b98d633bb00ee5f510d5e58449753cTed KremenekBugReport::Symbols &BugReport::getInterestingSymbols() { 1727c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek lazyInitializeInterestingSets(); 1728c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return *interestingSymbols.back(); 1729c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 1730c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 1731c4bac8e376b98d633bb00ee5f510d5e58449753cTed KremenekBugReport::Regions &BugReport::getInterestingRegions() { 1732c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek lazyInitializeInterestingSets(); 1733c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return *interestingRegions.back(); 1734c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 1735c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 1736c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::pushInterestingSymbolsAndRegions() { 1737c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.push_back(new Symbols(getInterestingSymbols())); 1738c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.push_back(new Regions(getInterestingRegions())); 1739c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 1740c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 1741c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::popInterestingSymbolsAndRegions() { 1742c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek delete interestingSymbols.back(); 1743c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.pop_back(); 1744c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek delete interestingRegions.back(); 1745c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.pop_back(); 1746c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 174776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 17489c378f705405d37f49795d5e915989de774fe11fTed Kremenekconst Stmt *BugReport::getStmt() const { 1749e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!ErrorNode) 1750e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return 0; 1751e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 1752212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care ProgramPoint ProgP = ErrorNode->getLocation(); 17535f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek const Stmt *S = NULL; 17541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17557a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEntrance> BE = ProgP.getAs<BlockEntrance>()) { 1756fafd3834754d2093e0ad7a1c005860fd527ecb7fZhongxing Xu CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit(); 175750d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu if (BE->getBlock() == &Exit) 1758212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care S = GetPreviousStmt(ErrorNode); 17593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 17605f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (!S) 17611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump S = GetStmt(ProgP); 17621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return S; 17643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 17653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1766640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidisstd::pair<BugReport::ranges_iterator, BugReport::ranges_iterator> 1767e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna ZaksBugReport::getRanges() { 1768e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // If no custom ranges, add the range of the statement corresponding to 1769e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // the error node. 1770e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (Ranges.empty()) { 1771e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (const Expr *E = dyn_cast_or_null<Expr>(getStmt())) 1772e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks addRange(E->getSourceRange()); 1773e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks else 1774e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 1775e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 1776e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 177714924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks // User-specified absence of range info. 177814924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks if (Ranges.size() == 1 && !Ranges.begin()->isValid()) 177914924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 178014924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks 1781e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(Ranges.begin(), Ranges.end()); 17823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 17833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1784590dd8e0959d8df5621827768987c4792b74fc06Anna ZaksPathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const { 1785b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks if (ErrorNode) { 1786590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(!Location.isValid() && 1787b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks "Either Location or ErrorNode should be specified but not both."); 1788b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks 17899c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const Stmt *S = GetCurrentOrPreviousStmt(ErrorNode)) { 1790590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks const LocationContext *LC = ErrorNode->getLocationContext(); 1791590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks 17923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // For member expressions, return the location of the '.' or '->'. 17935b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) 1794590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createMemberLoc(ME, SM); 17955b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek // For binary operators, return the location of the operator. 17965b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) 1797590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createOperatorLoc(B, SM); 17983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 17997a95de68c093991047ed8d339479ccad51b88663David Blaikie if (ErrorNode->getLocation().getAs<PostStmtPurgeDeadSymbols>()) 180063bc186d6ac0b44ba4ec6fccb5f471b05c79b666Jordan Rose return PathDiagnosticLocation::createEnd(S, SM, LC); 180163bc186d6ac0b44ba4ec6fccb5f471b05c79b666Jordan Rose 1802590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation::createBegin(S, SM, LC); 18033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1804b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } else { 1805b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks assert(Location.isValid()); 1806b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks return Location; 1807b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } 1808b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks 1809590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation(); 18103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 18113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 18123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 18133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReporter and subclasses. 18143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 18153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 18164a5f724538cbc275370c9504e8169ce92503256cBenjamin KramerBugReportEquivClass::~BugReportEquivClass() { } 1817a2f4ec0df645fc249d2945beef9653f03b175417Zhongxing XuGRBugReporter::~GRBugReporter() { } 18183106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReporterData::~BugReporterData() {} 18193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 182038b02b912e1a55c912f603c4369431264d36a381Zhongxing XuExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); } 18213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 182218c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekProgramStateManager& 18233106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekGRBugReporter::getStateManager() { return Eng.getStateManager(); } 18243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 18253b030a28cda2b953758507769c1d436bec5ec45eAnna ZaksBugReporter::~BugReporter() { 18263b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks FlushReports(); 18273b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks 18283b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks // Free the bug reports we are tracking. 18293b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks typedef std::vector<BugReportEquivClass *> ContTy; 18303b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end(); 18313b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks I != E; ++I) { 18323b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks delete *I; 18333b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks } 18343b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks} 18353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 18363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugReporter::FlushReports() { 18373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (BugTypes.isEmpty()) 18383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return; 18393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 18403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // First flush the warnings for each BugType. This may end up creating new 1841404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // warnings and new BugTypes. 1842404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: Only NSErrorChecker needs BugType's FlushReports. 1843404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // Turn NSErrorChecker into a proper checker and remove this. 18445f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<const BugType*, 16> bugTypes; 18453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) 1846404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis bugTypes.push_back(*I); 18475f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVector<const BugType*, 16>::iterator 1848404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I) 18493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const_cast<BugType*>(*I)->FlushReports(*this); 18503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1851d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks // We need to flush reports in deterministic order to ensure the order 1852d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks // of the reports is consistent between runs. 18530eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks typedef std::vector<BugReportEquivClass *> ContVecTy; 18540eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks for (ContVecTy::iterator EI=EQClassesVector.begin(), EE=EQClassesVector.end(); 18550eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks EI != EE; ++EI){ 18560eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks BugReportEquivClass& EQ = **EI; 1857404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis FlushReport(EQ); 18583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 18593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1860404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // BugReporter owns and deletes only BugTypes created implicitly through 1861404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // EmitBasicReport. 1862404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: There are leaks from checkers that assume that the BugTypes they 1863404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // create will be destroyed by the BugReporter. 1864404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis for (llvm::StringMap<BugType*>::iterator 1865404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I) 1866404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis delete I->second; 1867404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 18683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Remove all references to the BugType objects. 18693baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.getEmptySet(); 18703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 18713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 18723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 18733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnostics generation. 18743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 18753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 18761efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rosenamespace { 18771efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose/// A wrapper around a report graph, which contains only a single path, and its 18781efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose/// node maps. 18791efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Roseclass ReportGraph { 18801efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rosepublic: 18811efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose OwningPtr<ExplodedGraph> Graph; 18821efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose InterExplodedGraphMap BackMap; 18831efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose ExplodedNode *ErrorNode; 18841efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose size_t Index; 18851efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose}; 18861efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 18871efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose/// A wrapper around a trimmed graph and its node maps. 18881efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Roseclass TrimmedGraph { 18891efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose InterExplodedGraphMap ForwardMap; 18901efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose InterExplodedGraphMap InverseMap; 1891a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 1892a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose typedef llvm::DenseMap<const ExplodedNode *, unsigned> PriorityMapTy; 1893a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose PriorityMapTy PriorityMap; 1894a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 18951efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose OwningPtr<ExplodedGraph> G; 1896a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose const ExplodedNode *Root; 18971efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rosepublic: 18981efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose TrimmedGraph(const ExplodedGraph *OriginalGraph, 1899a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose ArrayRef<const ExplodedNode *> Nodes); 19001efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 19011efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose void createBestReportGraph(ArrayRef<const ExplodedNode *> Nodes, 19021efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose ReportGraph &GraphWrapper) const; 1903a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 1904a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose void removeErrorNode(const ExplodedNode *Node); 19051efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose}; 19061efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 19071efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose} 19081efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 1909a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan RoseTrimmedGraph::TrimmedGraph(const ExplodedGraph *OriginalGraph, 1910a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose ArrayRef<const ExplodedNode *> Nodes) { 1911a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose // The trimmed graph is created in the body of the constructor to ensure 1912a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose // that the DenseMaps have been initialized already. 1913a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose G.reset(OriginalGraph->trim(Nodes, &ForwardMap, &InverseMap)); 19141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the (first) error node in the trimmed graph. We just need to consult 19161efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose // the node map which maps from nodes in the original graph to nodes 19173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // in the new graph. 1918a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose std::queue<std::pair<const ExplodedNode *, unsigned> > WS; 19191efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose typedef llvm::SmallDenseMap<const ExplodedNode *, size_t, 32> IndexMapTy; 1920a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose IndexMapTy IndexMap(llvm::NextPowerOf2(Nodes.size() + 1)); 19213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 19221efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose for (unsigned i = 0, count = Nodes.size(); i < count; ++i) { 19231efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose const ExplodedNode *OriginalNode = Nodes[i]; 19241efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose if (const ExplodedNode *N = ForwardMap.lookup(OriginalNode)) { 1925a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose WS.push(std::make_pair(N, 0)); 19261efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose IndexMap[OriginalNode] = i; 19273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 192840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 19291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1930938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(!WS.empty() && "No error node found in the trimmed graph."); 19313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 1932a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose // Perform a reverse BFS to find all the shortest paths. 1933a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose Root = 0; 19343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!WS.empty()) { 1935a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose const ExplodedNode *Node; 1936a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose unsigned Priority; 1937a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose llvm::tie(Node, Priority) = WS.front(); 19383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek WS.pop(); 19391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1940a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose PriorityMapTy::iterator I = PriorityMap.find(Node); 1941a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose if (I != PriorityMap.end()) { 1942a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose assert(I->second <= Priority); 19433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 1944a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose } 19451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1946a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose PriorityMap[Node] = Priority; 19471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1948a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose if (Node->pred_empty()) 19493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Root = Node; 19501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1951a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose for (ExplodedNode::const_pred_iterator I = Node->pred_begin(), 1952a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose E = Node->pred_end(); 1953a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose I != E; ++I) 1954a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose WS.push(std::make_pair(*I, Priority + 1)); 19553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 1956a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 1957938332c657390d1e782e0adc03b092993edae962Ted Kremenek assert(Root); 1958a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose} 1959a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 1960a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rosevoid TrimmedGraph::createBestReportGraph(ArrayRef<const ExplodedNode *> Nodes, 1961a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose ReportGraph &GraphWrapper) const { 1962a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose assert(!GraphWrapper.Graph && "ReportGraph is already in use"); 1963a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose assert(GraphWrapper.BackMap.empty() && "ReportGraph is already in use"); 1964a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 1965a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose // Find the (first) error node in the trimmed graph. We just need to consult 1966a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose // the node map which maps from nodes in the original graph to nodes 1967a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose // in the new graph. 1968a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose std::queue<std::pair<const ExplodedNode *, unsigned> > WS; 1969a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose typedef llvm::SmallDenseMap<const ExplodedNode *, size_t, 32> IndexMapTy; 1970a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose IndexMapTy IndexMap(llvm::NextPowerOf2(Nodes.size() + 1)); 1971a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 1972a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose for (unsigned i = 0, count = Nodes.size(); i < count; ++i) { 1973a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose const ExplodedNode *OriginalNode = Nodes[i]; 1974a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose if (const ExplodedNode *N = ForwardMap.lookup(OriginalNode)) { 1975a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose WS.push(std::make_pair(N, 0)); 1976a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose IndexMap[OriginalNode] = i; 1977a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose } 1978a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose } 1979a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 1980a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose assert(!WS.empty() && "No error node found in the trimmed graph."); 1981a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 1982a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose // Create a new graph with a single path. This is the graph 1983a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose // that will be returned to the caller. 1984a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose ExplodedGraph *GNew = new ExplodedGraph(); 1985a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose GraphWrapper.Graph.reset(GNew); 19861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now walk from the root down the BFS path, always taking the successor 19883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // with the lowest number. 19891efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose ExplodedNode *Last = 0; 1990c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu for ( const ExplodedNode *N = Root ;;) { 19913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Lookup the number associated with the current node. 1992a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose PriorityMapTy::const_iterator I = PriorityMap.find(N); 1993a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose assert(I != PriorityMap.end()); 19941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the equivalent node in the new graph with the same state 19963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // and location. 19979c378f705405d37f49795d5e915989de774fe11fTed Kremenek ExplodedNode *NewN = GNew->getNode(N->getLocation(), N->getState()); 19981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Store the mapping to the original node. 20001efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose InterExplodedGraphMap::const_iterator IMitr = InverseMap.find(N); 20013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(IMitr != InverseMap.end() && "No mapping to original node."); 20021efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose GraphWrapper.BackMap[NewN] = IMitr->second; 20031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Link up the new node with the previous node. 20053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Last) 20065fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek NewN->addPredecessor(Last, *GNew); 20071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Last = NewN; 20091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Are we at the final node? 20111efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose IndexMapTy::iterator IMI = IndexMap.find(IMitr->second); 2012938332c657390d1e782e0adc03b092993edae962Ted Kremenek if (IMI != IndexMap.end()) { 20131efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose GraphWrapper.ErrorNode = NewN; 20141efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose GraphWrapper.Index = IMI->second; 20153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 20163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 20171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the next successor node. We choose the node that is marked 20193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // with the lowest DFS number. 20201efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose unsigned MinVal = -1U; 20211efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose for (ExplodedNode::const_succ_iterator SI = N->succ_begin(), 20221efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose SE = N->succ_end(); 20231efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose SI != SE; ++SI) { 2024a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose I = PriorityMap.find(*SI); 20251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2026a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose if (I == PriorityMap.end()) 20273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 20281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20291efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose if (I->second < MinVal) { 20303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek N = *SI; 20313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MinVal = I->second; 20323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 20333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 20341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20351efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose assert(MinVal != -1U); 20363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 20373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 2038d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 2039a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rosevoid TrimmedGraph::removeErrorNode(const ExplodedNode *ErrorNode) { 2040a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose ErrorNode = ForwardMap[ErrorNode]; 2041a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose assert(ErrorNode && "not an error node"); 2042a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 2043a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose PriorityMapTy::iterator PriorityEntry = PriorityMap.find(ErrorNode); 2044a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose assert(PriorityEntry != PriorityMap.end() && "error node already removed"); 2045a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose PriorityMap.erase(PriorityEntry); 2046a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 2047a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose std::queue<const ExplodedNode *> WS; 2048a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose for (ExplodedNode::const_pred_iterator PI = ErrorNode->pred_begin(), 2049a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose PE = ErrorNode->pred_end(); 2050a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose PI != PE; ++PI) { 2051a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose assert(PriorityMap.find(*PI) != PriorityMap.end()); 2052a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose WS.push(*PI); 2053a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose } 2054a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 2055a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose // Update all nodes possibly affected by this change. 2056a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose while (!WS.empty()) { 2057a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose const ExplodedNode *N = WS.front(); 2058a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose WS.pop(); 2059a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 2060a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose unsigned MinPriority = -1U; 2061a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose for (ExplodedNode::const_succ_iterator SI = N->succ_begin(), 2062a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose SE = N->succ_end(); 2063a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose SI != SE; ++SI) { 2064a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose PriorityMapTy::iterator SuccEntry = PriorityMap.find(*SI); 2065a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose if (SuccEntry == PriorityMap.end()) 2066a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose continue; 2067a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose MinPriority = std::min(SuccEntry->second, MinPriority); 2068a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose } 2069a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 2070a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose if (MinPriority == -1U) 2071a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose PriorityMap.erase(N); 2072a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose else if (PriorityMap[N] == MinPriority + 1) 2073a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose continue; 2074a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose else 2075a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose PriorityMap[N] = MinPriority + 1; 2076a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 2077a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose for (ExplodedNode::const_pred_iterator PI = N->pred_begin(), 2078a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose PE = N->pred_end(); 2079a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose PI != PE; ++PI) { 2080a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose assert(PriorityMap.find(*PI) != PriorityMap.end()); 2081a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose WS.push(*PI); 2082a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose } 2083a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose } 2084a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose} 2085a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 2086a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 20873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object 20883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// and collapses PathDiagosticPieces that are expanded by macros. 208977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) { 20902042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek typedef std::vector<std::pair<IntrusiveRefCntPtr<PathDiagnosticMacroPiece>, 20912042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek SourceLocation> > MacroStackTy; 20921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2093c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith typedef std::vector<IntrusiveRefCntPtr<PathDiagnosticPiece> > 20943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy; 20951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStackTy MacroStack; 20973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy Pieces; 20981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 209977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek for (PathPieces::const_iterator I = path.begin(), E = path.end(); 21002042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek I!=E; ++I) { 210177d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 210277d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek PathDiagnosticPiece *piece = I->getPtr(); 210377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 210477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek // Recursively compact calls. 210577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek if (PathDiagnosticCallPiece *call=dyn_cast<PathDiagnosticCallPiece>(piece)){ 210677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek CompactPathDiagnostic(call->path, SM); 210777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek } 210877d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 21093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Get the location of the PathDiagnosticPiece. 211077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek const FullSourceLoc Loc = piece->getLocation().asLocation(); 21111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine the instantiation location, which is the location we group 21133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // related PathDiagnosticPieces. 21141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation InstantiationLoc = Loc.isMacroID() ? 2115402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 21163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 21171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Loc.isFileID()) { 21193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.clear(); 212077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek Pieces.push_back(piece); 21213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 21223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 2123706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek 21243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(Loc.isMacroID()); 21251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Is the PathDiagnosticPiece within the same macro group? 21273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) { 212877d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek MacroStack.back().first->subPieces.push_back(piece); 21293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 21303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 2131d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 21323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // We aren't in the same group. Are we descending into a new macro 21333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // or are part of an old one? 2134c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith IntrusiveRefCntPtr<PathDiagnosticMacroPiece> MacroGroup; 2135d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 21363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ? 2137402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 21383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 21391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Walk the entire macro stack. 21413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!MacroStack.empty()) { 21423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (InstantiationLoc == MacroStack.back().second) { 21433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 21443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 21453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 21461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (ParentInstantiationLoc == MacroStack.back().second) { 21483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 21493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 215061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 21511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.pop_back(); 21536837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek } 21541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) { 21563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create a new macro group and add it to the stack. 2157590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticMacroPiece *NewGroup = 2158590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks new PathDiagnosticMacroPiece( 215977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek PathDiagnosticLocation::createSingleLocation(piece->getLocation())); 21605a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek 21613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (MacroGroup) 2162802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek MacroGroup->subPieces.push_back(NewGroup); 21633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 21643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(InstantiationLoc.isFileID()); 21653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Pieces.push_back(NewGroup); 21663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 21671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = NewGroup; 21693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc)); 21707dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 21713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 21723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Finally, add the PathDiagnosticPiece to the group. 217377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek MacroGroup->subPieces.push_back(piece); 21743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 21751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now take the pieces and construct a new PathDiagnostic. 217777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek path.clear(); 21781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 217977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) 218077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek path.push_back(*I); 218161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 218261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 21838347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosebool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, 2184c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticConsumer &PC, 2185c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek ArrayRef<BugReport *> &bugReports) { 218640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek assert(!bugReports.empty()); 21878347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 21889a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose bool HasValid = false; 21892f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose SmallVector<const ExplodedNode *, 32> errorNodes; 2190c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (ArrayRef<BugReport*>::iterator I = bugReports.begin(), 21919a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose E = bugReports.end(); I != E; ++I) { 21929a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose if ((*I)->isValid()) { 21939a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose HasValid = true; 21949a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose errorNodes.push_back((*I)->getErrorNode()); 21959a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose } else { 21969a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose errorNodes.push_back(0); 21979a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose } 219840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 21991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 22009a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose // If all the reports have been marked invalid by a previous path generation, 22019a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose // we're done. 22029a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose if (!HasValid) 22039a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose return false; 22049a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose 22052f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose typedef PathDiagnosticConsumer::PathGenerationScheme PathGenerationScheme; 22062f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose PathGenerationScheme ActiveScheme = PC.getGenerationScheme(); 22072f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 22081efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose TrimmedGraph TrimG(&getGraph(), errorNodes); 22091efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 22102f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose for (size_t Remaining = bugReports.size(); Remaining > 0; --Remaining) { 22112f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Construct a new graph that contains only a single path from the error 22122f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // node to a root. 22131efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose ReportGraph ErrorGraph; 22141efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose TrimG.createBestReportGraph(errorNodes, ErrorGraph); 22152f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 22162f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Find the BugReport with the original location. 22171efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose assert(ErrorGraph.Index < bugReports.size()); 22181efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose BugReport *R = bugReports[ErrorGraph.Index]; 22192f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert(R && "No original report found for sliced graph."); 22202f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert(R->isValid() && "Report selected by trimmed graph marked invalid."); 22212f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 22222f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Don't try to reuse this report if it ends up being suppressed. 22231efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose errorNodes[ErrorGraph.Index] = 0; 22242f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 22252f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Start building the path diagnostic... 22261efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose PathDiagnosticBuilder PDB(*this, R, ErrorGraph.BackMap, &PC); 22271efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose const ExplodedNode *N = ErrorGraph.ErrorNode; 22282f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 22292f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Register additional node visitors. 22302f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose R->addVisitor(new NilReceiverBRVisitor()); 22312f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose R->addVisitor(new ConditionBRVisitor()); 22322f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose R->addVisitor(new LikelyFalsePositiveSuppressionBRVisitor()); 22332f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 22342f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose BugReport::VisitorList visitors; 22352f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose unsigned origReportConfigToken, finalReportConfigToken; 22362f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 22372f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // While generating diagnostics, it's possible the visitors will decide 22382f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // new symbols and regions are interesting, or add other visitors based on 22392f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // the information they find. If they do, we need to regenerate the path 22402f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // based on our new report configuration. 22412f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose do { 22422f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Get a clean copy of all the visitors. 22432f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose for (BugReport::visitor_iterator I = R->visitor_begin(), 22442f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose E = R->visitor_end(); I != E; ++I) 22452f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose visitors.push_back((*I)->clone()); 22462f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 22472f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Clear out the active path from any previous work. 22482f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose PD.resetPath(); 22492f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose origReportConfigToken = R->getConfigurationChangeToken(); 22502f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 22512f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Generate the very last diagnostic piece - the piece is visible before 22522f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // the trace is expanded. 22532f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose PathDiagnosticPiece *LastPiece = 0; 22542f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end(); 22552f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose I != E; ++I) { 22562f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) { 22572f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert (!LastPiece && 22582f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose "There can only be one final piece in a diagnostic."); 22592f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose LastPiece = Piece; 22602f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose } 22613bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose } 226286ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks 22632f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (ActiveScheme != PathDiagnosticConsumer::None) { 22642f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (!LastPiece) 22652f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R); 22662f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert(LastPiece); 2267d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose PD.setEndOfPath(LastPiece); 22688347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose } 22692f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 22702f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose switch (ActiveScheme) { 22712f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose case PathDiagnosticConsumer::Extensive: 22722f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose GenerateExtensivePathDiagnostic(PD, PDB, N, visitors); 22732f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose break; 22742f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose case PathDiagnosticConsumer::Minimal: 22752f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose GenerateMinimalPathDiagnostic(PD, PDB, N, visitors); 22762f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose break; 22772f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose case PathDiagnosticConsumer::None: 22782f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose GenerateVisitorsOnlyPathDiagnostic(PD, PDB, N, visitors); 22792f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose break; 2280d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose } 22813bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 22822f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Clean up the visitors we used. 22832f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose llvm::DeleteContainerPointers(visitors); 22843bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 22852f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Did anything change while generating this path? 22862f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose finalReportConfigToken = R->getConfigurationChangeToken(); 22872f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose } while (finalReportConfigToken != origReportConfigToken); 22883bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 2289a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose if (!R->isValid()) { 2290a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose TrimG.removeErrorNode(R->getErrorNode()); 22912f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose continue; 2292a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose } 2293b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 22942f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Finally, prune the diagnostic path of uninteresting stuff. 22952f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (!PD.path.empty()) { 22962f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Remove messages that are basically the same. 22972f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose removeRedundantMsgs(PD.getMutablePieces()); 22982f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 22992f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (R->shouldPrunePath() && 23002f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose getEngine().getAnalysisManager().options.shouldPrunePaths()) { 23012f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose bool stillHasNotes = RemoveUnneededCalls(PD.getMutablePieces(), R); 23022f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert(stillHasNotes); 23032f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose (void)stillHasNotes; 23042f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose } 23052f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 23062f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose adjustCallLocations(PD.getMutablePieces()); 2307b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 2308afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 23092f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // We found a report and didn't suppress it. 23102f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose return true; 2311ed7948b55fa4b2505f240cc5287137f451172b4cTed Kremenek } 23128347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 23132f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // We suppressed all the reports in this equivalence class. 23142f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose return false; 23153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 23161aa44c7c9198796085b77c6bdd7c90030845a688Ted Kremenek 2317cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::Register(BugType *BT) { 23183baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.add(BugTypes, BT); 231976d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek} 232076d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek 2321785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rosevoid BugReporter::emitReport(BugReport* R) { 2322cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // Compute the bug report's hash to determine its equivalence class. 2323cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek llvm::FoldingSetNodeID ID; 2324cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek R->Profile(ID); 23251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 23261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Lookup the equivance class. If there isn't one, create it. 2327cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek BugType& BT = R->getBugType(); 2328cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek Register(&BT); 2329cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek void *InsertPos; 2330404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos); 23311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2332cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek if (!EQ) { 2333cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ = new BugReportEquivClass(R); 2334404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis EQClasses.InsertNode(EQ, InsertPos); 23353b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks EQClassesVector.push_back(EQ); 2336cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek } 2337cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek else 2338cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ->AddReport(R); 233961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 234061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 234106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 234206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 234306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek// Emitting reports in equivalence classes. 234406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 234506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 234606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremeneknamespace { 2347ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamstruct FRIEC_WLItem { 234806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *N; 234906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek ExplodedNode::const_succ_iterator I, E; 235006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 235106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek FRIEC_WLItem(const ExplodedNode *n) 235206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek : N(n), I(N->succ_begin()), E(N->succ_end()) {} 235306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek}; 235406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek} 235506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 235661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenekstatic BugReport * 235761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted KremenekFindReportInEquivalenceClass(BugReportEquivClass& EQ, 23585f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<BugReport*> &bugReports) { 235961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 236006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end(); 236106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(I != E); 23624a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer BugType& BT = I->getBugType(); 236361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 236440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // If we don't need to suppress any of the nodes because they are 236540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // post-dominated by a sink, simply add all the nodes in the equivalence class 236640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // to 'Nodes'. Any of the reports will serve as a "representative" report. 236761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!BT.isSuppressOnSink()) { 23684a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer BugReport *R = I; 236961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) { 23709c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N = I->getErrorNode(); 237161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (N) { 23724a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer R = I; 237340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek bugReports.push_back(R); 237461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 237561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 237606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek return R; 237761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 237861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 237906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // For bug reports that should be suppressed when all paths are post-dominated 238006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // by a sink node, iterate through the reports in the equivalence class 238106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // until we find one that isn't post-dominated (if one exists). We use a 238206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // DFS traversal of the ExplodedGraph to find a non-sink node. We could write 238306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // this as a recursive function, but we don't want to risk blowing out the 238406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // stack for very long paths. 238540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = 0; 238661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 238706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; I != E; ++I) { 23884a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer const ExplodedNode *errorNode = I->getErrorNode(); 238906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 239040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!errorNode) 239106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 239240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->isSink()) { 2393b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable( 239406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek "BugType::isSuppressSink() should not be 'true' for sink end nodes"); 239506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 239661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // No successors? By definition this nodes isn't post-dominated by a sink. 239740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->succ_empty()) { 23984a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer bugReports.push_back(I); 239940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 24004a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer exampleReport = I; 240161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek continue; 240261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 240361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 240406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // At this point we know that 'N' is not a sink and it has at least one 240506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // successor. Use a DFS worklist to find a non-sink end-of-path node. 240606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek typedef FRIEC_WLItem WLItem; 24075f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<WLItem, 10> DFSWorkList; 240806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek llvm::DenseMap<const ExplodedNode *, unsigned> Visited; 240906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 241006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek DFSWorkList WL; 241140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek WL.push_back(errorNode); 241240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek Visited[errorNode] = 1; 241306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 241406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek while (!WL.empty()) { 241506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WLItem &WI = WL.back(); 241606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(!WI.N->succ_empty()); 241706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 241806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; WI.I != WI.E; ++WI.I) { 241906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *Succ = *WI.I; 242006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // End-of-path node? 242106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (Succ->succ_empty()) { 242261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // If we found an end-of-path node that is not a sink. 242361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!Succ->isSink()) { 24244a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer bugReports.push_back(I); 242540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 24264a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer exampleReport = I; 242761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek WL.clear(); 242861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek break; 242961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 243006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Found a sink? Continue on to the next successor. 243106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 243206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 243306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Mark the successor as visited. If it hasn't been explored, 243406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // enqueue it to the DFS worklist. 243506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek unsigned &mark = Visited[Succ]; 243606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (!mark) { 243706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek mark = 1; 243806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.push_back(Succ); 243906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek break; 244006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 244106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 244261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 244361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // The worklist may have been cleared at this point. First 244461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // check if it is empty before checking the last item. 244561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!WL.empty() && &WL.back() == &WI) 244606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.pop_back(); 244706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 244806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 244906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 245061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // ExampleReport will be NULL if all the nodes in the equivalence class 245161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // were post-dominated by sinks. 245240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek return exampleReport; 245361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek} 2454e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 2455cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::FlushReport(BugReportEquivClass& EQ) { 24565f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BugReport*, 10> bugReports; 245740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports); 2458c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (exampleReport) { 2459c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek const PathDiagnosticConsumers &C = getPathDiagnosticConsumers(); 2460c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (PathDiagnosticConsumers::const_iterator I=C.begin(), 2461c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek E=C.end(); I != E; ++I) { 2462c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek FlushReport(exampleReport, **I, bugReports); 2463c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 2464c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 2465c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 2466c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2467c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReporter::FlushReport(BugReport *exampleReport, 2468c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticConsumer &PD, 2469c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek ArrayRef<BugReport*> bugReports) { 24701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2471cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // FIXME: Make sure we use the 'R' for the path that was actually used. 24721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Probably doesn't make a difference in practice. 247340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugType& BT = exampleReport->getBugType(); 24741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 24756f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<PathDiagnostic> 247607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek D(new PathDiagnostic(exampleReport->getDeclWithIssue(), 247707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek exampleReport->getBugType().getName(), 24783a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose exampleReport->getDescription(), 24793a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose exampleReport->getShortDescription(/*Fallback=*/false), 248097bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks BT.getCategory(), 248197bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks exampleReport->getUniqueingLocation(), 248297bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks exampleReport->getUniqueingDecl())); 2483d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek 2484cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose MaxBugClassSize = std::max(bugReports.size(), 2485cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose static_cast<size_t>(MaxBugClassSize)); 2486cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose 2487c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // Generate the full path diagnostic, using the generation scheme 2488d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // specified by the PathDiagnosticConsumer. Note that we have to generate 2489d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // path diagnostics even for consumers which do not support paths, because 2490d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // the BugReporterVisitors may mark this bug as a false positive. 2491d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!bugReports.empty()) 2492d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!generatePathDiagnostic(*D.get(), PD, bugReports)) 2493d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return; 24943148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek 2495cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose MaxValidBugClassSize = std::max(bugReports.size(), 2496cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose static_cast<size_t>(MaxValidBugClassSize)); 2497cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose 2498c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // If the path is empty, generate a single step path with the location 2499c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // of the issue. 2500802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek if (D->path.empty()) { 2501c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticLocation L = exampleReport->getLocation(getSourceManager()); 2502c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticPiece *piece = 2503c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek new PathDiagnosticEventPiece(L, exampleReport->getDescription()); 2504c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek BugReport::ranges_iterator Beg, End; 2505c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek llvm::tie(Beg, End) = exampleReport->getRanges(); 250607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek for ( ; Beg != End; ++Beg) 250707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek piece->addRange(*Beg); 25083a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose D->setEndOfPath(piece); 25093148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek } 25101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2511c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // Get the meta data. 2512c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek const BugReport::ExtraTextList &Meta = exampleReport->getExtraText(); 2513c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (BugReport::ExtraTextList::const_iterator i = Meta.begin(), 2514c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek e = Meta.end(); i != e; ++i) { 2515c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek D->addMeta(*i); 2516c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 2517c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2518c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PD.HandlePathDiagnostic(D.take()); 251961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 252057202071e477530e9348bc76671ee369b2399b92Ted Kremenek 252107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenekvoid BugReporter::EmitBasicReport(const Decl *DeclWithIssue, 252207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek StringRef name, 25235f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category, 2524590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks StringRef str, PathDiagnosticLocation Loc, 25258c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek SourceRange* RBeg, unsigned NumRanges) { 25261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2527404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // 'BT' is owned by BugReporter. 2528404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = getBugTypeForName(name, category); 2529590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks BugReport *R = new BugReport(*BT, str, Loc); 253007189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek R->setDeclWithIssue(DeclWithIssue); 2531cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg); 2532785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose emitReport(R); 2533cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek} 2534404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 25355f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerBugType *BugReporter::getBugTypeForName(StringRef name, 25365f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category) { 2537f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<136> fullDesc; 2538404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::raw_svector_ostream(fullDesc) << name << ":" << category; 2539404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::StringMapEntry<BugType *> & 2540404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry = StrBugTypes.GetOrCreateValue(fullDesc); 2541404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = entry.getValue(); 2542404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis if (!BT) { 2543404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BT = new BugType(name, category); 2544404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry.setValue(BT); 2545404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis } 2546404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis return BT; 2547404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis} 2548